View Javadoc

1   package com.ozacc.mail.fetch.impl;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.util.ArrayList;
6   import java.util.Date;
7   import java.util.Enumeration;
8   import java.util.List;
9   
10  import javax.mail.Address;
11  import javax.mail.Header;
12  import javax.mail.Message;
13  import javax.mail.MessagingException;
14  import javax.mail.internet.AddressException;
15  import javax.mail.internet.InternetAddress;
16  import javax.mail.internet.MimeMessage;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  import com.ozacc.mail.fetch.ReceivedMail;
22  import com.ozacc.mail.fetch.impl.sk_jp.AttachmentsExtractor;
23  import com.ozacc.mail.fetch.impl.sk_jp.HtmlPartExtractor;
24  import com.ozacc.mail.fetch.impl.sk_jp.MultipartUtility;
25  
26  /***
27   * MimeMessageからMailを生成するクラス。
28   * <p>
29   * 変換時に生じたチェック例外は、このクラス内でキャッチされ無視されます。
30   * 例外が生じた項目(差出人や宛先など)に該当するMailインスタンスのプロパティには何もセットされません。
31   * 
32   * @since 1.2
33   * @author Tomohiro Otsuka
34   * @version $Id: MailConverter.java,v 1.1.2.8 2005/01/18 07:21:20 otsuka Exp $
35   */
36  public class MailConverter {
37  
38  	private static Log log = LogFactory.getLog(MailConverter.class);
39  
40  	private MimeMessage[] messages;
41  
42  	/***
43  	 * @param mimeMessage 
44  	 */
45  	public MailConverter(MimeMessage mimeMessage) {
46  		this(new MimeMessage[] { mimeMessage });
47  	}
48  
49  	/***
50  	 * @param mimeMessages 
51  	 */
52  	public MailConverter(MimeMessage[] mimeMessages) {
53  		this.messages = mimeMessages;
54  	}
55  
56  	/***
57  	 * @return
58  	 */
59  	public ReceivedMail[] convertIntoMails() {
60  		log.debug("計" + messages.length + "通のMimeMessageをMailに変換します。");
61  		List list = new ArrayList();
62  		for (int i = 0; i < messages.length; i++) {
63  			log.debug((i + 1) + "通目のMimeMessageをMailに変換します。");
64  
65  			MimeMessage mm = messages[i];
66  			ReceivedMail mail = new ReceivedMail();
67  
68  			setReturnPath(mm, mail);
69  			setDate(mm, mail);
70  			setFromAddress(mm, mail);
71  			setRecipientAddresses(mm, mail);
72  			setMessageId(mm, mail);
73  			setReplyToAddress(mm, mail);
74  			setSubject(mm, mail);
75  			setXHeaders(mm, mail);
76  			setText(mm, mail);
77  			setHtmlText(mm, mail);
78  			setAttachmentFiles(mm, mail);
79  
80  			setSize(mm, mail);
81  
82  			mail.setMessage(mm);
83  
84  			log.debug((i + 1) + "通目のMimeMessageをMailに変換しました。");
85  			log.debug(mail.toString());
86  
87  			list.add(mail);
88  		}
89  		log.debug("計" + messages.length + "通のMimeMessageをMailに変換しました。");
90  		return (ReceivedMail[])list.toArray(new ReceivedMail[list.size()]);
91  	}
92  
93  	/***
94  	 * 指定されたMimeMessageに添付されているファイルを全て抽出し、
95  	 * 指定されたReceivedMailにセットします。
96  	 * 
97  	 * @param mm
98  	 * @param mail 
99  	 */
100 	private void setAttachmentFiles(MimeMessage mm, ReceivedMail mail) {
101 		try {
102 			AttachmentsExtractor ae = new AttachmentsExtractor(
103 					AttachmentsExtractor.MODE_IGNORE_MESSAGE
104 							| AttachmentsExtractor.MODE_IGNORE_INLINE);
105 			MultipartUtility.process(mm, ae);
106 			for (int i = 0, num = ae.getCount(); i < num; i++) {
107 				String fileName = ae.getFileName(i);
108 				InputStream is = ae.getInputStream(i);
109 				mail.addFile(is, fileName);
110 			}
111 		} catch (IOException e) {
112 			log.error("添付ファイルの取得に失敗しました。", e);
113 		} catch (MessagingException e) {
114 			// ignore
115 			log.warn(e.getMessage());
116 		}
117 	}
118 
119 	private void setXHeaders(MimeMessage mm, ReceivedMail mail) {
120 		log.debug("X-HeaderをMailにセットします。");
121 		String[] xHeaders = null;
122 		Enumeration headerEnum = null;
123 		try {
124 			headerEnum = mm.getAllHeaders();
125 		} catch (MessagingException e) {
126 			// ignore
127 			log.warn(e.getMessage());
128 		}
129 		while (headerEnum != null && headerEnum.hasMoreElements()) {
130 			Header header = (Header)headerEnum.nextElement();
131 			if (header.getName().startsWith("X-")) {
132 				mail.addXHeader(header.getName(), header.getValue());
133 			}
134 		}
135 	}
136 
137 	private void setReplyToAddress(MimeMessage mm, ReceivedMail mail) {
138 		log.debug("Reply-ToアドレスをMailにセットします。");
139 		Address[] addresses = null;
140 		try {
141 			addresses = mm.getReplyTo();
142 		} catch (MessagingException e) {
143 			// ignore
144 			log.warn(e.getMessage());
145 		}
146 		if (addresses != null) {
147 			log.debug(addresses.length + "つのReply-Toアドレスが見つかりました。最初のアドレスのみ取得されます。");
148 			for (int j = 0; j < addresses.length; j++) {
149 				Address address = addresses[j];
150 				mail.setReplyTo((InternetAddress)address);
151 				break;
152 			}
153 		} else {
154 			log.debug("Reply-Toアドレスは見つかりませんでした。");
155 		}
156 	}
157 
158 	/***
159 	 * メールの容量(byte)をMimeMessageから取得してReceivedMailにセットします。
160 	 * 取得に失敗した場合は -1 をセットします。
161 	 * 
162 	 * @param mm
163 	 * @param mail 
164 	 */
165 	private void setSize(MimeMessage mm, ReceivedMail mail) {
166 		try {
167 			mail.setSize(mm.getSize());
168 		} catch (MessagingException e) {
169 			mail.setSize(-1);
170 		}
171 	}
172 
173 	/***
174 	 * @param mm
175 	 * @param mail
176 	 * @throws MessagingException 
177 	 */
178 	private void setHtmlText(MimeMessage mm, ReceivedMail mail) {
179 		try {
180 			HtmlPartExtractor hpe = new HtmlPartExtractor();
181 			MultipartUtility.process(mm, hpe);
182 			String htmlText = hpe.getHtml();
183 			mail.setHtmlText(htmlText);
184 		} catch (MessagingException e) {
185 			// ignore
186 			log.warn(e.getMessage());
187 		}
188 	}
189 
190 	private void setText(MimeMessage mm, ReceivedMail mail) {
191 		try {
192 			String text = MultipartUtility.getPlainText(mm);
193 			mail.setText(text);
194 		} catch (MessagingException e) {
195 			// ignore
196 			log.warn(e.getMessage());
197 		}
198 	}
199 
200 	private void setMessageId(MimeMessage mm, ReceivedMail mail) {
201 		try {
202 			String messageId = mm.getMessageID();
203 			mail.setMessageId(messageId);
204 		} catch (MessagingException e) {
205 			// ignore
206 			log.warn(e.getMessage());
207 		}
208 	}
209 
210 	private void setSubject(MimeMessage mm, ReceivedMail mail) {
211 		try {
212 			String subject = mm.getSubject();
213 			mail.setSubject(subject);
214 		} catch (MessagingException e) {
215 			// ignore
216 			log.warn(e.getMessage());
217 		}
218 	}
219 
220 	private void setDate(MimeMessage mm, ReceivedMail mail) {
221 		try {
222 			Date d = mm.getSentDate();
223 			mail.setDate(d);
224 		} catch (MessagingException e) {
225 			// ignore
226 			log.warn(e.getMessage());
227 		}
228 	}
229 
230 	/***
231 	 * Return-Pathアドレスは必ずしもセットされてはいません。
232 	 * 特にspam系のメールでは不正なフォーマットのメールアドレスが
233 	 * セットされている場合もあるので要注意。
234 	 * 
235 	 * @param mm
236 	 * @param mail
237 	 */
238 	private void setReturnPath(MimeMessage mm, ReceivedMail mail) {
239 		log.debug("Return-Pathアドレスを検出します。");
240 		String[] returnPath = null;
241 		try {
242 			returnPath = mm.getHeader("Return-Path");
243 		} catch (MessagingException e) {
244 			// ignore
245 			log.warn(e.getMessage());
246 		}
247 		if (returnPath != null && returnPath.length > 0) {
248 			String email = returnPath[0].substring(1, returnPath[0].length() - 1);
249 			if (email.length() > 0) {
250 				try {
251 					mail.setReturnPath(email);
252 					log.debug("Return-PathアドレスをMailにセットしました。[Return-Path='" + email + "']");
253 				} catch (IllegalArgumentException e) {
254 					log.warn("Return-Pathアドレスが不正なメールアドレスフォーマットです。[Return-Path='" + email + "']");
255 				}
256 			} else {
257 				log.debug("Return-Pathアドレスは見つかりませんでした。");
258 			}
259 		} else {
260 			log.debug("Return-Pathアドレスは見つかりませんでした。");
261 		}
262 	}
263 
264 	private void setFromAddress(MimeMessage mm, ReceivedMail mail) {
265 		log.debug("Fromアドレスを検出します。");
266 		Address[] addresses = null;
267 		try {
268 			addresses = mm.getFrom();
269 		} catch (MessagingException e) {
270 			// ignore
271 			log.warn(e.getMessage());
272 		}
273 		if (addresses != null) {
274 			log.debug(addresses.length + "つのFromアドレスが見つかりました。");
275 			for (int j = 0; j < addresses.length; j++) {
276 				InternetAddress address = (InternetAddress)addresses[j];
277 				mail.setFrom(address);
278 				log.debug("FromアドレスをMailにセットしました。[From='" + address.toUnicodeString() + "']");
279 			}
280 		} else {
281 			log.debug("Fromアドレスは見つかりませんでした。");
282 		}
283 	}
284 
285 	private void setRecipientAddresses(MimeMessage mm, ReceivedMail mail) {
286 		/*
287 		 * TOアドレスのパース
288 		 */
289 		log.debug("Toアドレスを検出します。");
290 		Address[] toAddresses = null;
291 		try {
292 			toAddresses = mm.getRecipients(Message.RecipientType.TO);
293 		} catch (AddressException e) {
294 			log.warn("不正なメールアドレスが検出されました。[" + e.getRef() + "]");
295 		} catch (MessagingException e) {
296 			// ignore
297 			log.warn(e.getMessage());
298 		}
299 		if (toAddresses != null) {
300 			log.debug(toAddresses.length + "つのToアドレスが見つかりました。");
301 			for (int j = 0; j < toAddresses.length; j++) {
302 				InternetAddress address = (InternetAddress)toAddresses[j];
303 				mail.addTo(address);
304 				log.debug("ToアドレスをMailにセットしました。[To='" + address.toUnicodeString() + "']");
305 			}
306 		} else {
307 			log.debug("Toアドレスは見つかりませんでした。");
308 		}
309 
310 		/*
311 		 * CCアドレスのパース
312 		 */
313 		log.debug("Ccアドレスを検出します。");
314 		Address[] ccAddresses = null;
315 		try {
316 			ccAddresses = mm.getRecipients(Message.RecipientType.CC);
317 		} catch (AddressException e) {
318 			log.warn("不正なメールアドレスが検出されました。[" + e.getRef() + "]");
319 		} catch (MessagingException e) {
320 			// ignore
321 			log.warn(e.getMessage());
322 		}
323 		if (ccAddresses != null) {
324 			log.debug(ccAddresses.length + "つのCcアドレスが見つかりました。");
325 			for (int j = 0; j < ccAddresses.length; j++) {
326 				InternetAddress address = (InternetAddress)ccAddresses[j];
327 				mail.addCc(address);
328 				log.debug("CcアドレスをMailにセットしました。[Cc='" + address.toUnicodeString() + "']");
329 			}
330 		} else {
331 			log.debug("Ccアドレスは見つかりませんでした。");
332 		}
333 	}
334 
335 }