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.8 2005/01/22 12:23:14 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 getMessageIdOnly() {
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 * @return Returns the inReplyTo.
120 */
121 public String getInReplyTo() {
122 return (String)headers.get("In-Reply-To");
123 }
124
125 /***
126 * @return Returns the refereces.
127 */
128 public String getRefereces() {
129 return (String)headers.get("References");
130 }
131
132 /***
133 * @return 返信時の件名に付ける接頭辞
134 */
135 public String getReplySubjectPrefix() {
136 return replySubjectPrefix;
137 }
138
139 /***
140 * 返信時の件名に付ける接頭辞をセットします。
141 * デフォルトは「Re: 」。
142 *
143 * @param replySubjectPrefix 返信時の件名に付ける接頭辞
144 */
145 public void setReplySubjectPrefix(String replySubjectPrefix) {
146 this.replySubjectPrefix = replySubjectPrefix;
147 }
148
149 /***
150 * メール内容を出力します。<br>
151 * メールのソースに似たフォーマットで出力されます。
152 *
153 * @see java.lang.Object#toString()
154 */
155 public String toString() {
156 StringBuffer buf = new StringBuffer(1000);
157 buf.append("Mail\n");
158 buf.append("Return-Path: ").append(returnPath).append("\n");
159 buf.append("Message-ID: ").append(messageId).append("\n");
160 buf.append("Date: ").append(date).append("\n");
161 buf.append("From: ").append(from != null ? from.toUnicodeString() : null).append("\n");
162 buf.append("To: ").append(arrayToCommaDelimitedString(to)).append("\n");
163 buf.append("Cc: ").append(arrayToCommaDelimitedString(cc)).append("\n");
164 buf.append("Bcc: ").append(arrayToCommaDelimitedString(bcc)).append("\n");
165 buf.append("Reply-To: ").append(replyTo != null ? replyTo.toUnicodeString() : null).append(
166 "\n");
167 buf.append("Subject: ").append(subject).append("\n");
168
169 if (headers != null) {
170 for (Iterator itr = headers.keySet().iterator(); itr.hasNext();) {
171 String header = (String)itr.next();
172 String value = (String)headers.get(header);
173 buf.append(header).append(": ").append(value).append("\n");
174 }
175 }
176
177 buf.append("\n");
178 buf.append(text);
179
180 if (htmlText != null) {
181 buf.append("\n\n-----\n\n");
182 buf.append(htmlText);
183 }
184
185 if (isFileAttached()) {
186 buf.append("\n\nAttachments\n");
187 for (int i = 0, num = attachmentFiles.size(); i < num; i++) {
188 AttachmentFile f = (AttachmentFile)attachmentFiles.get(i);
189 buf.append("[").append(i + 1).append("] ").append(f.getName()).append("\n");
190 }
191 }
192
193 return buf.toString();
194 }
195
196 /***
197 * @return Returns the message.
198 */
199 public MimeMessage getMessage() {
200 return message;
201 }
202
203 /***
204 * @param message The message to set.
205 */
206 public void setMessage(MimeMessage message) {
207 this.message = message;
208 }
209
210 /***
211 * メールサーバとの接続切断時に、このメールをメールサーバから削除します。
212 * 削除できるように設定ができた場合に true を返します。
213 * <p>
214 * このメソッドは、<code>FetchMailPro</code>のメソッドによって取得された
215 * <code>ReceivedMail</code>インスタンスでのみ有効です。
216 * また、<code>FetchMailPro</code>インスタンスがメールサーバに
217 * 接続されている状態での呼び出しのみ有効です。<br>
218 * これらの条件が満たされない時にこのメソッドが呼び出された場合
219 * false を返します。
220 *
221 * TODO: うまく動いてない。
222 *
223 * @see FetchMailPro
224 * @param delete 削除するように設定する場合 true
225 * @return 削除設定が正常に行われた場合 true
226 */
227 public boolean setDelete(boolean delete) {
228 if (message != null) {
229 try {
230 message.setFlag(Flags.Flag.DELETED, delete);
231 } catch (MessagingException e) {
232 return false;
233 }
234 return true;
235 }
236 return false;
237 }
238
239 /***
240 * メールのサイズ(容量)を返します。単位はbyte。
241 * この値は厳密なものではないので注意してください。
242 *
243 * @see MimeMessage#getSize()
244 * @return メールのサイズ(単位はbyte)
245 */
246 public int getSize() {
247 return size;
248 }
249
250 /***
251 * メールのサイズ(容量)をセットします。単位はbyte。
252 *
253 * @param size メールのサイズ(単位はbyte)
254 */
255 public void setSize(int size) {
256 this.size = size;
257 }
258
259 /***
260 * 添付ファイルのFileインスタンス配列を返します。
261 * 添付ファイルがない場合は空の配列を返します。
262 *
263 * @return 添付ファイルのFileインスタンス配列
264 */
265 public File[] getFiles() {
266 AttachmentFile[] aFiles = getAttachmentFiles();
267 File[] files = new File[aFiles.length];
268 for (int i = 0; i < aFiles.length; i++) {
269 AttachmentFile aFile = aFiles[i];
270 files[i] = aFile.getFile();
271 }
272 return files;
273 }
274
275 /***
276 * このメールの返信メール用Mailインスタンスを生成して返します。
277 * <ul>
278 * <li>宛先(Toアドレス)には、このメールのReply-To、またはFromがセットされます。</li>
279 * <li>件名には、このメールの件名が大文字小文字問わず「Re:」で始まっていなければ、「Re: 」を頭に付けた件名がセットされます。「Re:」で始まっている場合には、その件名をそのままセットします。</li>
280 * <li>本文には、何もセットされません。</li>
281 * <li>このメールにMessage-IDがセットされていれば、In-Reply-Toヘッダにその値がセットされます。</li>
282 * <li>このメールにMessage-IDがセットされていれば、Referencesヘッダにその値が加えられます。</li>
283 * </ul>
284 *
285 * @return 返信用のMailインスタンス
286 */
287 public Mail reply() {
288 Mail mail = new Mail();
289
290
291 if (getReplyTo() != null) {
292 mail.addTo(getReplyTo());
293 } else {
294 mail.addTo(getFrom());
295 }
296
297
298 String subject = getSubject();
299 if ((subject.length() >= 3 && !"Re:".equalsIgnoreCase(subject.substring(0, 3)))
300 || subject.length() < 3) {
301 subject = replySubjectPrefix + subject;
302 }
303 mail.setSubject(subject);
304
305
306 String messageId = getMessageId();
307 if (messageId != null && !"<>".equals(messageId)) {
308 String references = getRefereces();
309 if (references != null) {
310 references = messageId + " " + references;
311 } else if (getInReplyTo() != null) {
312 references = messageId + " " + getInReplyTo();
313 } else {
314 references = messageId;
315 }
316 mail.addHeader("References", references);
317 mail.addHeader("In-Reply-To", messageId);
318 }
319
320 return mail;
321 }
322
323 /***
324 * Receivedヘッダフィールドを追加します。
325 *
326 * @param rh Receivedヘッダフィールド
327 */
328 public void addReceviedHeader(ReceivedHeader rh) {
329 if (receivedHeaders == null) {
330 receivedHeaders = new ArrayList();
331 }
332 receivedHeaders.add(rh);
333 }
334
335 /***
336 * Receivedヘッダフィールドの配列を返します。<br>
337 * 自分のサーバ(このメールが届いたサーバ)から送信元のメールサーバを辿る順で並んでいます。<br>
338 * 受信メールがReceivedヘッダフィールドを持たない、または解析できなかった場合は空の配列を返します。
339 *
340 * @return Receivedヘッダフィールドの配列
341 */
342 public ReceivedHeader[] getReceivedHeaders() {
343 if (receivedHeaders == null) {
344 return new ReceivedHeader[0];
345 }
346 return (ReceivedHeader[])receivedHeaders
347 .toArray(new ReceivedHeader[receivedHeaders.size()]);
348 }
349
350 /***
351 * Receviedヘッダフィールドを表すクラス。
352 */
353 public static class ReceivedHeader {
354
355 private String from;
356
357 private String by;
358
359 /***
360 * @param from メールを送信したサーバのホスト名
361 * @param by メールを受信したサーバのホスト名
362 */
363 public ReceivedHeader(String from, String by) {
364 this.from = from;
365 this.by = by;
366 }
367
368 /***
369 * @see java.lang.Object#toString()
370 */
371 public String toString() {
372 return "Sent from " + from + " and received by " + by;
373 }
374
375 /***
376 * @return メールを受信したサーバのホスト名
377 */
378 public String getBy() {
379 return by;
380 }
381
382 /***
383 * @return メールを送信したサーバのホスト名
384 */
385 public String getFrom() {
386 return from;
387 }
388 }
389 }