View Javadoc

1   package com.ozacc.mail.impl;
2   
3   import java.io.UnsupportedEncodingException;
4   import java.util.Iterator;
5   import java.util.Map;
6   
7   import javax.activation.DataHandler;
8   import javax.activation.DataSource;
9   import javax.mail.MessagingException;
10  import javax.mail.internet.InternetAddress;
11  import javax.mail.internet.MimeBodyPart;
12  import javax.mail.internet.MimeMessage;
13  import javax.mail.internet.MimeMultipart;
14  import javax.mail.internet.MimePart;
15  import javax.mail.internet.MimeUtility;
16  
17  import com.ozacc.mail.Mail;
18  
19  /***
20   * MimeMessageインスタンスを生成するクラス。
21   * 
22   * @since 1.0
23   * @author Tomohiro Otsuka
24   * @version $Id: MimeMessageBuilder.java,v 1.11.2.1 2005/01/21 22:14:26 otsuka Exp $
25   */
26  public class MimeMessageBuilder {
27  
28  	private MimeMessage mimeMessage;
29  
30  	private String charset = Mail.JIS_CHARSET;
31  
32  	private boolean hasRecipient = false;
33  
34  	/***
35  	 * コンストラクタ。
36  	 * デフォルトの文字コード ISO-2022-JP がエンコーディングに使用されます。
37  	 * 
38  	 * @param mimeMessage
39  	 */
40  	public MimeMessageBuilder(MimeMessage mimeMessage) {
41  		this.mimeMessage = mimeMessage;
42  	}
43  
44  	/***
45  	 * コンストラクタ。
46  	 * 本文や件名のエンコーディングに使用する文字コードを指定します。
47  	 * 
48  	 * @param mimeMessage
49  	 * @param charset エンコーディングに使用する文字コード
50  	 */
51  	public MimeMessageBuilder(MimeMessage mimeMessage, String charset) {
52  		this.mimeMessage = mimeMessage;
53  		this.charset = charset;
54  	}
55  
56  	/***
57  	 * コンストラクタの引数で渡されたMimeMessageをそのまま返します。
58  	 * 
59  	 * @return MimeMessage
60  	 */
61  	public MimeMessage getMimeMessage() {
62  		return this.mimeMessage;
63  	}
64  
65  	/***
66  	 * 指定されたメールからMimeMessageを生成します。
67  	 * 
68  	 * @param mail MimeMessageのソースとなるMail
69  	 * @throws MessagingException
70  	 * @throws UnsupportedEncodingException
71  	 */
72  	public void buildMimeMessage(Mail mail) throws UnsupportedEncodingException, MessagingException {
73  
74  		setTo(mail);
75  
76  		setCc(mail);
77  
78  		setBcc(mail);
79  
80  		// 宛先の指定がない場合エラー
81  		if (!hasRecipient) {
82  			throw new MessagingException("宛先の指定がありません。To、Cc、Bccのいずれか一つは指定する必要があります。");
83  		}
84  
85  		setFrom(mail);
86  
87  		setSubject(mail);
88  
89  		setReplyTo(mail);
90  
91  		setXHeaders(mail);
92  
93  		setImportance(mail);
94  
95  		if (mail.isMultipartMail()) {
96  
97  			if (!mail.isFileAttached() && mail.isHtmlMail()) { // Plain text, HTML
98  
99  				if (mail.getText() != null && mail.getText().length() > 0) { // Plain text, HTML
100 
101 					MimeMultipart textAndHtmlMultipart = new MimeMultipart("alternative");
102 					setPlainText(mail, textAndHtmlMultipart);
103 					setHtmlText(mail, textAndHtmlMultipart);
104 					this.mimeMessage.setContent(textAndHtmlMultipart);
105 
106 				} else { // HTML Only マルチパートは使用しない
107 
108 					setHtmlText(mail.getHtmlText(), this.mimeMessage);
109 
110 				}
111 
112 			} else if (mail.isFileAttached() && mail.isHtmlMail()) { // Plain text, HMTL, File
113 
114 				MimeMultipart textAndHtmlMultipart = new MimeMultipart("alternative");
115 				setPlainText(mail, textAndHtmlMultipart);
116 				setHtmlText(mail, textAndHtmlMultipart);
117 
118 				MimeMultipart containingMultipart = new MimeMultipart();
119 				MimeBodyPart textBodyPart = createMimeBodyPart(containingMultipart);
120 				textBodyPart.setContent(textAndHtmlMultipart);
121 				setAttachmentFiles(mail, containingMultipart);
122 
123 				this.mimeMessage.setContent(containingMultipart);
124 
125 			} else if (mail.isFileAttached() && !mail.isHtmlMail()) { // Plain text, File
126 
127 				MimeMultipart textAndFileMultipart = new MimeMultipart();
128 				setPlainText(mail, textAndFileMultipart);
129 				setAttachmentFiles(mail, textAndFileMultipart);
130 				this.mimeMessage.setContent(textAndFileMultipart);
131 
132 			} else { // Plain text only マルチパートは使用しない
133 
134 				setText(mail.getText(), this.mimeMessage);
135 
136 			}
137 
138 		} else {
139 
140 			setText(mail.getText(), this.mimeMessage);
141 
142 		}
143 
144 	}
145 
146 	/***
147 	 * 
148 	 * @since 1.1
149 	 * 
150 	 * @param mail
151 	 * @param mimeMultipart
152 	 * @throws MessagingException
153 	 * @throws UnsupportedEncodingException 
154 	 */
155 	private void setAttachmentFiles(Mail mail, MimeMultipart mimeMultipart)
156 																			throws MessagingException,
157 																			UnsupportedEncodingException {
158 		Mail.AttachmentFile[] files = mail.getAttachmentFiles();
159 		for (int i = 0; i < files.length; i++) {
160 			MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
161 			Mail.AttachmentFile attachmentFile = files[i];
162 			addAttachment(attachmentFile.getName(), attachmentFile.getDataSource(), bodyPart);
163 		}
164 	}
165 
166 	/***
167 	 * 
168 	 * @since 1.1
169 	 * 
170 	 * @param mail
171 	 * @param mimeMultipart
172 	 * @throws MessagingException 
173 	 */
174 	private void setHtmlText(Mail mail, MimeMultipart mimeMultipart) throws MessagingException {
175 		if (mail.isHtmlMail()) {
176 			MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
177 			setHtmlText(mail.getHtmlText(), bodyPart);
178 		}
179 	}
180 
181 	/***
182 	 * 
183 	 * @since 1.1
184 	 * 
185 	 * @param mail
186 	 * @param mimeMultipart
187 	 * @throws MessagingException 
188 	 */
189 	private void setPlainText(Mail mail, MimeMultipart mimeMultipart) throws MessagingException {
190 		if (mail.getText() != null && mail.getText().length() > 0) {
191 			MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
192 			setText(mail.getText(), bodyPart);
193 		}
194 	}
195 
196 	/***
197 	 * 新しいMimeBodyPartインスタンスを生成し、指定されたMimeMultipartに登録します。
198 	 * 
199 	 * このメソッドはマルチパートメール生成時にのみ呼び出すことができます。
200 	 * プレーンテキストメール生成時には、mimeMulipartがnullなので、
201 	 * NullPointerExceptionがスローされます。
202 	 * 
203 	 * @since 1.1
204 	 * 
205 	 * @param mm
206 	 * @return 生成されたMimeBodyPart
207 	 * @throws MessagingException 
208 	 */
209 	private MimeBodyPart createMimeBodyPart(MimeMultipart mm) throws MessagingException {
210 		MimeBodyPart bodyPart = new MimeBodyPart();
211 		mm.addBodyPart(bodyPart);
212 		return bodyPart;
213 	}
214 
215 	/***
216 	 * @since 1.1
217 	 * 
218 	 * @param htmlText
219 	 * @param mimePart 
220 	 * @throws MessagingException
221 	 */
222 	private void setHtmlText(final String htmlText, MimePart mimePart) throws MessagingException {
223 		if (charset != null) {
224 			mimePart.setContent(htmlText, "text/html; charset=" + charset);
225 		} else {
226 			mimePart.setContent(htmlText, "text/html");
227 		}
228 		mimePart.setHeader("Content-Transfer-Encoding", "7bit");
229 	}
230 
231 	/***
232 	 * @param mail 
233 	 * @throws MessagingException
234 	 */
235 	private void setXHeaders(Mail mail) throws MessagingException {
236 		Map headers = mail.getHeaders();
237 		if (headers == null) {
238 			return;
239 		}
240 
241 		Iterator itr = headers.keySet().iterator();
242 		while (itr.hasNext()) {
243 			String key = (String)itr.next();
244 			String value = (String)headers.get(key);
245 			mimeMessage.setHeader(key, value);
246 		}
247 	}
248 
249 	/***
250 	 * @param mail 
251 	 * @throws MessagingException
252 	 */
253 	private void setImportance(Mail mail) throws MessagingException {
254 		if (mail.getImportance() != null) {
255 			mimeMessage.setHeader("Importance", mail.getImportance());
256 
257 			int level = 3;
258 			if (Mail.Importance.HIGH.equals(mail.getImportance())) {
259 				level = 1;
260 			} else if (Mail.Importance.LOW.equals(mail.getImportance())) {
261 				level = 5;
262 			}
263 			mimeMessage.setHeader("X-Priority", String.valueOf(level));
264 		}
265 	}
266 
267 	/***
268 	 * @param mail 
269 	 * @throws MessagingException
270 	 */
271 	private void setReplyTo(Mail mail) throws MessagingException {
272 		if (mail.getReplyTo() != null) {
273 			mimeMessage.setReplyTo(new InternetAddress[] { mail.getReplyTo() });
274 		}
275 	}
276 
277 	/***
278 	 * @param mail 
279 	 * @throws MessagingException
280 	 */
281 	private void setBcc(Mail mail) throws MessagingException {
282 		if (mail.getBcc().length > 0) {
283 			mimeMessage.setRecipients(MimeMessage.RecipientType.BCC, mail.getBcc());
284 			hasRecipient = true;
285 		}
286 	}
287 
288 	/***
289 	 * @param mail 
290 	 * @throws MessagingException
291 	 */
292 	private void setCc(Mail mail) throws MessagingException {
293 		if (mail.getCc().length > 0) {
294 			mimeMessage.setRecipients(MimeMessage.RecipientType.CC, mail.getCc());
295 			hasRecipient = true;
296 		}
297 	}
298 
299 	/***
300 	 * @param mail 
301 	 * @throws MessagingException
302 	 */
303 	private void setTo(Mail mail) throws MessagingException {
304 		if (mail.getTo().length > 0) {
305 			mimeMessage.setRecipients(MimeMessage.RecipientType.TO, mail.getTo());
306 			hasRecipient = true;
307 		}
308 	}
309 
310 	/***
311 	 * 本文をセット。
312 	 * <p>
313 	 * NOTE: 本文の最後に改行がないとMozilla系のメーラーで最終行の日本語が文字化けしてしまう為、
314 	 * message.setTextの引数で最後に\nを追加している。
315 	 * 
316 	 * @since 1.1
317 	 * 
318 	 * @param text 本文
319 	 * @param mimePart 本文をセットするMimePart 
320 	 * @throws MessagingException
321 	 */
322 	private void setText(String text, MimePart mimePart) throws MessagingException {
323 		if (charset != null) {
324 			if (charset.equalsIgnoreCase(Mail.JIS_CHARSET)) {
325 				// Cp932クラスを使用して、怪しい記号を強制的にJIS変換
326 				mimePart.setText(Cp932.toJIS(text) + "\n", charset);
327 			} else {
328 				mimePart.setText(text + "\n", charset);
329 			}
330 		} else {
331 			mimePart.setText(text + "\n");
332 		}
333 		mimePart.setHeader("Content-Transfer-Encoding", "7bit");
334 	}
335 
336 	/***
337 	 * @param mail
338 	 * @throws MessagingException
339 	 * @throws UnsupportedEncodingException
340 	 */
341 	private void setSubject(Mail mail) throws UnsupportedEncodingException, MessagingException {
342 		if (charset != null) {
343 			if (charset.equalsIgnoreCase(Mail.JIS_CHARSET)) {
344 				String subject = Cp932.toJIS(mail.getSubject());
345 				mimeMessage.setSubject(MimeUtility.encodeText(subject, charset, "B"));
346 			} else {
347 				mimeMessage.setSubject(mail.getSubject(), charset);
348 			}
349 		} else {
350 			mimeMessage.setSubject(mail.getSubject());
351 		}
352 	}
353 
354 	/***
355 	 * @param mail
356 	 * @throws MessagingException 
357 	 */
358 	private void setFrom(Mail mail) throws MessagingException {
359 		mimeMessage.setFrom(mail.getFrom());
360 	}
361 
362 	/***
363 	 * 添付ファイルデータを指定されたMimeBodyPartにセットします。
364 	 * 
365 	 * @since 1.1
366 	 * 
367 	 * @param fileName
368 	 * @param dataSource
369 	 * @param mimeBodyPart ファイルデータをセットするMimeBodyPart
370 	 * @throws UnsupportedEncodingException
371 	 * @throws MessagingException
372 	 */
373 	private void addAttachment(String fileName, DataSource dataSource, MimeBodyPart mimeBodyPart)
374 																									throws UnsupportedEncodingException,
375 																									MessagingException {
376 		if (charset != null) {
377 			// ファイル名のエンコード
378 			mimeBodyPart.setFileName(MimeUtility.encodeText(fileName, charset, "B"));
379 		} else {
380 			mimeBodyPart.setFileName(fileName);
381 		}
382 
383 		mimeBodyPart.setDataHandler(new DataHandler(dataSource));
384 	}
385 
386 }