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.6 2004/11/25 08:00:16 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
74 /***
75 * @see com.ozacc.mail.fetch.FetchMailPro#connect()
76 */
77 public synchronized void connect() throws MailException {
78 log.debug(protocol.toUpperCase() + "サーバ[" + host + "]に接続します。");
79
80 Session session = Session.getInstance(createProperties(), null);
81 if (javaMailLogEnabled) {
82 session.setDebug(true);
83 }
84
85 try {
86 store = session.getStore(protocol);
87 } catch (NoSuchProviderException e) {
88 log.error("指定されたプロトコル[" + protocol + "]はサポートされていません。", e);
89 throw new MailException("指定されたプロトコル[" + protocol + "]はサポートされていません。", e);
90 }
91
92 try {
93 store.connect(host, port, username, password);
94 } catch (AuthenticationFailedException e) {
95 log.error(protocol.toUpperCase() + "サーバ[" + host + "]への接続認証に失敗しました。", e);
96 throw new MailAuthenticationException(protocol.toUpperCase() + "サーバ[" + host
97 + "]への接続認証に失敗しました。", e);
98 } catch (MessagingException e) {
99 log.error(protocol.toUpperCase() + "サーバ[" + host + "]への接続に失敗しました。", e);
100 throw new MailException(protocol.toUpperCase() + "サーバ[" + host + "]への接続に失敗しました。", e);
101 }
102
103 log.info(protocol.toUpperCase() + "サーバ[" + host + "]に接続しました。");
104
105 changeFolder(INBOX_NAME);
106 }
107
108 /***
109 * Sessionに渡すPropertiesインスタンスを返します。
110 * APOP認証を行う場合に、"mail.pop3.apop.enable"をセットします。
111 *
112 * @return Sessionに渡すPropertiesインスタンス
113 */
114 private Properties createProperties() {
115 Properties prop = new Properties();
116 if ("apop".equalsIgnoreCase(protocol)) {
117 prop.put("mail.pop3.apop.enable", "true");
118 }
119 return prop;
120 }
121
122 /***
123 * @see com.ozacc.mail.fetch.FetchMailPro#disconnect()
124 */
125 public synchronized void disconnect() throws MailException {
126 closeCurrentFolderIfOpen();
127 log.debug(protocol.toUpperCase() + "サーバ[" + host + "]との接続を切断します。");
128 try {
129 store.close();
130 store = null;
131 } catch (MessagingException e) {
132 throw new MailException("サーバ[" + host + "]との接続切断に失敗しました。", e);
133 }
134 log.info(protocol.toUpperCase() + "サーバ[" + host + "]との接続を切断しました。");
135 }
136
137 /***
138 * 現在のメッセージフォルダをクローズします。
139 *
140 * @throws MailException メッセージフォルダのクローズに失敗した場合
141 */
142 private void closeCurrentFolderIfOpen() throws MailException {
143 if (currentFolder != null && currentFolder.isOpen()) {
144 log.debug("メッセージフォルダ[" + currentFolder.getName() + "]をクローズします。");
145 try {
146 currentFolder.close(true);
147 } catch (MessagingException e) {
148 log.error("メッセージフォルダ[" + currentFolder.getName() + "]のクローズに失敗しました。", e);
149 throw new MailException("メッセージフォルダ[" + currentFolder.getName() + "]のクローズに失敗しました。",
150 e);
151 }
152 log.debug("メッセージフォルダ[" + currentFolder.getName() + "]をクローズしました。");
153 currentFolder = null;
154 }
155 }
156
157 /***
158 * @see com.ozacc.mail.fetch.FetchMailPro#changeFolder(java.lang.String)
159 */
160 public synchronized void changeFolder(String folderName) throws MailException {
161 closeCurrentFolderIfOpen();
162
163 log.debug("メッセージフォルダ[" + folderName + "]をオープンします。");
164 try {
165 currentFolder = store.getFolder(folderName);
166 currentFolder.open(Folder.READ_WRITE);
167 } catch (MessagingException e) {
168 log.error("メッセージフォルダ[" + folderName + "]のオープンに失敗しました。", e);
169 throw new MailException("メッセージフォルダ[" + folderName + "]のオープンに失敗しました。", e);
170 }
171 log.debug("メッセージフォルダ[" + folderName + "]をオープンしました。");
172 }
173
174 /***
175 * @see com.ozacc.mail.fetch.FetchMailPro#getMailCount()
176 */
177 public int getMailCount() throws MailException {
178 checkIfCurrentFolderIsOpen();
179 try {
180 return currentFolder.getMessageCount();
181 } catch (MessagingException e) {
182 throw new MailFetchException("メール数の取得に失敗しました。", e);
183 }
184 }
185
186 /***
187 * メールサーバに接続されていて、フォルダが操作できる状態かどうか調べます。
188 * フォルダが操作できる状態にない場合、NotConnectedExceptionをスローします。
189 *
190 * @throws NotConnectedException
191 */
192 private void checkIfCurrentFolderIsOpen() throws NotConnectedException {
193 if (currentFolder == null || !currentFolder.isOpen()) {
194 throw new NotConnectedException(protocol.toUpperCase() + "サーバ[" + host + "]に接続されていません。");
195 }
196 }
197
198 /***
199 * @see com.ozacc.mail.fetch.FetchMailPro#getMail(int)
200 */
201 public ReceivedMail getMail(int num) throws MailException {
202 MimeMessage mimeMessage = getMessage(num);
203 MailConverter converter = new MailConverter(mimeMessage);
204 return converter.convertIntoMails()[0];
205 }
206
207 public ReceivedMail[] getMails(boolean delete) throws MailException {
208 MimeMessage[] mimeMessages = getMessages(delete);
209 MailConverter converter = new MailConverter(mimeMessages);
210 return converter.convertIntoMails();
211 }
212
213 /***
214 * @see com.ozacc.mail.fetch.FetchMailPro#getMessage(int)
215 */
216 public MimeMessage getMessage(int num) throws MailException {
217 checkIfCurrentFolderIsOpen();
218 try {
219 return (MimeMessage)currentFolder.getMessage(num);
220 } catch (MessagingException e) {
221 log.error("メッセージの取得に失敗しました。", e);
222 throw new MailFetchException("メッセージの取得に失敗しました。", e);
223 }
224 }
225
226 public MimeMessage[] getMessages(boolean delete) throws MailException {
227 checkIfCurrentFolderIsOpen();
228 try {
229 Message[] messages = currentFolder.getMessages();
230
231 if (log.isInfoEnabled()) {
232 if (messages.length > 0) {
233 log.info(messages.length + "通のメールを受信します。");
234 } else {
235 log.info("受信するメールはありません。");
236 }
237 }
238
239
240 currentFolder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);
241
242
243 if (delete) {
244 currentFolder.setFlags(messages, new Flags(Flags.Flag.DELETED), true);
245 }
246
247 MimeMessage[] mimeMessages = new MimeMessage[messages.length];
248 for (int i = 0; i < messages.length; i++) {
249 mimeMessages[i] = (MimeMessage)messages[i];
250
251 }
252 return mimeMessages;
253 } catch (MessagingException e) {
254 log.error("メッセージの取得に失敗しました。", e);
255 throw new MailFetchException("メッセージの取得に失敗しました。", e);
256 }
257 }
258
259 /***
260 * @see com.ozacc.mail.fetch.FetchMailPro#isConnected()
261 */
262 public boolean isConnected() {
263 return store.isConnected();
264 }
265
266 /***
267 * @return Returns the host.
268 */
269 public String getHost() {
270 return host;
271 }
272
273 /***
274 * @param host The host to set.
275 */
276 public void setHost(String host) {
277 this.host = host;
278 }
279
280 /***
281 * @return 認証パスワード
282 */
283 public String getPassword() {
284 return password;
285 }
286
287 /***
288 * @param password 認証パスワード
289 */
290 public void setPassword(String password) {
291 this.password = password;
292 }
293
294 /***
295 * @return プロトコル
296 */
297 public String getProtocol() {
298 return protocol;
299 }
300
301 /***
302 * メール受信に使用するプロトコロルをセットします。
303 * 現在サポートされているプロトコルは、「pop3」と「imap」の二つです。
304 * デフォルトは「pop3」です。
305 * <p>
306 * POP3サーバへの認証をAPOPで行いたい場合は、プロトコル名ではありませんが、
307 * 「apop」を指定してください。APOP認証を使用するには、JavaMail 1.3.2以降が必要です。
308 *
309 * @param protocol プロトコル
310 */
311 public void setProtocol(String protocol) {
312 this.protocol = protocol;
313 }
314
315 /***
316 * @return 認証ユーザ名
317 */
318 public String getUsername() {
319 return username;
320 }
321
322 /***
323 * @param username 認証ユーザ名
324 */
325 public void setUsername(String username) {
326 this.username = username;
327 }
328
329 /***
330 * @return ポート番号
331 */
332 public int getPort() {
333 return port;
334 }
335
336 /***
337 * メール受信に使用するポート番号をセットします。
338 * プロトコルに応じたポート番号が自動的に使用されますので、通常ここでポート番号をセットする必要はありません。
339 *
340 * @param port ポート番号
341 */
342 public void setPort(int port) {
343 this.port = port;
344 }
345
346 /***
347 * JavaMailのデバッグが有効かどうか判定します。
348 *
349 * @return JavaMailのデバッグが有効な場合 ture
350 */
351 public boolean isJavaMailLogEnabled() {
352 return javaMailLogEnabled;
353 }
354
355 /***
356 * JavaMailのデバッグを有効にするかどうか指定します。
357 * 有効にすると、<code>System.out</code>のデバッグメッセージが出力されます。<br>
358 * デフォルトは無効になっています。
359 *
360 * @see javax.mail.session#setDebug(boolean)
361 * @param javaMailLogEnabled The javaMailLogEnabled to set.
362 */
363 public void setJavaMailLogEnabled(boolean javaMailLogEnabled) {
364 this.javaMailLogEnabled = javaMailLogEnabled;
365 }
366 }