View Javadoc

1   package com.ozacc.mail.fetch;
2   
3   import java.io.File;
4   import java.util.ArrayList;
5   import java.util.Date;
6   import java.util.Iterator;
7   import java.util.List;
8   
9   import javax.mail.Flags;
10  import javax.mail.MessagingException;
11  import javax.mail.internet.MimeMessage;
12  
13  import com.ozacc.mail.Mail;
14  
15  /***
16   * 受信メール。
17   * <p>
18   * <code>FetchMail</code>、<code>FetchMailPro</code>の実装クラスで受信したメールが、
19   * インターネットメールとしての仕様を満たしていないヘッダ(FromやToなど)の値がセットされていた場合、
20   * そのヘッダに該当する<code>ReceivedMail</code>インスタンスのプロパティには何もセットされません。
21   * 
22   * @since 1.2
23   * @author Tomohiro Otsuka
24   * @version $Id: ReceivedMail.java,v 1.1.2.9 2005/01/23 07:13:13 otsuka Exp $
25   */
26  public class ReceivedMail extends Mail {
27  
28  	private String replySubjectPrefix = "Re: ";
29  
30  	private Date date;
31  
32  	private String messageId;
33  
34  	private int size;
35  
36  	private List receivedHeaders;
37  
38  	private MimeMessage message;
39  
40  	/***
41  	 * コンストラクタ。
42  	 */
43  	public ReceivedMail() {
44  		super();
45  	}
46  
47  	/***
48  	 * コンストラクタ。
49  	 * 
50  	 * @param charset 
51  	 */
52  	public ReceivedMail(String charset) {
53  		super(charset);
54  	}
55  
56  	/***
57  	 * コピーコンストラクタ。
58  	 * 
59  	 * @param original 
60  	 */
61  	public ReceivedMail(Mail original) {
62  		super(original);
63  	}
64  
65  	/***
66  	 * 送信日時を返します。
67  	 * <p>
68  	 * 注: メールの受信日時ではありません。
69  	 * 
70  	 * @return 送信日時
71  	 */
72  	public Date getDate() {
73  		return date;
74  	}
75  
76  	/***
77  	 * 送信日時をセットします。
78  	 * 
79  	 * @param date 送信日時
80  	 */
81  	public void setDate(Date date) {
82  		this.date = date;
83  	}
84  
85  	/***
86  	 * 前後に&lt;&gt;が付いたメッセージIDを返します。
87  	 * 
88  	 * @return 前後に&lt;&gt;が付いたメッセージID
89  	 */
90  	public String getMessageId() {
91  		if (messageId.startsWith("<") && messageId.endsWith(">")) {
92  			return messageId;
93  		}
94  		return "<" + messageId + ">";
95  	}
96  
97  	/***
98  	 * メッセージIDを返します。前後に&lt;&gt;は付きません。
99  	 * 
100 	 * @return メッセージID
101 	 */
102 	public String getMessageIdWithoutBracket() {
103 		if (messageId.startsWith("<") && messageId.endsWith(">")) {
104 			return messageId.substring(1, messageId.length() - 1);
105 		}
106 		return messageId;
107 	}
108 
109 	/***
110 	 * メッセージIDをセットします。
111 	 * 
112 	 * @param messageId メッセージID
113 	 */
114 	public void setMessageId(String messageId) {
115 		this.messageId = messageId;
116 	}
117 
118 	/***
119 	 * In-Reply-Toヘッダの値を返します。
120 	 * In-Reply-Toヘッダがない場合はnullを返します。
121 	 * 
122 	 * @return In-Reply-Toヘッダの値
123 	 */
124 	public String getInReplyTo() {
125 		return (String)headers.get("In-Reply-To");
126 	}
127 
128 	/***
129 	 * Referencesヘッダの値を返します。
130 	 * Referencesヘッダがない場合はnullを返します。
131 	 * 
132 	 * @return Referencesヘッダの値
133 	 */
134 	public String getRefereces() {
135 		return (String)headers.get("References");
136 	}
137 
138 	/***
139 	 * @return 返信時の件名に付ける接頭辞
140 	 */
141 	public String getReplySubjectPrefix() {
142 		return replySubjectPrefix;
143 	}
144 
145 	/***
146 	 * 返信時の件名に付ける接頭辞をセットします。
147 	 * デフォルトは「Re: 」。
148 	 * 
149 	 * @param replySubjectPrefix 返信時の件名に付ける接頭辞
150 	 */
151 	public void setReplySubjectPrefix(String replySubjectPrefix) {
152 		this.replySubjectPrefix = replySubjectPrefix;
153 	}
154 
155 	/***
156 	 * メール内容を出力します。<br>
157 	 * メールのソースに似たフォーマットで出力されます。
158 	 * 
159 	 * @see java.lang.Object#toString()
160 	 */
161 	public String toString() {
162 		StringBuffer buf = new StringBuffer(1000);
163 		buf.append("Mail\n");
164 		buf.append("Return-Path: ").append(returnPath).append("\n");
165 		buf.append("Message-ID: ").append(messageId).append("\n");
166 		buf.append("Date: ").append(date).append("\n");
167 		buf.append("From: ").append(from != null ? from.toUnicodeString() : null).append("\n");
168 		buf.append("To: ").append(arrayToCommaDelimitedString(to)).append("\n");
169 		buf.append("Cc: ").append(arrayToCommaDelimitedString(cc)).append("\n");
170 		buf.append("Bcc: ").append(arrayToCommaDelimitedString(bcc)).append("\n");
171 		buf.append("Reply-To: ").append(replyTo != null ? replyTo.toUnicodeString() : null).append(
172 				"\n");
173 		buf.append("Subject: ").append(subject).append("\n");
174 
175 		if (headers != null) {
176 			for (Iterator itr = headers.keySet().iterator(); itr.hasNext();) {
177 				String header = (String)itr.next();
178 				String value = (String)headers.get(header);
179 				buf.append(header).append(": ").append(value).append("\n");
180 			}
181 		}
182 
183 		buf.append("\n");
184 		buf.append(text);
185 
186 		if (htmlText != null) {
187 			buf.append("\n\n-----\n\n");
188 			buf.append(htmlText);
189 		}
190 
191 		if (isFileAttached()) {
192 			buf.append("\n\nAttachments\n");
193 			for (int i = 0, num = attachmentFiles.size(); i < num; i++) {
194 				AttachmentFile f = (AttachmentFile)attachmentFiles.get(i);
195 				buf.append("[").append(i + 1).append("] ").append(f.getName()).append("\n");
196 			}
197 		}
198 
199 		return buf.toString();
200 	}
201 
202 	/***
203 	 * @return Returns the message.
204 	 */
205 	public MimeMessage getMessage() {
206 		return message;
207 	}
208 
209 	/***
210 	 * @param message The message to set.
211 	 */
212 	public void setMessage(MimeMessage message) {
213 		this.message = message;
214 	}
215 
216 	/***
217 	 * メールサーバとの接続切断時に、このメールをメールサーバから削除します。
218 	 * 削除できるように設定ができた場合に true を返します。
219 	 * <p>
220 	 * このメソッドは、<code>FetchMailPro</code>のメソッドによって取得された
221 	 * <code>ReceivedMail</code>インスタンスでのみ有効です。
222 	 * また、<code>FetchMailPro</code>インスタンスがメールサーバに
223 	 * 接続されている状態での呼び出しのみ有効です。<br>
224 	 * これらの条件が満たされない時にこのメソッドが呼び出された場合
225 	 * false を返します。
226 	 * 
227 	 * TODO: うまく動いてない。
228 	 * 
229 	 * @see FetchMailPro
230 	 * @param delete 削除するように設定する場合 true
231 	 * @return 削除設定が正常に行われた場合 true
232 	 */
233 	public boolean setDelete(boolean delete) {
234 		if (message != null) {
235 			try {
236 				message.setFlag(Flags.Flag.DELETED, delete);
237 			} catch (MessagingException e) {
238 				return false;
239 			}
240 			return true;
241 		}
242 		return false;
243 	}
244 
245 	/***
246 	 * メールのサイズ(容量)を返します。単位はbyte。
247 	 * この値は厳密なものではないので注意してください。
248 	 * 
249 	 * @see MimeMessage#getSize()
250 	 * @return メールのサイズ(単位はbyte)
251 	 */
252 	public int getSize() {
253 		return size;
254 	}
255 
256 	/***
257 	 * メールのサイズ(容量)をセットします。単位はbyte。
258 	 * 
259 	 * @param size メールのサイズ(単位はbyte)
260 	 */
261 	public void setSize(int size) {
262 		this.size = size;
263 	}
264 
265 	/***
266 	 * 添付ファイルのFileインスタンス配列を返します。
267 	 * 添付ファイルがない場合は空の配列を返します。
268 	 * 
269 	 * @return 添付ファイルのFileインスタンス配列
270 	 */
271 	public File[] getFiles() {
272 		AttachmentFile[] aFiles = getAttachmentFiles();
273 		File[] files = new File[aFiles.length];
274 		for (int i = 0; i < aFiles.length; i++) {
275 			AttachmentFile aFile = aFiles[i];
276 			files[i] = aFile.getFile();
277 		}
278 		return files;
279 	}
280 
281 	/***
282 	 * このメールの返信メール用Mailインスタンスを生成して返します。
283 	 * <ul>
284 	 * <li>宛先(Toアドレス)には、このメールのReply-To、またはFromがセットされます。</li>
285 	 * <li>件名には、このメールの件名が大文字小文字問わず「Re:」で始まっていなければ、「Re: 」を頭に付けた件名がセットされます。「Re:」で始まっている場合には、その件名をそのままセットします。</li>
286 	 * <li>本文には、何もセットされません。</li>
287 	 * <li>このメールにMessage-IDがセットされていれば、In-Reply-Toヘッダにその値がセットされます。</li>
288 	 * <li>このメールにMessage-IDがセットされていれば、Referencesヘッダにその値が加えられます。</li>
289 	 * </ul>
290 	 * 
291 	 * @return 返信用のMailインスタンス
292 	 */
293 	public Mail reply() {
294 		Mail mail = new Mail();
295 
296 		// 宛先
297 		if (getReplyTo() != null) {
298 			mail.addTo(getReplyTo());
299 		} else {
300 			mail.addTo(getFrom());
301 		}
302 
303 		// 件名
304 		String subject = getSubject();
305 		if ((subject.length() >= 3 && !"Re:".equalsIgnoreCase(subject.substring(0, 3)))
306 				|| subject.length() < 3) {
307 			subject = replySubjectPrefix + subject;
308 		}
309 		mail.setSubject(subject);
310 
311 		// In-Reply-To, References
312 		String messageId = getMessageId();
313 		if (messageId != null && !"<>".equals(messageId)) {
314 			String references = getRefereces();
315 			if (references != null) {
316 				references = messageId + " " + references;
317 			} else if (getInReplyTo() != null) {
318 				references = messageId + " " + getInReplyTo();
319 			} else {
320 				references = messageId;
321 			}
322 			mail.addHeader("References", references);
323 			mail.addHeader("In-Reply-To", messageId);
324 		}
325 
326 		return mail;
327 	}
328 
329 	/***
330 	 * Receivedヘッダフィールドを追加します。
331 	 * 
332 	 * @param rh Receivedヘッダフィールド
333 	 */
334 	public void addReceviedHeader(ReceivedHeader rh) {
335 		if (receivedHeaders == null) {
336 			receivedHeaders = new ArrayList();
337 		}
338 		receivedHeaders.add(rh);
339 	}
340 
341 	/***
342 	 * Receivedヘッダフィールドの配列を返します。<br>
343 	 * 自分のサーバ(このメールが届いたサーバ)から送信元のメールサーバを辿る順で並んでいます。<br>
344 	 * 受信メールがReceivedヘッダフィールドを持たない、または解析できなかった場合は空の配列を返します。
345 	 * 
346 	 * @return Receivedヘッダフィールドの配列
347 	 */
348 	public ReceivedHeader[] getReceivedHeaders() {
349 		if (receivedHeaders == null) {
350 			return new ReceivedHeader[0];
351 		}
352 		return (ReceivedHeader[])receivedHeaders
353 				.toArray(new ReceivedHeader[receivedHeaders.size()]);
354 	}
355 
356 	/***
357 	 * Receviedヘッダフィールドを表すクラス。
358 	 */
359 	public static class ReceivedHeader {
360 
361 		private String from;
362 
363 		private String by;
364 
365 		/***
366 		 * @param from メールを送信したサーバのホスト名
367 		 * @param by メールを受信したサーバのホスト名
368 		 */
369 		public ReceivedHeader(String from, String by) {
370 			this.from = from;
371 			this.by = by;
372 		}
373 
374 		/***
375 		 * @see java.lang.Object#toString()
376 		 */
377 		public String toString() {
378 			return "Sent from " + from + " and received by " + by;
379 		}
380 
381 		/***
382 		 * メールを受信したサーバのホスト名を返します。
383 		 * 
384 		 * @return メールを受信したサーバのホスト名
385 		 */
386 		public String getBy() {
387 			return by;
388 		}
389 
390 		/***
391 		 * メールを送信したサーバのホスト名を返します。
392 		 * 
393 		 * @return メールを送信したサーバのホスト名
394 		 */
395 		public String getFrom() {
396 			return from;
397 		}
398 	}
399 }