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インスタンスを生成するクラス。Mail一通毎に生成されます。
21 *
22 * @since 1.0
23 * @author Tomohiro Otsuka
24 * @version $Id: MimeMessageBuilder.java,v 1.11.2.2 2007/03/30 13:03:44 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 setCharset(mail);
74
75 setTo(mail);
76 setCc(mail);
77 setBcc(mail);
78
79 if (!hasRecipient) {
80 throw new MessagingException("宛先の指定がありません。To、Cc、Bccのいずれか一つは指定する必要があります。");
81 }
82 setFrom(mail);
83 setSubject(mail);
84 setReplyTo(mail);
85 setXHeaders(mail);
86 setImportance(mail);
87
88 if (mail.isMultipartMail()) {
89
90 if (!mail.isFileAttached() && mail.isHtmlMail()) {
91
92 if (mail.getText() != null && mail.getText().length() > 0) {
93
94 MimeMultipart textAndHtmlMultipart = new MimeMultipart("alternative");
95 setPlainText(mail, textAndHtmlMultipart);
96 setHtmlText(mail, textAndHtmlMultipart);
97 this.mimeMessage.setContent(textAndHtmlMultipart);
98
99 } else {
100
101 setHtmlText(mail.getHtmlText(), this.mimeMessage);
102
103 }
104
105 } else if (mail.isFileAttached() && mail.isHtmlMail()) {
106
107 MimeMultipart textAndHtmlMultipart = new MimeMultipart("alternative");
108 setPlainText(mail, textAndHtmlMultipart);
109 setHtmlText(mail, textAndHtmlMultipart);
110
111 MimeMultipart containingMultipart = new MimeMultipart();
112 MimeBodyPart textBodyPart = createMimeBodyPart(containingMultipart);
113 textBodyPart.setContent(textAndHtmlMultipart);
114 setAttachmentFiles(mail, containingMultipart);
115
116 this.mimeMessage.setContent(containingMultipart);
117
118 } else if (mail.isFileAttached() && !mail.isHtmlMail()) {
119
120 MimeMultipart textAndFileMultipart = new MimeMultipart();
121 setPlainText(mail, textAndFileMultipart);
122 setAttachmentFiles(mail, textAndFileMultipart);
123 this.mimeMessage.setContent(textAndFileMultipart);
124
125 } else {
126
127 setText(mail.getText(), this.mimeMessage);
128
129 }
130
131 } else {
132
133 setText(mail.getText(), this.mimeMessage);
134
135 }
136
137 }
138
139 /***
140 * メールに使用するcharsetを決定します。
141 * Mail#charsetが設定されている場合、その値が優先されます。
142 *
143 * @since 1.2.1
144 * @param mail
145 */
146 private void setCharset(Mail mail) {
147 if (mail.getCharset() != null && !"".equals(mail.getCharset())) {
148 charset = mail.getCharset();
149 }
150 }
151
152 /***
153 *
154 * @since 1.1
155 *
156 * @param mail
157 * @param mimeMultipart
158 * @throws MessagingException
159 * @throws UnsupportedEncodingException
160 */
161 private void setAttachmentFiles(Mail mail, MimeMultipart mimeMultipart)
162 throws MessagingException,
163 UnsupportedEncodingException {
164 Mail.AttachmentFile[] files = mail.getAttachmentFiles();
165 for (int i = 0; i < files.length; i++) {
166 MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
167 Mail.AttachmentFile attachmentFile = files[i];
168 addAttachment(attachmentFile.getName(), attachmentFile.getDataSource(), bodyPart);
169 }
170 }
171
172 /***
173 *
174 * @since 1.1
175 *
176 * @param mail
177 * @param mimeMultipart
178 * @throws MessagingException
179 */
180 private void setHtmlText(Mail mail, MimeMultipart mimeMultipart) throws MessagingException {
181 if (mail.isHtmlMail()) {
182 MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
183 setHtmlText(mail.getHtmlText(), bodyPart);
184 }
185 }
186
187 /***
188 *
189 * @since 1.1
190 *
191 * @param mail
192 * @param mimeMultipart
193 * @throws MessagingException
194 */
195 private void setPlainText(Mail mail, MimeMultipart mimeMultipart) throws MessagingException {
196 if (mail.getText() != null && mail.getText().length() > 0) {
197 MimeBodyPart bodyPart = createMimeBodyPart(mimeMultipart);
198 setText(mail.getText(), bodyPart);
199 }
200 }
201
202 /***
203 * 新しいMimeBodyPartインスタンスを生成し、指定されたMimeMultipartに登録します。
204 *
205 * このメソッドはマルチパートメール生成時にのみ呼び出すことができます。
206 * プレーンテキストメール生成時には、mimeMulipartがnullなので、
207 * NullPointerExceptionがスローされます。
208 *
209 * @since 1.1
210 *
211 * @param mm
212 * @return 生成されたMimeBodyPart
213 * @throws MessagingException
214 */
215 private MimeBodyPart createMimeBodyPart(MimeMultipart mm) throws MessagingException {
216 MimeBodyPart bodyPart = new MimeBodyPart();
217 mm.addBodyPart(bodyPart);
218 return bodyPart;
219 }
220
221 /***
222 * @since 1.1
223 *
224 * @param htmlText
225 * @param mimePart
226 * @throws MessagingException
227 */
228 private void setHtmlText(final String htmlText, MimePart mimePart) throws MessagingException {
229 if (charset != null) {
230 mimePart.setContent(htmlText, "text/html; charset=" + charset);
231 } else {
232 mimePart.setContent(htmlText, "text/html");
233 }
234 setContentTransferEncoding(mimePart);
235 }
236
237 /***
238 * @param mail
239 * @throws MessagingException
240 */
241 private void setXHeaders(Mail mail) throws MessagingException {
242 Map headers = mail.getHeaders();
243 if (headers == null) {
244 return;
245 }
246
247 Iterator itr = headers.keySet().iterator();
248 while (itr.hasNext()) {
249 String key = (String)itr.next();
250 String value = (String)headers.get(key);
251 mimeMessage.setHeader(key, value);
252 }
253 }
254
255 /***
256 * @param mail
257 * @throws MessagingException
258 */
259 private void setImportance(Mail mail) throws MessagingException {
260 if (mail.getImportance() != null) {
261 mimeMessage.setHeader("Importance", mail.getImportance());
262
263 int level = 3;
264 if (Mail.Importance.HIGH.equals(mail.getImportance())) {
265 level = 1;
266 } else if (Mail.Importance.LOW.equals(mail.getImportance())) {
267 level = 5;
268 }
269 mimeMessage.setHeader("X-Priority", String.valueOf(level));
270 }
271 }
272
273 /***
274 * @param mail
275 * @throws MessagingException
276 * @throws UnsupportedEncodingException
277 */
278 private void setReplyTo(Mail mail) throws MessagingException, UnsupportedEncodingException {
279 if (mail.getReplyTo() != null) {
280 mimeMessage.setReplyTo(new InternetAddress[] { convertCharset(mail.getReplyTo()) });
281 }
282 }
283
284 /***
285 * @param mail
286 * @throws MessagingException
287 * @throws UnsupportedEncodingException
288 */
289 private void setBcc(Mail mail) throws MessagingException, UnsupportedEncodingException {
290 if (mail.getBcc().length > 0) {
291 mimeMessage.setRecipients(MimeMessage.RecipientType.BCC, convertCharset(mail.getBcc()));
292 hasRecipient = true;
293 }
294 }
295
296 /***
297 * @param mail
298 * @throws MessagingException
299 * @throws UnsupportedEncodingException
300 */
301 private void setCc(Mail mail) throws MessagingException, UnsupportedEncodingException {
302 if (mail.getCc().length > 0) {
303 mimeMessage.setRecipients(MimeMessage.RecipientType.CC, convertCharset(mail.getCc()));
304 hasRecipient = true;
305 }
306 }
307
308 /***
309 * @param mail
310 * @throws MessagingException
311 * @throws UnsupportedEncodingException
312 */
313 private void setTo(Mail mail) throws MessagingException, UnsupportedEncodingException {
314 if (mail.getTo().length > 0) {
315 mimeMessage.setRecipients(MimeMessage.RecipientType.TO, convertCharset(mail.getTo()));
316 hasRecipient = true;
317 }
318 }
319
320 /***
321 * 本文をセット。
322 * <p>
323 * NOTE: 本文の最後に改行がないとMozilla系のメーラーで最終行の日本語が文字化けしてしまう為、
324 * message.setTextの引数で最後に\nを追加している。
325 *
326 * @since 1.1
327 *
328 * @param text 本文
329 * @param mimePart 本文をセットするMimePart
330 * @throws MessagingException
331 */
332 private void setText(String text, MimePart mimePart) throws MessagingException {
333 if (charset != null) {
334 if (charset.equalsIgnoreCase(Mail.JIS_CHARSET)) {
335
336 mimePart.setText(Cp932.toJIS(text) + "\n", charset);
337 } else {
338 mimePart.setText(text + "\n", charset);
339 }
340 } else {
341 mimePart.setText(text + "\n");
342 }
343 setContentTransferEncoding(mimePart);
344 }
345
346 /***
347 * charsetに応じてContent-Trnasfer-Encodingを設定します。
348 * が、UTF-8の時に8bitになること以外分かりません。。。
349 *
350 * @since 1.2.1
351 * @param mimePart
352 * @throws MessagingException
353 */
354 private void setContentTransferEncoding(MimePart mimePart) throws MessagingException {
355 String contentTransferEncoding = "7bit";
356 if ("UTF-8".equalsIgnoreCase(charset)) {
357 contentTransferEncoding = "8bit";
358 }
359 mimePart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
360 }
361
362 /***
363 * @param mail
364 * @throws MessagingException
365 * @throws UnsupportedEncodingException
366 */
367 private void setSubject(Mail mail) throws UnsupportedEncodingException, MessagingException {
368 if (charset != null) {
369 if (Mail.JIS_CHARSET.equalsIgnoreCase(charset)) {
370 String subject = Cp932.toJIS(mail.getSubject());
371 mimeMessage.setSubject(MimeUtility.encodeText(subject, charset, "B"));
372 } else {
373 mimeMessage.setSubject(mail.getSubject(), charset);
374 }
375 } else {
376 mimeMessage.setSubject(mail.getSubject());
377 }
378 }
379
380 /***
381 * @param mail
382 * @throws MessagingException
383 * @throws UnsupportedEncodingException
384 */
385 private void setFrom(Mail mail) throws MessagingException, UnsupportedEncodingException {
386 InternetAddress address = convertCharset(mail.getFrom());
387 mimeMessage.setFrom(address);
388 }
389
390 private InternetAddress convertCharset(InternetAddress address)
391 throws UnsupportedEncodingException {
392 String name = address.getPersonal();
393 if (name != null && !"".equals(name) && Mail.JIS_CHARSET.equalsIgnoreCase(charset)) {
394 name = Cp932.toJIS(name);
395 }
396 return new InternetAddress(address.getAddress(), name, charset);
397 }
398
399 private InternetAddress[] convertCharset(InternetAddress[] addresses)
400 throws UnsupportedEncodingException {
401 for (int i = 0; i < addresses.length; i++) {
402 addresses[i] = convertCharset(addresses[i]);
403 }
404 return addresses;
405 }
406
407 /***
408 * 添付ファイルデータを指定されたMimeBodyPartにセットします。
409 *
410 * @since 1.1
411 *
412 * @param fileName
413 * @param dataSource
414 * @param mimeBodyPart ファイルデータをセットするMimeBodyPart
415 * @throws UnsupportedEncodingException
416 * @throws MessagingException
417 */
418 private void addAttachment(String fileName, DataSource dataSource, MimeBodyPart mimeBodyPart)
419 throws UnsupportedEncodingException,
420 MessagingException {
421 if (charset != null) {
422
423 mimeBodyPart.setFileName(MimeUtility.encodeText(fileName, charset, "B"));
424 } else {
425 mimeBodyPart.setFileName(fileName);
426 }
427
428 mimeBodyPart.setDataHandler(new DataHandler(dataSource));
429 }
430
431 }