OSDN Git Service

bb862ec86405b313d67f50a0975733a2e680f6bd
[spring-ext/ozacc-mail.git] / src / main / java / com / ozacc / mail / fetch / impl / FetchMailProImpl.java
1 package com.ozacc.mail.fetch.impl;\r
2 \r
3 import java.util.Properties;\r
4 \r
5 import javax.mail.AuthenticationFailedException;\r
6 import javax.mail.Flags;\r
7 import javax.mail.Folder;\r
8 import javax.mail.Message;\r
9 import javax.mail.MessagingException;\r
10 import javax.mail.NoSuchProviderException;\r
11 import javax.mail.Session;\r
12 import javax.mail.Store;\r
13 import javax.mail.internet.MimeMessage;\r
14 \r
15 import org.apache.commons.logging.Log;\r
16 import org.apache.commons.logging.LogFactory;\r
17 \r
18 import com.ozacc.mail.MailAuthenticationException;\r
19 import com.ozacc.mail.MailException;\r
20 import com.ozacc.mail.NotConnectedException;\r
21 import com.ozacc.mail.fetch.FetchMailPro;\r
22 import com.ozacc.mail.fetch.MailConverter;\r
23 import com.ozacc.mail.fetch.MailFetchException;\r
24 import com.ozacc.mail.fetch.ReceivedMail;\r
25 \r
26 /**\r
27  * <code>FetchMail</code>インターフェースの実装クラス。\r
28  * <p>\r
29  * このクラスのインスタンスは、インスタンス変数を用いて状態を保持するため、\r
30  * ステートレスではありません。ステートフルです。\r
31  * \r
32  * @since 1.2\r
33  * @author Tomohiro Otsuka\r
34  * @author gaku\r
35  * @version $Id: FetchMailProImpl.java,v 1.1.2.13 2005/04/10 05:22:24 otsuka Exp $\r
36  */\r
37 public class FetchMailProImpl implements FetchMailPro {\r
38 \r
39         private static Log log = LogFactory.getLog(FetchMailProImpl.class);\r
40 \r
41         /** デフォルトのSMTPサーバ。「localhost」 */\r
42         public static final String DEFAULT_HOST = "localhost";\r
43 \r
44         /** デフォルトのプロトコル。「pop3」 */\r
45         public static final String DEFAULT_PROTOCOL = "pop3";\r
46 \r
47         /**\r
48          * デフォルトのポート。「-1」<br>\r
49          * -1はプロトコルに応じた適切なポートを設定する特別な値。\r
50          */\r
51         public static final int DEFAULT_PORT = -1;\r
52 \r
53         private static final String INBOX_NAME = "INBOX";\r
54 \r
55         private String host = DEFAULT_HOST;\r
56 \r
57         private String protocol = DEFAULT_PROTOCOL;\r
58 \r
59         private int port = DEFAULT_PORT;\r
60 \r
61         private String username;\r
62 \r
63         private String password;\r
64 \r
65         private boolean javaMailLogEnabled;\r
66 \r
67         private Store store;\r
68 \r
69         private Folder currentFolder;\r
70 \r
71         /** MailConver の実装インスタンス。 */\r
72         private MailConverter mailConverter = new MailConverterImpl();\r
73 \r
74         /**\r
75          * コンストラクタ。\r
76          */\r
77         public FetchMailProImpl() {\r
78                 System.setProperty("mail.mime.multipart.ignoremissingendboundary", "true");\r
79         }\r
80 \r
81         /**\r
82          * @see com.ozacc.mail.fetch.FetchMailPro#connect()\r
83          */\r
84         public synchronized void connect() throws MailException {\r
85                 if (isConnected()) {\r
86                         log.warn("既にサーバ[" + host + "]に接続されています。再接続するには先に接続を切断する必要があります。");\r
87                         return;\r
88                 }\r
89 \r
90                 log.debug(protocol.toUpperCase() + "サーバ[" + host + "]に接続します。");\r
91                 Session session = Session.getInstance(createProperties(), null);\r
92                 if (javaMailLogEnabled) {\r
93                         session.setDebug(true);\r
94                 }\r
95                 try {\r
96                         store = session.getStore(protocol);\r
97                         store.connect(host, port, username, password);\r
98                 } catch (NoSuchProviderException e) {\r
99                         log.error("指定されたプロトコル[" + protocol + "]はサポートされていません。", e);\r
100                         throw new MailException("指定されたプロトコル[" + protocol + "]はサポートされていません。", e);\r
101                 } catch (AuthenticationFailedException e) {\r
102                         log.error(protocol.toUpperCase() + "サーバ[" + host + "]への接続認証に失敗しました。", e);\r
103                         throw new MailAuthenticationException(protocol.toUpperCase() + "サーバ[" + host\r
104                                         + "]への接続認証に失敗しました。", e);\r
105                 } catch (MessagingException e) {\r
106                         log.error(protocol.toUpperCase() + "サーバ[" + host + "]への接続に失敗しました。", e);\r
107                         throw new MailException(protocol.toUpperCase() + "サーバ[" + host + "]への接続に失敗しました。", e);\r
108                 }\r
109                 log.info(protocol.toUpperCase() + "サーバ[" + host + "]に接続しました。");\r
110 \r
111                 changeFolder(INBOX_NAME);\r
112         }\r
113 \r
114         /**\r
115          * Sessionに渡すPropertiesインスタンスを返します。\r
116          * APOP認証を行う場合に、"mail.pop3.apop.enable"をセットします。\r
117          * \r
118          * @return Sessionに渡すPropertiesインスタンス\r
119          */\r
120         private Properties createProperties() {\r
121                 Properties prop = new Properties();\r
122                 if ("apop".equalsIgnoreCase(protocol)) {\r
123                         prop.put("mail.pop3.apop.enable", "true");\r
124                 }\r
125                 return prop;\r
126         }\r
127 \r
128         /**\r
129          * @see com.ozacc.mail.fetch.FetchMailPro#disconnect()\r
130          */\r
131         public synchronized void disconnect() throws MailException {\r
132                 try {\r
133                         closeCurrentFolderIfOpen();\r
134                 } finally {\r
135                         if (isConnected()) {\r
136                                 log.debug(protocol.toUpperCase() + "サーバ[" + host + "]との接続を切断します。");\r
137                                 try {\r
138                                         store.close();\r
139                                         store = null;\r
140                                 } catch (MessagingException e) {\r
141                                         throw new MailException("サーバ[" + host + "]との接続切断に失敗しました。", e);\r
142                                 }\r
143                         }\r
144                 }\r
145                 log.info(protocol.toUpperCase() + "サーバ[" + host + "]との接続を切断しました。");\r
146         }\r
147 \r
148         /**\r
149          * 現在のメッセージフォルダをクローズします。\r
150          * \r
151          * @throws MailException メッセージフォルダのクローズに失敗した場合\r
152          */\r
153         private void closeCurrentFolderIfOpen() throws MailException {\r
154                 if (currentFolder != null && currentFolder.isOpen()) {\r
155                         log.debug("メッセージフォルダ[" + currentFolder.getName() + "]をクローズします。");\r
156                         try {\r
157                                 currentFolder.close(true);\r
158                         } catch (MessagingException e) {\r
159                                 log.error("メッセージフォルダ[" + currentFolder.getName() + "]のクローズに失敗しました。", e);\r
160                                 throw new MailException("メッセージフォルダ[" + currentFolder.getName() + "]のクローズに失敗しました。",\r
161                                                 e);\r
162                         }\r
163                         log.debug("メッセージフォルダ[" + currentFolder.getName() + "]をクローズしました。");\r
164                         currentFolder = null;\r
165                 }\r
166         }\r
167 \r
168         /**\r
169          * @see com.ozacc.mail.fetch.FetchMailPro#changeFolder(java.lang.String)\r
170          */\r
171         public synchronized void changeFolder(String folderName) throws MailException {\r
172                 if (!isConnected()) {\r
173                         log.warn("メールサーバに接続されていません。");\r
174                         return;\r
175                 }\r
176 \r
177                 closeCurrentFolderIfOpen();\r
178                 log.debug("メッセージフォルダ[" + folderName + "]をオープンします。");\r
179                 try {\r
180                         currentFolder = store.getFolder(folderName);\r
181                         currentFolder.open(Folder.READ_WRITE);\r
182                 } catch (MessagingException e) {\r
183                         log.error("メッセージフォルダ[" + folderName + "]のオープンに失敗しました。", e);\r
184                         throw new MailException("メッセージフォルダ[" + folderName + "]のオープンに失敗しました。", e);\r
185                 }\r
186                 log.debug("メッセージフォルダ[" + folderName + "]をオープンしました。");\r
187         }\r
188 \r
189         /**\r
190          * @see com.ozacc.mail.fetch.FetchMailPro#getMailCount()\r
191          */\r
192         public int getMailCount() throws MailException {\r
193                 checkIfCurrentFolderIsOpen();\r
194                 try {\r
195                         return currentFolder.getMessageCount();\r
196                 } catch (MessagingException e) {\r
197                         throw new MailFetchException("メール数の取得に失敗しました。", e);\r
198                 }\r
199         }\r
200 \r
201         /**\r
202          * メールサーバに接続されていて、フォルダが操作できる状態かどうか調べます。\r
203          * フォルダが操作できる状態にない場合、NotConnectedExceptionをスローします。\r
204          * \r
205          * @throws NotConnectedException\r
206          */\r
207         private void checkIfCurrentFolderIsOpen() throws NotConnectedException {\r
208                 if (currentFolder == null || !currentFolder.isOpen()) {\r
209                         throw new NotConnectedException(protocol.toUpperCase() + "サーバ[" + host + "]に接続されていません。");\r
210                 }\r
211         }\r
212 \r
213         /**\r
214          * @see com.ozacc.mail.fetch.FetchMailPro#getMail(int)\r
215          */\r
216         public ReceivedMail getMail(int num) throws MailException {\r
217                 return getMail(num, false);\r
218         }\r
219 \r
220         /**\r
221          * @see com.ozacc.mail.fetch.FetchMailPro#getMail(int, boolean)\r
222          */\r
223         public ReceivedMail getMail(int num, boolean delete) throws MailException {\r
224                 MimeMessage mimeMessage = getMessage(num);\r
225                 try {\r
226                         mimeMessage.setFlag(Flags.Flag.DELETED, delete);\r
227                         log.debug(num + "番目のメッセージにDELETEDフラグをセットしました。");\r
228                 } catch (MessagingException e) {\r
229                         throw new MailException("DELETEDフラグのセットに失敗しました。", e);\r
230                 }\r
231                 return mailConverter.convertIntoMail(mimeMessage);\r
232         }\r
233 \r
234         /**\r
235          * @see com.ozacc.mail.fetch.FetchMailPro#getMails(boolean)\r
236          */\r
237         public ReceivedMail[] getMails(boolean delete) throws MailException {\r
238                 MimeMessage[] mimeMessages = getMessages(delete);\r
239                 return mailConverter.convertIntoMails(mimeMessages);\r
240         }\r
241 \r
242         /**\r
243          * @see com.ozacc.mail.fetch.FetchMailPro#getMessage(int)\r
244          */\r
245         public synchronized MimeMessage getMessage(int num) throws MailException {\r
246                 checkIfCurrentFolderIsOpen();\r
247                 try {\r
248                         return (MimeMessage)currentFolder.getMessage(num);\r
249                 } catch (MessagingException e) {\r
250                         log.error("メッセージの取得に失敗しました。", e);\r
251                         throw new MailFetchException("メッセージの取得に失敗しました。", e);\r
252                 }\r
253         }\r
254 \r
255         public synchronized MimeMessage[] getMessages(boolean delete) throws MailException {\r
256                 checkIfCurrentFolderIsOpen();\r
257                 try {\r
258                         Message[] messages = currentFolder.getMessages();\r
259                         if (log.isInfoEnabled()) {\r
260                                 if (messages.length > 0) {\r
261                                         log.info(messages.length + "通のメールを受信します。");\r
262                                 } else {\r
263                                         log.info("受信するメールはありません。");\r
264                                 }\r
265                         }\r
266                         // SEENフラグを立てる\r
267                         currentFolder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);\r
268                         // DELETEDフラグを立てる\r
269                         if (delete) {\r
270                                 currentFolder.setFlags(messages, new Flags(Flags.Flag.DELETED), true);\r
271                         }\r
272                         MimeMessage[] mimeMessages = new MimeMessage[messages.length];\r
273                         for (int i = 0; i < messages.length; i++) {\r
274                                 mimeMessages[i] = (MimeMessage)messages[i];\r
275                         }\r
276                         return mimeMessages;\r
277                 } catch (MessagingException e) {\r
278                         log.error("メッセージの取得に失敗しました。", e);\r
279                         throw new MailFetchException("メッセージの取得に失敗しました。", e);\r
280                 }\r
281         }\r
282 \r
283         /**\r
284          * @see com.ozacc.mail.fetch.FetchMailPro#isConnected()\r
285          */\r
286         public boolean isConnected() {\r
287                 return store != null && store.isConnected();\r
288         }\r
289 \r
290         /**\r
291          *  メールサーバのホスト名、またはIPアドレスを返します。\r
292          * \r
293          * @return  メールサーバのホスト名、またはIPアドレス\r
294          */\r
295         public String getHost() {\r
296                 return host;\r
297         }\r
298 \r
299         /**\r
300          * メールサーバのホスト名、またはIPアドレスをセットします。\r
301          * デフォルトは localhost です。\r
302          * \r
303          * @param host メールサーバのホスト名、またはIPアドレス\r
304          */\r
305         public void setHost(String host) {\r
306                 this.host = host;\r
307         }\r
308 \r
309         /**\r
310          * メールサーバの認証パスワードを返します。\r
311          * \r
312          * @return メールサーバの認証パスワード\r
313          */\r
314         public String getPassword() {\r
315                 return password;\r
316         }\r
317 \r
318         /**\r
319          * メールサーバの認証パスワード名をセットします。\r
320          * \r
321          * @param password メールサーバの認証パスワード\r
322          */\r
323         public void setPassword(String password) {\r
324                 this.password = password;\r
325         }\r
326 \r
327         /**\r
328          * メール受信に使用するプロトコロルをセットします。\r
329          * \r
330          * @return プロトコル\r
331          */\r
332         public String getProtocol() {\r
333                 return protocol;\r
334         }\r
335 \r
336         /**\r
337          * メール受信に使用するプロトコロルをセットします。\r
338          * 現在サポートされているプロトコルは、「pop3」と「imap」の二つです。\r
339          * デフォルトは「pop3」です。\r
340          * <p>\r
341          * POP3サーバへの認証をAPOPで行いたい場合は、プロトコル名ではありませんが、\r
342          * 「apop」を指定してください。APOP認証を使用するには、JavaMail 1.3.2以降が必要です。\r
343          * \r
344          * @param protocol プロトコル\r
345          */\r
346         public void setProtocol(String protocol) {\r
347                 this.protocol = protocol;\r
348         }\r
349 \r
350         /**\r
351          * @return 認証ユーザ名\r
352          */\r
353         public String getUsername() {\r
354                 return username;\r
355         }\r
356 \r
357         /**\r
358          * メールサーバの認証ユーザ名をセットします。\r
359          * \r
360          * @param username 認証ユーザ名\r
361          */\r
362         public void setUsername(String username) {\r
363                 this.username = username;\r
364         }\r
365 \r
366         /**\r
367          * @return ポート番号\r
368          */\r
369         public int getPort() {\r
370                 return port;\r
371         }\r
372 \r
373         /**\r
374          * メール受信に使用するポート番号をセットします。\r
375          * プロトコルに応じたポート番号が自動的に使用されますので、通常ここでポート番号をセットする必要はありません。\r
376          * \r
377          * @param port ポート番号\r
378          */\r
379         public void setPort(int port) {\r
380                 this.port = port;\r
381         }\r
382 \r
383         /**\r
384          * JavaMailのデバッグが有効かどうか判定します。\r
385          * \r
386          * @return JavaMailのデバッグが有効な場合 ture\r
387          */\r
388         public boolean isJavaMailLogEnabled() {\r
389                 return javaMailLogEnabled;\r
390         }\r
391 \r
392         /**\r
393          * JavaMailのデバッグを有効にするかどうか指定します。\r
394          * 有効にすると、<code>System.out</code>のデバッグメッセージが出力されます。<br>\r
395          * デフォルトは無効になっています。\r
396          * \r
397          * @see javax.mail.session#setDebug(boolean)\r
398          * @param javaMailLogEnabled The javaMailLogEnabled to set.\r
399          */\r
400         public void setJavaMailLogEnabled(boolean javaMailLogEnabled) {\r
401                 this.javaMailLogEnabled = javaMailLogEnabled;\r
402         }\r
403 \r
404         /**\r
405          * MailConveterインターフェースの実装インスタンスをセットします。\r
406          * デフォルトでは、MailConverterImplが使用されます。\r
407          * \r
408          * @see com.ozacc.mail.fetch.MailConveter\r
409          * @see com.ozacc.mail.fetch.impl.MailConveterImpl\r
410          * @param mailConverter MailConveterインターフェースの実装インスタンス\r
411          */\r
412         public void setMailConverter(MailConverter mailConverter) {\r
413                 this.mailConverter = mailConverter;\r
414         }\r
415 }