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 2004/09/20 20:12:54 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.getXHeaders();
    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 }