OSDN Git Service

CVS最新版の全ファイルを追加
[spring-ext/ozacc-mail.git] / src / java / com / ozacc / mail / mock / MockSendMail.java
1 package com.ozacc.mail.mock;\r
2 \r
3 import java.io.UnsupportedEncodingException;\r
4 import java.util.ArrayList;\r
5 import java.util.List;\r
6 import java.util.Properties;\r
7 \r
8 import javax.mail.MessagingException;\r
9 import javax.mail.Session;\r
10 import javax.mail.internet.InternetAddress;\r
11 import javax.mail.internet.MimeMessage;\r
12 \r
13 import com.ozacc.mail.Mail;\r
14 import com.ozacc.mail.MailBuildException;\r
15 import com.ozacc.mail.MailException;\r
16 import com.ozacc.mail.SendMail;\r
17 import com.ozacc.mail.impl.MimeMessageBuilder;\r
18 \r
19 /**\r
20  * SendMailImplクラスのMock。<br>\r
21  * 実存するSMTPサーバを設定しても、実際には送信されません。\r
22  * デバッグモードを有効にすると、メールを送信するタイミングでコンソールに送信メール内容が出力されます。\r
23  * <p>\r
24  * Mailインスタンスを addExpectedMail() にセットし verify() メソッドを実行すると、send() されたMailインスタンスと全てのプロパティ(XHeader、添付ファイルを除く)が一致しなければAssertionFailedExceptionがスローされます。\r
25  * <p>\r
26  * 例えば、send() されたMailインスタンスのFromアドレスと件名だけチェックし、その他のプロパティはチェックしたくない場合は、MockMailインスタンスを使用します。\r
27  * <pre>Mail sentMail = new Mail();\r
28  *sentMail.setFrom("from@example.com");\r
29  *sentMail.setSubject("件名");\r
30  *sentMail.addTo("to@example.com");\r
31  *sentMail.setText("動的生成される本文");\r
32  *\r
33  *Mail expectedMail = new Mail();\r
34  *expectedMail.setFrom("from@example.com");\r
35  *expectedMail.setSubject("件名");\r
36  *\r
37  *MockMail mockMail = new MockMail();\r
38  *mockMail.setFrom("from@example.com");\r
39  *mockMail.setSubject("件名");\r
40  *\r
41  *MockSendMail sendMail = new MockSendMail();\r
42  *sendMail.addExpectedMail(expectedMail);\r
43  *sendMail.send(sentMail);\r
44  *sendMail.verify(); // 失敗 AssertionFailedException\r
45  *\r
46  *sendMail = new MockSendMail();\r
47  *sendMail.addExpectedMail(mockMail);\r
48  *sendMail.send(sentMail);\r
49  *sendMail.verify(); // 成功</pre>\r
50  * <p>\r
51  * <strong>注:</strong> 添付ファイルは比較対象になりません。\r
52  * \r
53  * @since 1.0\r
54  * @author Tomohiro Otsuka\r
55  * @version $Id: MockSendMail.java,v 1.10.2.1 2004/11/25 08:01:47 otsuka Exp $\r
56  */\r
57 public class MockSendMail implements SendMail {\r
58 \r
59         /** デフォルトのプロトコル。「smtp」 */\r
60         public static final String DEFAULT_PROTOCOL = "smtp";\r
61 \r
62         /** デフォルトのポート。「-1」 */\r
63         public static final int DEFAULT_PORT = -1;\r
64 \r
65         /** デフォルトのSMTPサーバ。「localhost」 */\r
66         public static final String DEFAULT_HOST = "localhost";\r
67 \r
68         /** ISO-2022-JP */\r
69         public static final String JIS_CHARSET = "ISO-2022-JP";\r
70 \r
71         private static final String RETURN_PATH_KEY = "mail.smtp.from";\r
72 \r
73         private String protocol = DEFAULT_PROTOCOL;\r
74 \r
75         private String host = DEFAULT_HOST;\r
76 \r
77         private int port = DEFAULT_PORT;\r
78 \r
79         private String username;\r
80 \r
81         private String password;\r
82 \r
83         private String charset = JIS_CHARSET;\r
84 \r
85         private String returnPath;\r
86 \r
87         private List sentMails;\r
88 \r
89         private List mimeMessages;\r
90 \r
91         private List expectedMails;\r
92 \r
93         private boolean debug;\r
94 \r
95         /**\r
96          * コンストラクタ。\r
97          */\r
98         public MockSendMail() {\r
99                 super();\r
100                 initialize();\r
101         }\r
102 \r
103         /**\r
104          * MockSendMailインスタンスを初期化します。\r
105          */\r
106         public void initialize() {\r
107                 sentMails = new ArrayList();\r
108                 expectedMails = new ArrayList();\r
109                 mimeMessages = new ArrayList();\r
110         }\r
111 \r
112         /**\r
113          * 送信されたメールのMimeMessageインスタンスを返します。\r
114          * 送信順の配列です。\r
115          * \r
116          * @return 送信メールのMimeMessageインスタンス配列\r
117          */\r
118         public MimeMessage[] getMimeMessages() {\r
119                 return (MimeMessage[])mimeMessages.toArray(new MimeMessage[mimeMessages.size()]);\r
120         }\r
121 \r
122         /**\r
123          * 送信されたMailインスタンスを返します。送信順の配列です。\r
124          * \r
125          * @return 送信メールのMailインスタンス配列\r
126          */\r
127         public Mail[] getSentMails() {\r
128                 return (Mail[])sentMails.toArray(new Mail[sentMails.size()]);\r
129         }\r
130 \r
131         /**\r
132          * デバッグモードが有効になっているか判定します。\r
133          * \r
134          * @return Returns 有効になっている場合 true\r
135          */\r
136         public boolean isDebug() {\r
137                 return debug;\r
138         }\r
139 \r
140         /**\r
141          * デバッグモード(コンソールにログを出力)を有効にします。\r
142          * デフォルトは無効です。\r
143          * \r
144          * @param debug デバッグモードを有効にする場合 true\r
145          */\r
146         public void setDebug(boolean debug) {\r
147                 this.debug = debug;\r
148         }\r
149 \r
150         /**\r
151          * デバッグモードが有効のとき、指定されたメッセージをコンソールに出力します。\r
152          * \r
153          * @param message コンソール出力するメッセージ\r
154          */\r
155         private void debug(String message) {\r
156                 if (debug) {\r
157                         System.out.println("[" + Thread.currentThread().getName() + "] DEBUG "\r
158                                         + getClass().getName() + " - " + message);\r
159                 }\r
160         }\r
161 \r
162         /**\r
163          * \r
164          * @param expectedMail\r
165          */\r
166         public void addExpectedMail(Mail expectedMail) {\r
167                 expectedMails.add(expectedMail);\r
168         }\r
169 \r
170         /**\r
171          * \r
172          * @param expectedMails\r
173          */\r
174         public void addExpectedMail(Mail[] expectedMails) {\r
175                 for (int i = 0; i < expectedMails.length; i++) {\r
176                         addExpectedMail(expectedMails[i]);\r
177                 }\r
178         }\r
179 \r
180         /**\r
181          * \r
182          * @throws AssertionFailedException\r
183          */\r
184         public void verify() throws AssertionFailedException {\r
185                 debug("======================================================");\r
186                 debug("                      verify()                        ");\r
187                 debug("======================================================");\r
188 \r
189                 // メールの数を比較\r
190                 int numOfExpectedMails = expectedMails.size();\r
191                 int numOfSentMails = sentMails.size();\r
192                 if (numOfExpectedMails != numOfSentMails) {\r
193                         throw new AssertionFailedException("期待メール数<" + numOfExpectedMails + ">と送信メール数<"\r
194                                         + numOfSentMails + ">が一致しませんでした。");\r
195                 }\r
196 \r
197                 debug("期待メール数と送信メール数は一致しました。[" + numOfExpectedMails + "通]");\r
198 \r
199                 // メール内容を比較\r
200                 for (int i = 0; i < numOfExpectedMails; i++) {\r
201                         Mail expected = (Mail)expectedMails.get(i);\r
202                         Mail sent = (Mail)sentMails.get(i);\r
203                         debug((i + 1) + "通目のチェックを開始します。("\r
204                                         + ((expected instanceof MockMail) ? "MockMail" : "Mail") + " - Mail)");\r
205                         checkEquality(expected, sent, i + 1);\r
206                         debug((i + 1) + "通目の期待メールと送信メール内容は一致しました。");\r
207                 }\r
208 \r
209                 debug("verifyプロセスは全て成功しました。");\r
210                 debug("======================================================");\r
211         }\r
212 \r
213         /**\r
214          * @param expected\r
215          * @param sent \r
216          * @throws AssertionFailedException\r
217          */\r
218         public void checkEquality(Mail expected, Mail sent, int num) throws AssertionFailedException {\r
219                 boolean mockMode = (expected instanceof MockMail);\r
220 \r
221                 // マルチパートメールの場合\r
222                 if (expected.isMultipartMail()) {\r
223 \r
224                         // HTML\r
225                         if (!mockMode) {\r
226                                 if ((expected.getHtmlText() == null && sent.getHtmlText() != null)\r
227                                                 || (expected.getHtmlText() != null && sent.getHtmlText() == null)\r
228                                                 || (!expected.getHtmlText().equals(sent.getHtmlText()))) {\r
229                                         throwExceptioWithMessage("HTML本文", expected.getHtmlText(), sent.getHtmlText(),\r
230                                                         num);\r
231                                 }\r
232                         } else if (mockMode && expected.getHtmlText() != null) {\r
233                                 if (!expected.getHtmlText().equals(sent.getHtmlText())) {\r
234                                         throwExceptioWithMessage("HTML本文", expected.getHtmlText(), sent.getHtmlText(),\r
235                                                         num);\r
236                                 }\r
237                         }\r
238                 }\r
239 \r
240                 // Return-Path\r
241                 if (!mockMode || (mockMode && expected.getReturnPath() != null)) {\r
242                         if (expected.getReturnPath() != null && sent.getReturnPath() != null) {\r
243                                 if (!expected.getReturnPath().equals(sent.getReturnPath())) {\r
244                                         throwExceptioWithMessage("Return-Pathアドレス", expected.getReturnPath()\r
245                                                         .toUnicodeString(), sent.getReturnPath().toUnicodeString(), num);\r
246                                 }\r
247                         } else if ((expected.getReturnPath() != null && sent.getReturnPath() == null)\r
248                                         || (expected.getReturnPath() == null && sent.getReturnPath() != null)) {\r
249                                 throw new AssertionFailedException();\r
250                         }\r
251                 }\r
252 \r
253                 // From\r
254                 if (!mockMode || (mockMode && expected.getFrom() != null)) {\r
255                         if (expected.getFrom() != null && sent.getFrom() != null) {\r
256                                 if (!EqualityCheck.equals(expected.getFrom(), sent.getFrom())) {\r
257                                         throwExceptioWithMessage("Fromアドレス", expected.getFrom().toUnicodeString(), sent\r
258                                                         .getFrom().toUnicodeString(), num);\r
259                                 }\r
260                         } else if ((expected.getFrom() != null && sent.getFrom() == null)\r
261                                         || (expected.getFrom() == null && sent.getFrom() != null)) {\r
262                                 throw new AssertionFailedException();\r
263                         }\r
264                 }\r
265 \r
266                 // to\r
267                 InternetAddress[] expectedAddresses = expected.getTo();\r
268                 InternetAddress[] sentAddresses = sent.getTo();\r
269                 if (!mockMode || (mockMode && expectedAddresses.length > 0)) {\r
270                         if (expectedAddresses.length != sentAddresses.length) {\r
271                                 throwExceptioWithMessage("Toアドレス数", Integer.toString(expectedAddresses.length),\r
272                                                 Integer.toString(sentAddresses.length), num);\r
273                         }\r
274                         for (int i = 0; i < expectedAddresses.length; i++) {\r
275                                 if (!EqualityCheck.equals(expectedAddresses[i], sentAddresses[i])) {\r
276                                         throwExceptioWithMessage("Toアドレス", expectedAddresses[i].toUnicodeString(),\r
277                                                         sentAddresses[i].toUnicodeString(), num);\r
278                                 }\r
279                         }\r
280                 }\r
281 \r
282                 // cc\r
283                 expectedAddresses = expected.getCc();\r
284                 sentAddresses = sent.getCc();\r
285                 if (!mockMode || (mockMode && expectedAddresses.length > 0)) {\r
286                         if (expectedAddresses.length != sentAddresses.length) {\r
287                                 throwExceptioWithMessage("Ccアドレス数", Integer.toString(expectedAddresses.length),\r
288                                                 Integer.toString(sentAddresses.length), num);\r
289                         }\r
290                         for (int i = 0; i < expectedAddresses.length; i++) {\r
291                                 if (!EqualityCheck.equals(expectedAddresses[i], sentAddresses[i])) {\r
292                                         throwExceptioWithMessage("Ccアドレス", expectedAddresses[i].toUnicodeString(),\r
293                                                         sentAddresses[i].toUnicodeString(), num);\r
294                                 }\r
295                         }\r
296                 }\r
297 \r
298                 // bcc\r
299                 expectedAddresses = expected.getBcc();\r
300                 sentAddresses = sent.getBcc();\r
301                 if (!mockMode || (mockMode && expectedAddresses.length > 0)) {\r
302                         if (expectedAddresses.length != sentAddresses.length) {\r
303                                 throwExceptioWithMessage("Bccアドレス数", Integer.toString(expectedAddresses.length),\r
304                                                 Integer.toString(sentAddresses.length), num);\r
305                         }\r
306                         for (int i = 0; i < expectedAddresses.length; i++) {\r
307                                 if (!EqualityCheck.equals(expectedAddresses[i], sentAddresses[i])) {\r
308                                         throwExceptioWithMessage("Bccアドレス", expectedAddresses[i].toUnicodeString(),\r
309                                                         sentAddresses[i].toUnicodeString(), num);\r
310                                 }\r
311                         }\r
312                 }\r
313 \r
314                 // Reply-To\r
315                 if (!mockMode || (mockMode && expected.getReplyTo() != null)) {\r
316                         if (expected.getReplyTo() != null && sent.getReplyTo() != null) {\r
317                                 if (!EqualityCheck.equals(expected.getReplyTo(), sent.getReplyTo())) {\r
318                                         throwExceptioWithMessage("ReplyToアドレス",\r
319                                                         expected.getReplyTo().toUnicodeString(), sent.getReplyTo()\r
320                                                                         .toUnicodeString(), num);\r
321                                 }\r
322                         } else if ((expected.getReplyTo() != null && sent.getReplyTo() == null)\r
323                                         || (expected.getReplyTo() == null && sent.getReplyTo() != null)) {\r
324                                 throw new AssertionFailedException();\r
325                         }\r
326                 }\r
327 \r
328                 // 件名\r
329                 if (!mockMode || (mockMode && expected.getSubject().length() > 0)) {\r
330                         if (!expected.getSubject().equals(sent.getSubject())) {\r
331                                 throwExceptioWithMessage("件名", expected.getSubject(), sent.getSubject(), num);\r
332                         }\r
333                 }\r
334 \r
335                 // 本文\r
336                 if (!mockMode || (mockMode && expected.getText().length() > 0)) {\r
337                         if (!expected.getText().equals(sent.getText())) {\r
338                                 throwExceptioWithMessage("本文", expected.getText(), sent.getText(), num);\r
339                         }\r
340                 }\r
341 \r
342         }\r
343 \r
344         /**\r
345          * 引数の値を受けてエラーメッセージを生成し、AssertionFailedErrorをスローします。\r
346          * \r
347          * @param name 一致しなかった項目名\r
348          * @param expectedValue 期待値\r
349          * @param sentValue 実際値\r
350          * @param num N番目のメール\r
351          * @throws AssertionFailedException 生成された例外\r
352          */\r
353         protected void throwExceptioWithMessage(String name, String expectedValue, String sentValue,\r
354                                                                                         int num) throws AssertionFailedException {\r
355                 String message = num + "番目のメッセージで、「" + name + "」が一致しませんでした。期待値='" + expectedValue\r
356                                 + "', 送信値='" + sentValue + "'";\r
357 \r
358                 debug(message);\r
359                 debug("verifyプロセスは失敗しました。");\r
360                 debug("******************************************************");\r
361 \r
362                 throw new AssertionFailedException(message);\r
363         }\r
364 \r
365         /**\r
366          * @see com.ozacc.mail.SendMail#send(com.ozacc.mail.Mail)\r
367          */\r
368         public void send(Mail mail) throws MailException {\r
369                 send(new Mail[] { mail });\r
370         }\r
371 \r
372         /**\r
373          * @see com.ozacc.mail.SendMail#send(com.ozacc.mail.Mail[])\r
374          */\r
375         public void send(Mail[] mails) throws MailException {\r
376                 debug("SMTPサーバ[" + host + "]に接続するフリ。");\r
377                 debug("SMTPサーバ[" + host + "]に接続したフリ。");\r
378 \r
379                 Session session = Session.getInstance(new Properties());\r
380                 for (int i = 0; i < mails.length; i++) {\r
381 \r
382                         Mail mail = mails[i];\r
383 \r
384                         // MimeMessageを生成\r
385                         MimeMessage message = new MimeMessage(session);\r
386                         MimeMessageBuilder builder = new MimeMessageBuilder(message);\r
387                         try {\r
388                                 builder.buildMimeMessage(mail);\r
389                         } catch (UnsupportedEncodingException e) {\r
390                                 throw new MailBuildException("サポートされていない文字コードが指定されました。", e);\r
391                         } catch (MessagingException e) {\r
392                                 throw new MailBuildException("MimeMessageの生成に失敗しました。", e);\r
393                         }\r
394                         mimeMessages.add(message);\r
395 \r
396                         debug("メールを送信するフリ。");\r
397                         sentMails.add(mail);\r
398                         debug(mail.toString());\r
399                         debug("メールを送信したフリ。");\r
400                 }\r
401 \r
402                 debug("SMTPサーバ[" + host + "]との接続を切断するフリ。");\r
403                 debug("SMTPサーバ[" + host + "]との接続を切断したフリ。");\r
404         }\r
405 \r
406         /**\r
407          * @see com.ozacc.mail.SendMail#send(javax.mail.internet.MimeMessage)\r
408          */\r
409         public void send(MimeMessage mimeMessage) throws MailException {\r
410                 throw new UnsupportedOperationException("申し訳ございません。MockSendMailでは、このメソッドをサポートしていません。");\r
411         }\r
412 \r
413         /**\r
414          * @see com.ozacc.mail.SendMail#send(javax.mail.internet.MimeMessage[])\r
415          */\r
416         public void send(MimeMessage[] mimeMessages) throws MailException {\r
417                 throw new UnsupportedOperationException("申し訳ございません。MockSendMailでは、このメソッドをサポートしていません。");\r
418         }\r
419 \r
420         /**\r
421          * エンコーディングに使用する文字コードを返します。\r
422          * \r
423          * @return エンコーディングに使用する文字コード\r
424          */\r
425         public String getCharset() {\r
426                 return charset;\r
427         }\r
428 \r
429         /**\r
430          * メールの件名や本文のエンコーディングに使用する文字コードを指定します。\r
431          * デフォルトは ISO-2022-JP です。\r
432          * \r
433          * @param charset エンコーディングに使用する文字コード\r
434          */\r
435         public void setCharset(String charset) {\r
436                 this.charset = charset;\r
437         }\r
438 \r
439         /**\r
440          * セットされたSMTPサーバのホスト名、またはIPアドレスを返します。\r
441          * \r
442          * @return SMTPサーバのホスト名、またはIPアドレス\r
443          */\r
444         public String getHost() {\r
445                 return host;\r
446         }\r
447 \r
448         /**\r
449          * SMTPサーバのホスト名、またはIPアドレスをセットします。\r
450          * デフォルトは localhost です。\r
451          * \r
452          * @param host SMTPサーバのホスト名、またはIPアドレス\r
453          */\r
454         public void setHost(String host) {\r
455                 this.host = host;\r
456         }\r
457 \r
458         /**\r
459          * @return SMTPサーバ認証パスワード\r
460          */\r
461         public String getPassword() {\r
462                 return password;\r
463         }\r
464 \r
465         /**\r
466          * SMTPサーバの接続認証が必要な場合にパスワードをセットします。\r
467          * \r
468          * @param password SMTPサーバ認証パスワード\r
469          */\r
470         public void setPassword(String password) {\r
471                 this.password = password;\r
472         }\r
473 \r
474         /**\r
475          * @return SMTPサーバのポート番号\r
476          */\r
477         public int getPort() {\r
478                 return port;\r
479         }\r
480 \r
481         /**\r
482          * SMTPサーバのポート番号をセットします。\r
483          * \r
484          * @param port SMTPサーバのポート番号\r
485          */\r
486         public void setPort(int port) {\r
487                 this.port = port;\r
488         }\r
489 \r
490         /**\r
491          * @return Returns the protocol.\r
492          */\r
493         public String getProtocol() {\r
494                 return protocol;\r
495         }\r
496 \r
497         /**\r
498          * @param protocol The protocol to set.\r
499          */\r
500         public void setProtocol(String protocol) {\r
501                 this.protocol = protocol;\r
502         }\r
503 \r
504         /**\r
505          * @return Return-Pathアドレス\r
506          */\r
507         public String getReturnPath() {\r
508                 return returnPath;\r
509         }\r
510 \r
511         /**\r
512          * Return-Pathアドレスをセットします。\r
513          * \r
514          * @param returnPath Return-Pathアドレス\r
515          */\r
516         public void setReturnPath(String returnPath) {\r
517                 this.returnPath = returnPath;\r
518         }\r
519 \r
520         /**\r
521          * @return SMTPサーバ認証ユーザ名\r
522          */\r
523         public String getUsername() {\r
524                 return username;\r
525         }\r
526 \r
527         /**\r
528          * SMTPサーバの接続認証が必要な場合にユーザ名をセットします。\r
529          * \r
530          * @param username SMTPサーバ認証ユーザ名\r
531          */\r
532         public void setUsername(String username) {\r
533                 this.username = username;\r
534         }\r
535 \r
536 }