View Javadoc

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 			// SEENフラグを立てる
240 			currentFolder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);
241 
242 			// DELETEDフラグを立てる
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 }