View Javadoc

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