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 * 前後に<>が付いたメッセージIDを返します。
87 *
88 * @return 前後に<>が付いたメッセージID
89 */
90 public String getMessageId() {
91 if (messageId.startsWith("<") && messageId.endsWith(">")) {
92 return messageId;
93 }
94 return "<" + messageId + ">";
95 }
96
97 /***
98 * メッセージIDを返します。前後に<>は付きません。
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
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 }