1 package com.ozacc.mail.impl;
2
3 import java.io.UnsupportedEncodingException;
4 import java.util.Date;
5 import java.util.Properties;
6
7 import javax.mail.AuthenticationFailedException;
8 import javax.mail.MessagingException;
9 import javax.mail.Session;
10 import javax.mail.Transport;
11 import javax.mail.internet.MimeMessage;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15
16 import com.ozacc.mail.Mail;
17 import com.ozacc.mail.MailAuthenticationException;
18 import com.ozacc.mail.MailBuildException;
19 import com.ozacc.mail.MailException;
20 import com.ozacc.mail.MailSendException;
21 import com.ozacc.mail.NotConnectedException;
22 import com.ozacc.mail.SendMailPro;
23
24 /***
25 * SendMailProインターフェースの実装クラス。
26 *
27 * @since 1.0
28 * @author Tomohiro Otsuka
29 * @version $Id: SendMailProImpl.java,v 1.4 2004/09/21 20:54:40 otsuka Exp $
30 */
31 public class SendMailProImpl implements SendMailPro {
32
33 /*** smtp */
34 public static final String DEFAULT_PROTOCOL = "smtp";
35
36 /*** -1 */
37 public static final int DEFAULT_PORT = -1;
38
39 /*** localhost */
40 public static final String DEFAULT_HOST = "localhost";
41
42 /*** ISO-2022-JP */
43 public static final String JIS_CHARSET = "ISO-2022-JP";
44
45 private static final String RETURN_PATH_KEY = "mail.smtp.from";
46
47 private static Log log = LogFactory.getLog(SendMailProImpl.class);
48
49 private String protocol = DEFAULT_PROTOCOL;
50
51 private String host = DEFAULT_HOST;
52
53 private int port = DEFAULT_PORT;
54
55 private String username;
56
57 private String password;
58
59 private String charset = JIS_CHARSET;
60
61 private String returnPath;
62
63 private Session session = Session.getInstance(new Properties());
64
65 private Transport transport;
66
67 private boolean connected;
68
69 private String messageId;
70
71 /***
72 * コンストラクタ。
73 */
74 public SendMailProImpl() {}
75
76 /***
77 * コンストラクタ。使用す�?SMTPサーバを指定します。
78 *
79 * @param host SMTPサーバのホスト名、またはIPアド�?ス
80 */
81 public SendMailProImpl(String host) {
82 this();
83 setHost(host);
84 }
85
86 /***
87 * @see com.ozacc.mail.SendMailPro#connect()
88 */
89 public synchronized void connect() throws MailException {
90
91 putOnReturnPath(this.returnPath);
92
93 try {
94
95 log.debug("SMTPサーバ[" + host + "]に接続します。");
96
97 transport = session.getTransport(protocol);
98 transport.connect(host, port, username, password);
99 } catch (AuthenticationFailedException ex) {
100 log.error("SMTPサーバ[" + host + "]への接続認証に失敗しました。", ex);
101 throw new MailAuthenticationException(ex);
102 } catch (MessagingException ex) {
103 log.error("SMTPサーバ[" + host + "]への接続に失敗しました。", ex);
104 throw new MailSendException("SMTPサーバ[" + host + "]への接続に失敗しました。", ex);
105 }
106
107 log.debug("SMTPサーバ[" + host + "]に接続しました。");
108
109 connected = true;
110 }
111
112 /***
113 * @see com.ozacc.mail.SendMailPro#disconnect()
114 */
115 public synchronized void disconnect() throws MailException {
116 if (connected) {
117 try {
118 log.debug("SMTPサーバ[" + host + "]との接続を切断します。");
119
120
121 transport.close();
122 connected = false;
123
124 log.debug("SMTPサーバ[" + host + "]との接続を切断しました。");
125 } catch (MessagingException ex) {
126 log.error("SMTPサーバ[" + host + "]との接続切断に失敗しました。", ex);
127 throw new MailException("SMTPサーバ[" + host + "]との接続切断に失敗しました。");
128 } finally {
129
130 releaseReturnPath(false);
131 }
132 } else {
133 log.warn("SMTPサーバ[" + host + "]との接続が確立さ�?ていない状態で、接続の切断が�?クエストさ�?ました。");
134 }
135 }
136
137 /***
138 * ReturnPathをセットします。
139 *
140 * @param returnPath
141 */
142 private void putOnReturnPath(String returnPath) {
143 if (returnPath != null) {
144 session.getProperties().put(RETURN_PATH_KEY, returnPath);
145 log.debug("Return-Path[" + returnPath + "]を設定しました。");
146 }
147 }
148
149 /***
150 * ReturnPathの設定をク�?アします。
151 * <p>
152 * setGlobalReturnPathAgainがtrueに指定さ�?てい�?�?合、�?旦Return-Path設定をク�?アした後に、
153 * グ��充バ�?なReturn-Path(setReturnPath()メソッドで、このインスタンスにセットさ�?たReturn-Pathアド�?ス)を設定します。
154 * グ��充バ�?なReturn-Pathがセットさ�?ていなけ�?ばReturn-Pathはク�?アさ�?たままになります。
155 * <p>
156 * ク�?アさ�?た状態でsend()メソッドが実行さ�?�?と、Fromの値がReturn-Pathに使用さ�?ます。
157 *
158 * @param setGlobalReturnPathAgain Return-Path設定をク�?アした後、再度グ��充バ�?なReturn-Pathをセットす�?�?�? true
159 */
160 private void releaseReturnPath(boolean setGlobalReturnPathAgain) {
161 session.getProperties().remove(RETURN_PATH_KEY);
162 log.debug("Return-Path設定をク�?アしました。");
163
164 if (setGlobalReturnPathAgain && this.returnPath != null) {
165 putOnReturnPath(this.returnPath);
166 }
167 }
168
169 /***
170 * @see com.ozacc.mail.SendMailPro#send(javax.mail.internet.MimeMessage)
171 */
172 public void send(MimeMessage mimeMessage) throws MailException {
173 if (!connected) {
174 log.error("SMTPサーバへの接続が確立さ�?ていません。");
175 throw new NotConnectedException("SMTPサーバへの接続が確立さ�?ていません。");
176 }
177
178 try {
179
180 mimeMessage.setSentDate(new Date());
181 mimeMessage.saveChanges();
182
183 log.debug("メー�?を送信します。");
184 transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
185 log.debug("メー�?を送信しました。");
186 } catch (MessagingException ex) {
187 log.error("メー�?の送信に失敗しました。", ex);
188 throw new MailSendException("メー�?の送信に失敗しました。", ex);
189 }
190 }
191
192 /***
193 * @see com.ozacc.mail.SendMailPro#send(com.ozacc.mail.Mail)
194 */
195 public void send(Mail mail) throws MailException {
196 if (mail.getReturnPath() != null) {
197 sendMailWithReturnPath(mail);
198 } else {
199 sendMail(mail);
200 }
201 }
202
203 /***
204 * 指定さ�?たMailからMimeMessageを生成し、send(MimeMessage)メソッドに渡します。
205 *
206 * @param mail
207 * @throws MailException
208 */
209 private void sendMail(Mail mail) throws MailException {
210
211 MimeMessage message = createMimeMessage();
212 MimeMessageBuilder builder = new MimeMessageBuilder(message, charset);
213 try {
214 builder.buildMimeMessage(mail);
215 } catch (UnsupportedEncodingException e) {
216 throw new MailBuildException("サポートさ�?ていない文字コードが指定さ�?ました。", e);
217 } catch (MessagingException e) {
218 throw new MailBuildException("MimeMessageの生成に失敗しました。", e);
219 }
220
221 send(message);
222 }
223
224 /***
225 * 指定さ�?たMailにセットさ�?たReturn-Pathを設定して、メー�?を送信します。
226 * 同�?メソッドです。
227 *
228 * @param mail
229 * @throws MailException
230 */
231 private synchronized void sendMailWithReturnPath(Mail mail) throws MailException {
232 putOnReturnPath(mail.getReturnPath().getAddress());
233
234 sendMail(mail);
235
236 releaseReturnPath(true);
237 }
238
239 /***
240 * 新しいMimeMessageオブジェクトを生成します。
241 *
242 * @return 新しいMimeMessageオブジェクト
243 */
244 public MimeMessage createMimeMessage() {
245 if (messageId == null) {
246 return new MimeMessage(session);
247 }
248 return new OMLMimeMessage(session, messageId);
249 }
250
251 /***
252 * @return Returns the session.
253 */
254 protected Session getSession() {
255 return session;
256 }
257
258 /***
259 * エンコーディングに使用す�?文字コードを返します。
260 *
261 * @return エンコーディングに使用す�?文字コード
262 */
263 public String getCharset() {
264 return charset;
265 }
266
267 /***
268 * メー�?の�?名や本文のエンコーディングに使用す�?文字コードを指定します。
269 * デフォ�?トは ISO-2022-JP です。
270 * <p>
271 * �?本�?環境で利用す�?�?合は通�?変更す�?必要はありません。
272 *
273 * @param charset エンコーディングに使用す�?文字コード
274 */
275 public void setCharset(String charset) {
276 this.charset = charset;
277 }
278
279 /***
280 * @return Returns the host.
281 */
282 public String getHost() {
283 return host;
284 }
285
286 /***
287 * SMTPサーバのホスト名、またはIPアド�?スをセットします。
288 * デフォ�?トは localhost です。
289 *
290 * @param host SMTPサーバのホスト名、またはIPアド�?ス
291 */
292 public void setHost(String host) {
293 this.host = host;
294 }
295
296 /***
297 * @return SMTPサーバ認証パス�?ード
298 */
299 public String getPassword() {
300 return password;
301 }
302
303 /***
304 * SMTPサーバの接続認証が必要な�?合にパス�?ードをセットします。
305 *
306 * @param password SMTPサーバ認証パス�?ード
307 */
308 public void setPassword(String password) {
309 this.password = password;
310 }
311
312 /***
313 * @return SMTPサーバのポート番�?
314 */
315 public int getPort() {
316 return port;
317 }
318
319 /***
320 * SMTPサーバのポート番号をセットします。
321 *
322 * @param port SMTPサーバのポート番�?
323 */
324 public void setPort(int port) {
325 this.port = port;
326 }
327
328 /***
329 * @return Returns the protocol.
330 */
331 public String getProtocol() {
332 return protocol;
333 }
334
335 /***
336 * @param protocol The protocol to set.
337 */
338 public void setProtocol(String protocol) {
339 this.protocol = protocol;
340 }
341
342 /***
343 * @return Return-Pathアド�?ス
344 */
345 public String getReturnPath() {
346 return returnPath;
347 }
348
349 /***
350 * Return-Pathアド�?スをセットします。
351 * <p>
352 * 送信す�?Mailインスタンスに指定さ�?たFromアド�?ス以外のアド�?スをReturn-Pathとしたい�?合に使用します。
353 * ここでセットさ�?たReturn-Pathより、Mailインスタンスにセットさ�?たReturn-Pathが優先さ�?ます。
354 *
355 * @param returnPath Return-Pathアド�?ス
356 */
357 public void setReturnPath(String returnPath) {
358 this.returnPath = returnPath;
359 }
360
361 /***
362 * @return SMTPサーバ認証ユーザ名
363 */
364 public String getUsername() {
365 return username;
366 }
367
368 /***
369 * SMTPサーバの接続認証が必要な�?合にユーザ名をセットします。
370 *
371 * @param username SMTPサーバ認証ユーザ名
372 */
373 public void setUsername(String username) {
374 this.username = username;
375 }
376
377 /***
378 * 生成さ�?�?MimeMessageに付けら�?�?Message-Idヘッダのドメイン部分を指定します。<br>
379 * 指定さ�?ない�?�?(nullや空文字列の�?�?)は、JavaMailがMessage-Idヘッダを生成します。
380 * JavaMailが生成す�?「JavaMail.実行ユーザ名@ホスト名」のMessage-Idを避けたい�?合に、このメソッドを使用します。
381 * <p>
382 * messageIdプ��叢ティがセットさ�?てい�?�?合、Mailから生成さ�?�?MimeMessageのMessage-Idには
383 * <code>タイムスタンプ + ランダムに生成さ�?�?16桁の数値 + ここでセットさ�?た値</code>
384 * が使用さ�?ます。
385 * <p>
386 * 生成さ�?�?Message-Idの例。 (実際の数値部分は送信メー�?毎に変�?ります)<ul>
387 * <li>messageIdに'example.com'を指定した�?合・・・1095714924963.5619528074501343@example.com</li>
388 * <li>messageIdに'@example.com'を指定した�?合・・・1095714924963.5619528074501343@example.com (上と同じ)</li>
389 * <li>messageIdに'OML@example.com'を指定した�?合・・・1095714924963.5619528074501343.OML@example.com</li>
390 * <li>messageIdに'.OML@example.com'を指定した�?合・・・1095714924963.5619528074501343.OML@example.com (上と同じ)</li>
391 * </ul>
392 * <p>
393 * <strong>�?:</strong> このMessage-Idは<code>send(Mail)</code>か<code>send(Mail[])</code>メソッドが呼びだ�?た�?にのみ有効です。MimeMessageを直接送信す�?�?合には適用さ�?ません。
394 *
395 * @param messageId メー�?に付けら�?�?Message-Idヘッダのドメイン部分
396 * @throws IllegalArgumentException @を複数含んだ文字列を指定した�?�?
397 */
398 public void setMessageId(String messageId) {
399 if (messageId == null || messageId.length() < 1) {
400 return;
401 }
402
403 String[] parts = messageId.split("@");
404 if (parts.length > 2) {
405 throw new IllegalArgumentException("messageIdプ��叢ティに'@'を複数含むことはできません。[" + messageId
406 + "]");
407 }
408
409 this.messageId = messageId;
410 }
411 }