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