KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > suberic > pooka > MessageInfo


1 package net.suberic.pooka;
2 import net.suberic.pooka.filter.FilterAction;
3 import net.suberic.pooka.gui.MessageProxy;
4 import net.suberic.util.thread.*;
5 import javax.mail.*;
6 import javax.mail.internet.MimeBodyPart JavaDoc;
7 import javax.mail.internet.MimeMessage JavaDoc;
8 import javax.mail.event.*;
9 import javax.swing.*;
10 import java.util.Hashtable JavaDoc;
11 import java.util.Vector JavaDoc;
12 import java.util.logging.Logger JavaDoc;
13 import java.util.logging.Level JavaDoc;
14 import java.io.*;
15
16 public class MessageInfo {
17   // the wrapped Message
18
Message JavaDoc message;
19
20   // the source FolderInfo
21
FolderInfo folderInfo;
22
23   // if the tableInfo has been loaded yet.
24
boolean loaded = false;
25
26   // if the message has been read
27
boolean seen = false;
28
29   // if the attachments have been loaded yet.
30
boolean attachmentsLoaded = false;
31
32   // the MessageProxy associated with this MessageInfo
33
MessageProxy messageProxy;
34
35   // the attachments on the message.
36
AttachmentBundle attachments;
37
38   // the CryptoInfo for this Message.
39
MessageCryptoInfo cryptoInfo = new MessageCryptoInfo(this);
40
41   // if the Message itself has been loaded via fetch()
42
boolean fetched = false;
43
44   public static int FORWARD_AS_ATTACHMENT = 0;
45   public static int FORWARD_QUOTED = 1;
46   public static int FORWARD_AS_INLINE = 2;
47
48   protected MessageInfo() {
49   }
50
51   /**
52    * This creates a new MessageInfo from the given FolderInfo and Message.
53    */

54   public MessageInfo(Message JavaDoc newMessage, FolderInfo newFolderInfo) {
55     folderInfo = newFolderInfo;
56     message = newMessage;
57   }
58
59   /**
60    * This loads the Attachment information into the attachments vector.
61    */

62   public void loadAttachmentInfo() throws MessagingException {
63     try {
64       // FIXME
65
attachments = MailUtilities.parseAttachments(getMessage());
66       attachmentsLoaded = true;
67       if (Pooka.getProperty("EncryptionManager.autoDecrypt", "false").equalsIgnoreCase("true") && cryptoInfo.isEncrypted()) {
68         UserProfile p = getDefaultProfile();
69         if (p == null)
70           p = Pooka.getPookaManager().getUserProfileManager().getDefaultProfile();
71
72         if (cryptoInfo.autoDecrypt(p)) {
73           //attachments = MailUtilities.parseAttachments(getMessage());
74
}
75       }
76
77       if (Pooka.getProperty("EncryptionManager.autoCheckSig", "false").equalsIgnoreCase("true") && cryptoInfo.isSigned()) {
78         if (cryptoInfo.autoCheckSignature((javax.mail.internet.InternetAddress JavaDoc) getMessage().getFrom()[0])) {
79           //attachments = MailUtilities.parseAttachments(getMessage());
80
}
81       }
82
83     } catch (MessagingException me) {
84       // if we can't parse the message, try loading it as a single text
85
// file.
86
try {
87         javax.mail.internet.MimeMessage JavaDoc mimeMessage = (javax.mail.internet.MimeMessage JavaDoc)getMessage();
88         AttachmentBundle bundle = new AttachmentBundle(mimeMessage);
89         ByteArrayOutputStream baos = new ByteArrayOutputStream();
90         java.util.List JavaDoc headerList = new java.util.ArrayList JavaDoc();
91         java.util.Enumeration JavaDoc headerEnum = mimeMessage.getAllHeaders();
92         while (headerEnum.hasMoreElements()) {
93           Header hdr = (Header) headerEnum.nextElement();
94           headerList.add(hdr.getName());
95         }
96         String JavaDoc[] excludeList = (String JavaDoc[]) headerList.toArray(new String JavaDoc[0]);
97         mimeMessage.writeTo(baos, excludeList);
98         String JavaDoc content = baos.toString("ISO-8859-1");
99         MimeBodyPart JavaDoc mbp = new MimeBodyPart JavaDoc();
100         mbp.setText(content);
101         Attachment textPart = new Attachment(mbp);
102         bundle.addAttachment(textPart);
103
104         attachments = bundle;
105       } catch (Exception JavaDoc e) {
106         throw me;
107       }
108     } catch (java.io.IOException JavaDoc ioe) {
109       throw new MessagingException("Error loading Message: " + ioe.toString(), ioe);
110     }
111
112   }
113
114   /**
115    * This gets a Flag property from the Message.
116    */

117   public boolean flagIsSet(String JavaDoc flagName) throws MessagingException {
118     if (Thread.currentThread() != getFolderInfo().getFolderThread() && ! (Thread.currentThread() instanceof net.suberic.pooka.thread.LoadMessageThread)) {
119       Logger JavaDoc folderLogger = getFolderInfo().getLogger();
120       if (folderLogger.isLoggable(Level.WARNING)) {
121         folderLogger.log(Level.WARNING, "Accessing Message Flags not on Folder Thread.");
122         Thread.currentThread().dumpStack();
123       }
124     }
125
126     if (flagName.equals("FLAG.ANSWERED") )
127       return getMessage().isSet(Flags.Flag.ANSWERED);
128     else if (flagName.equals("FLAG.DELETED"))
129       return getMessage().isSet(Flags.Flag.DELETED);
130     else if (flagName.equals("FLAG.DRAFT"))
131       return getMessage().isSet(Flags.Flag.DRAFT);
132     else if (flagName.equals("FLAG.FLAGGED"))
133       return getMessage().isSet(Flags.Flag.FLAGGED);
134     else if (flagName.equals("FLAG.RECENT"))
135       return getMessage().isSet(Flags.Flag.RECENT);
136     else if (flagName.equals("FLAG.SEEN")) {
137       if (folderInfo != null && ! folderInfo.tracksUnreadMessages())
138         return true;
139       else
140         return getMessage().isSet(Flags.Flag.SEEN);
141     }
142
143     return false;
144   }
145
146   /**
147    * This gets the Flags object for the wrapped Message.
148    */

149   public Flags getFlags() throws MessagingException {
150     if (Thread.currentThread() != getFolderInfo().getFolderThread() && ! (Thread.currentThread() instanceof net.suberic.pooka.thread.LoadMessageThread)) {
151       Logger JavaDoc folderLogger = getFolderInfo().getLogger();
152       if (folderLogger.isLoggable(Level.WARNING)) {
153         folderLogger.log(Level.WARNING, "Accessing Message Flags not on Folder Thread.");
154         Thread.currentThread().dumpStack();
155
156       }
157     }
158     return getMessage().getFlags();
159   }
160
161   /**
162    * Refreshes the flags object.
163    */

164   public void refreshFlags() throws MessagingException {
165     if (Thread.currentThread() != getFolderInfo().getFolderThread() && ! (Thread.currentThread() instanceof net.suberic.pooka.thread.LoadMessageThread)) {
166       Logger JavaDoc folderLogger = getFolderInfo().getLogger();
167       if (folderLogger.isLoggable(Level.WARNING)) {
168         folderLogger.log(Level.WARNING, "Accessing Message Flags not on Folder Thread.");
169         Thread.currentThread().dumpStack();
170
171       }
172     }
173     getFolderInfo().refreshFlags(this);
174   }
175
176   /**
177    * Refreshes the Headers object.
178    */

179   public void refreshHeaders() throws MessagingException {
180     if (Thread.currentThread() != getFolderInfo().getFolderThread() && ! (Thread.currentThread() instanceof net.suberic.pooka.thread.LoadMessageThread)) {
181       Logger JavaDoc folderLogger = getFolderInfo().getLogger();
182       if (folderLogger.isLoggable(Level.WARNING)) {
183         folderLogger.log(Level.WARNING, "Accessing Message Headers not on Folder Thread.");
184         Thread.currentThread().dumpStack();
185
186       }
187     }
188     getFolderInfo().refreshHeaders(this);
189   }
190
191   /**
192    * This gets a particular property (From, To, Date, Subject, or just
193    * about any Email Header) from the Message.
194    */

195   public Object JavaDoc getMessageProperty(String JavaDoc prop) throws MessagingException {
196     if (getFolderInfo() != null && Thread.currentThread() != getFolderInfo().getFolderThread() && ! (Thread.currentThread() instanceof net.suberic.pooka.thread.LoadMessageThread)) {
197       Logger JavaDoc folderLogger = getFolderInfo().getLogger();
198       if (folderLogger.isLoggable(Level.WARNING)) {
199         folderLogger.log(Level.WARNING, "Getting Message Property not on Folder Thread.");
200         Thread.currentThread().dumpStack();
201
202       }
203     }
204     Message JavaDoc msg = getMessage();
205     if (prop.equals("From")) {
206       try {
207         Address[] fromAddr = msg.getFrom();
208         return MailUtilities.decodeAddressString(fromAddr);
209       } catch (javax.mail.internet.AddressException JavaDoc ae) {
210         return ((MimeMessage JavaDoc) msg).getHeader("From", ",");
211       }
212     } else if (prop.equalsIgnoreCase("receivedDate")) {
213       return msg.getReceivedDate();
214     } else if (prop.equalsIgnoreCase("recipients")) {
215       return msg.getAllRecipients();
216     } else if (prop.equalsIgnoreCase("to")) {
217       return MailUtilities.decodeAddressString(msg.getRecipients(Message.RecipientType.TO));
218     } else if (prop.equalsIgnoreCase("cc")) {
219       return MailUtilities.decodeAddressString(msg.getRecipients(Message.RecipientType.CC));
220     } else if (prop.equalsIgnoreCase("bcc")) {
221       return MailUtilities.decodeAddressString(msg.getRecipients(Message.RecipientType.BCC));
222     } else if (prop.equalsIgnoreCase("Date")) {
223       return msg.getSentDate();
224     } else if (prop.equalsIgnoreCase("Subject")) {
225       return MailUtilities.decodeText(msg.getSubject());
226     }
227
228     if (msg instanceof MimeMessage JavaDoc) {
229       String JavaDoc hdrVal = ((MimeMessage JavaDoc)msg).getHeader(prop, ",");
230       if (hdrVal != null && hdrVal.length() > 0)
231         return MailUtilities.decodeText(hdrVal);
232     }
233     return "";
234   }
235
236   /**
237    * Gets the Content and inline text content for the Message.
238    */

239   public String JavaDoc getTextAndTextInlines(String JavaDoc attachmentSeparator, boolean withHeaders, boolean showFullHeaders, int maxLength, String JavaDoc truncationMessage) throws MessagingException {
240     try {
241       if (!hasLoadedAttachments())
242         loadAttachmentInfo();
243       return attachments.getTextAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, maxLength, truncationMessage);
244     } catch (FolderClosedException fce) {
245       try {
246         if (getFolderInfo().shouldBeConnected()) {
247           getFolderInfo().openFolder(Folder.READ_WRITE);
248           loadAttachmentInfo();
249           return attachments.getTextAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, maxLength, truncationMessage);
250         } else {
251           throw fce;
252         }
253       } catch (java.io.IOException JavaDoc ioe) {
254         throw new MessagingException(ioe.getMessage());
255       }
256     } catch (java.io.IOException JavaDoc ioe) {
257       ioe.printStackTrace();
258       throw new MessagingException(ioe.getMessage());
259     }
260   }
261
262   /**
263    * Gets the Content and inline text content for the Message.
264    */

265   public String JavaDoc getTextAndTextInlines(String JavaDoc attachmentSeparator, boolean withHeaders, boolean showFullHeaders) throws MessagingException {
266     return getTextAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getTruncationMessage());
267   }
268
269   /**
270    * Gets the Content and inline text content for the Message.
271    */

272   public String JavaDoc getTextAndTextInlines(boolean withHeaders, boolean showFullHeaders) throws MessagingException {
273     return getTextAndTextInlines(getAttachmentSeparator(), withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getTruncationMessage());
274   }
275
276   /**
277    * Gets the Text part of the Content of this Message. If no real text
278    * content is found, returns the html content. If there's none of that,
279    * either, then returns null.
280    */

281   public String JavaDoc getTextPart(boolean withHeaders, boolean showFullHeaders, int maxLength, String JavaDoc truncationMessage) throws MessagingException {
282     try {
283       if (!hasLoadedAttachments())
284         loadAttachmentInfo();
285       String JavaDoc returnValue = attachments.getTextPart(withHeaders, showFullHeaders, maxLength, truncationMessage);
286       if (returnValue != null)
287         return returnValue;
288       else
289         return getHtmlPart(withHeaders, showFullHeaders, maxLength, getHtmlTruncationMessage());
290     } catch (FolderClosedException fce) {
291       try {
292         if (getFolderInfo().shouldBeConnected()) {
293           getFolderInfo().openFolder(Folder.READ_WRITE);
294           loadAttachmentInfo();
295           String JavaDoc returnValue = attachments.getTextPart(withHeaders, showFullHeaders, maxLength, truncationMessage);
296           if (returnValue != null)
297             return returnValue;
298           else
299             return getHtmlPart(withHeaders, showFullHeaders, maxLength, getHtmlTruncationMessage());
300         } else {
301           throw fce;
302         }
303       } catch (java.io.IOException JavaDoc ioe) {
304         throw new MessagingException(ioe.getMessage());
305       }
306     } catch (java.io.IOException JavaDoc ioe) {
307       throw new MessagingException(ioe.getMessage());
308     }
309   }
310
311   /**
312    * Gets the Text part of the Content of this Message. If no real text
313    * content is found, returns the html content. If there's none of that,
314    * either, then returns null.
315    */

316   public String JavaDoc getTextPart(boolean withHeaders, boolean showFullHeaders) throws MessagingException {
317     return getTextPart(withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getTruncationMessage());
318   }
319
320   /**
321    * Gets the Html part of the Content of this Message.
322    */

323   public String JavaDoc getHtmlPart(boolean withHeaders, boolean showFullHeaders, int maxLength, String JavaDoc truncationMessage) throws MessagingException {
324     try {
325       if (!hasLoadedAttachments())
326         loadAttachmentInfo();
327       return attachments.getHtmlPart(withHeaders, showFullHeaders, maxLength, truncationMessage);
328     } catch (FolderClosedException fce) {
329       try {
330         if (getFolderInfo().shouldBeConnected()) {
331           getFolderInfo().openFolder(Folder.READ_WRITE);
332           loadAttachmentInfo();
333           return attachments.getHtmlPart(withHeaders, showFullHeaders, maxLength, truncationMessage);
334         } else {
335           throw fce;
336         }
337       } catch (java.io.IOException JavaDoc ioe) {
338         throw new MessagingException(ioe.getMessage());
339       }
340     } catch (java.io.IOException JavaDoc ioe) {
341       throw new MessagingException(ioe.getMessage());
342     }
343   }
344
345   /**
346    * Gets the Html part of the Content of this Message.
347    */

348   public String JavaDoc getHtmlPart(boolean withHeaders, boolean showFullHeaders) throws MessagingException {
349     return getHtmlPart(withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getTruncationMessage());
350   }
351
352   /**
353    * Gets the Content and inline text content for the Message.
354    */

355   public String JavaDoc getHtmlAndTextInlines(String JavaDoc attachmentSeparator, boolean withHeaders, boolean showFullHeaders, int maxLength, String JavaDoc truncationMessage) throws MessagingException {
356     try {
357       if (!hasLoadedAttachments())
358         loadAttachmentInfo();
359       return attachments.getHtmlAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, maxLength, truncationMessage);
360     } catch (FolderClosedException fce) {
361       try {
362         if (getFolderInfo().shouldBeConnected()) {
363           getFolderInfo().openFolder(Folder.READ_WRITE);
364           loadAttachmentInfo();
365           return attachments.getHtmlAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, maxLength, truncationMessage);
366         } else {
367           throw fce;
368         }
369       } catch (java.io.IOException JavaDoc ioe) {
370         throw new MessagingException(ioe.getMessage());
371       }
372     } catch (java.io.IOException JavaDoc ioe) {
373       throw new MessagingException(ioe.getMessage());
374     }
375   }
376
377   /**
378    * Gets the Content and inline text content for the Message.
379    */

380   public String JavaDoc getHtmlAndTextInlines(String JavaDoc attachmentSeparator, boolean withHeaders, boolean showFullHeaders) throws MessagingException {
381     return getHtmlAndTextInlines(attachmentSeparator, withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getHtmlTruncationMessage());
382   }
383
384   /**
385    * Gets the Content and inline text content for the Message.
386    */

387   public String JavaDoc getHtmlAndTextInlines(boolean withHeaders, boolean showFullHeaders) throws MessagingException {
388     return getHtmlAndTextInlines(getHtmlAttachmentSeparator(), withHeaders, showFullHeaders, getMaxMessageDisplayLength(), getHtmlTruncationMessage());
389   }
390
391   /**
392    * Gets the raw RFC 822 message.
393    */

394   public String JavaDoc getRawText() throws MessagingException {
395     try {
396       ByteArrayOutputStream baos = new ByteArrayOutputStream();
397       MimeMessage JavaDoc mm = (MimeMessage JavaDoc) getMessage();
398       mm.writeTo(baos);
399       return baos.toString();
400     } catch (IOException ioe) {
401       MessagingException returnValue = new MessagingException("Error reading Message Stream", ioe);
402       throw returnValue;
403     }
404   }
405
406   /**
407    * Moves the Message into the target Folder.
408    */

409   public void moveMessage(FolderInfo targetFolder, boolean expunge) throws MessagingException {
410     try {
411       folderInfo.copyMessages(new MessageInfo[] { this }, targetFolder);
412     } catch (MessagingException me) {
413       MessagingException returnValue = new MessagingException (Pooka.getProperty("error.Message.CopyErrorMessage", "Error: could not copy messages to folder: ") + targetFolder.toString() +"\n", me);
414       throw returnValue;
415     }
416
417     try {
418       remove(expunge);
419     } catch (MessagingException me) {
420       MessagingException returnValue = new MessagingException(Pooka.getProperty("error.Message.RemoveErrorMessage", "Error: could not remove messages from folder: ") + targetFolder.toString() +"\n", me);
421       throw returnValue;
422     }
423   }
424
425   /**
426    * Copies the Message into the target Folder.
427    */

428   public void copyMessage(FolderInfo targetFolder) throws MessagingException {
429     try {
430       folderInfo.copyMessages(new MessageInfo[] { this }, targetFolder);
431     } catch (MessagingException me) {
432       MessagingException returnValue = new MessagingException (Pooka.getProperty("error.Message.CopyErrorMessage", "Error: could not copy messages to folder: ") + targetFolder.toString() +"\n", me);
433       throw returnValue;
434     }
435
436   }
437
438   /**
439    * A convenience method which sets autoExpunge by the value of
440    * Pooka.autoExpunge, and then calls moveMessage(targetFolder, autoExpunge)
441    * with that value.
442    */

443   public void moveMessage(FolderInfo targetFolder) throws MessagingException {
444     moveMessage(targetFolder, Pooka.getProperty("Pooka.autoExpunge", "true").equals("true"));
445   }
446
447   /**
448    * Bounces this message to another user.
449    */

450   public void bounceMessage(Address[] recipientList) throws javax.mail.MessagingException JavaDoc {
451
452     MimeMessage JavaDoc mm = (MimeMessage JavaDoc)getMessage();
453     MimeMessage JavaDoc mmClone = new MimeMessage JavaDoc(mm);
454
455     NewMessageInfo nmi = new NewMessageInfo(mmClone);
456     net.suberic.pooka.gui.NewMessageProxy nmp = new net.suberic.pooka.gui.NewMessageProxy(nmi);
457     java.util.HashMap JavaDoc messageMap = new java.util.HashMap JavaDoc();
458     messageMap.put(mmClone, recipientList);
459
460     nmi.setSendMessageMap(messageMap);
461
462     final NewMessageInfo final_nmi = nmi;
463
464     UserProfile p = getDefaultProfile();
465     if (p == null)
466       p = Pooka.getPookaManager().getUserProfileManager().getDefaultProfile();
467
468     if (p != null && p.getMailServer() != null) {
469       final OutgoingMailServer mailServer = p.getMailServer();
470       mailServer.mailServerThread.addToQueue(new javax.swing.AbstractAction JavaDoc() {
471           public void actionPerformed(java.awt.event.ActionEvent JavaDoc ae) {
472             mailServer.sendMessage(final_nmi);
473           }
474         }, new java.awt.event.ActionEvent JavaDoc(this, 0, "message-send"));
475     }
476   }
477
478   /**
479    * Deletes the Message from the current Folder. If a Trash folder is
480    * set, this method moves the message into the Trash folder. If no
481    * Trash folder is set, this marks the message as deleted. In addition,
482    * if the autoExpunge variable is set to true, it also expunges
483    * the message from the mailbox.
484    */

485   public void deleteMessage(boolean autoExpunge) throws MessagingException {
486     FolderInfo trashFolder = getFolderInfo().getTrashFolder();
487     if ((getFolderInfo().useTrashFolder()) && (trashFolder != null) && (trashFolder != getFolderInfo())) {
488       try {
489         moveMessage(trashFolder, autoExpunge);
490       } catch (MessagingException me) {
491         throw new MessagingException(Pooka.getProperty("error.Messsage.DeleteNoTrashFolder", "No trash folder available."), me);
492       }
493     } else {
494
495       // actually remove the message, if we haven't already moved it.
496

497       try {
498         remove(autoExpunge);
499       } catch (MessagingException me) {
500         me.printStackTrace();
501         throw new MessagingException(Pooka.getProperty("error.Message.DeleteErrorMessage", "Error: could not delete message.") +"\n", me);
502       }
503     }
504
505     if (getMessageProxy() != null)
506       getMessageProxy().close();
507   }
508
509   /**
510    * A convenience method which sets autoExpunge by the value of
511    * Pooka.autoExpunge, and then calls deleteMessage(boolean autoExpunge)
512    * with that value.
513    */

514   public void deleteMessage() throws MessagingException {
515     deleteMessage(Pooka.getProperty("Pooka.autoExpunge", "true").equals("true"));
516   }
517
518   /**
519    * This actually marks the message as deleted, and, if autoexpunge is
520    * set to true, expunges the folder.
521    *
522    * This should not be called directly; rather, deleteMessage() should
523    * be used in order to ensure that the delete is done properly (using
524    * trash folders, for instance). If, however, the deleteMessage()
525    * throws an Exception, it may be necessary to follow up with a call
526    * to remove().
527    */

528   public void remove(boolean autoExpunge) throws MessagingException {
529     Message JavaDoc m = getMessage();
530     if (m != null) {
531       m.setFlag(Flags.Flag.DELETED, true);
532       if ( autoExpunge ) {
533         folderInfo.expunge();
534       }
535     }
536   }
537
538   /**
539    * This puts the reply prefix 'prefix' in front of each line in the
540    * body of the Message.
541    */

542   public String JavaDoc prefixMessage(String JavaDoc originalMessage, String JavaDoc prefix, String JavaDoc intro) {
543     StringBuffer JavaDoc newValue = new StringBuffer JavaDoc(originalMessage);
544
545     int currentCR = originalMessage.lastIndexOf('\n', originalMessage.length());
546     while (currentCR != -1) {
547       newValue.insert(currentCR+1, prefix);
548       currentCR=originalMessage.lastIndexOf('\n', currentCR-1);
549     }
550     newValue.insert(0, prefix);
551     newValue.insert(0, intro);
552
553     return newValue.toString();
554   }
555
556   /**
557    * This parses a message line using the current Message as a model.
558    * The introTemplate will be of the form 'On %d, %n wrote', or
559    * something similar. This method uses the Pooka.parsedString
560    * characters to decide which strings to substitute for which
561    * characters.
562    */

563   public String JavaDoc parseMsgString(MimeMessage JavaDoc m, String JavaDoc introTemplate, boolean addLF) {
564     StringBuffer JavaDoc intro = new StringBuffer JavaDoc(introTemplate);
565     int index = introTemplate.lastIndexOf('%', introTemplate.length());
566     try {
567       while (index > -1) {
568         try {
569           char nextChar = introTemplate.charAt(index + 1);
570           String JavaDoc replaceMe = null;
571           if (nextChar == Pooka.getProperty("Pooka.parsedString.nameChar", "n").charAt(0)) {
572
573             Address[] fromAddresses = m.getFrom();
574             if (fromAddresses.length > 0 && fromAddresses[0] != null) {
575               replaceMe = MailUtilities.decodeAddressString(fromAddresses);
576               if (replaceMe == null)
577                 replaceMe = "";
578               intro.replace(index, index +2, replaceMe);
579             }
580           } else if (nextChar == Pooka.getProperty("Pooka.parsedString.dateChar", "d").charAt(0)) {
581             replaceMe = Pooka.getDateFormatter().fullDateFormat.format(m.getSentDate());
582             if (replaceMe == null)
583               replaceMe = "";
584             intro.replace(index, index + 2, replaceMe);
585           } else if (nextChar == Pooka.getProperty("Pooka.parsedString.subjChar", "s").charAt(0)) {
586             replaceMe = m.getSubject();
587             if (replaceMe == null)
588               replaceMe = "";
589             intro.replace(index, index + 2, replaceMe);
590           } else if (nextChar == '%') {
591             intro.replace(index, index+1, "%");
592           }
593           index = introTemplate.lastIndexOf('%', index -1);
594         } catch (StringIndexOutOfBoundsException JavaDoc e) {
595           index = introTemplate.lastIndexOf('%', index -1);
596         }
597       }
598     } catch (MessagingException me) {
599       return null;
600     }
601
602     if (addLF)
603       if (intro.charAt(intro.length()-1) != '\n')
604         intro.append('\n');
605
606     return intro.toString();
607   }
608
609   /**
610    * This populates a message which is a reply to the current
611    * message.
612    */

613   public NewMessageInfo populateReply(boolean replyAll, boolean withAttachments)
614     throws MessagingException {
615     MimeMessage JavaDoc newMsg = (MimeMessage JavaDoc) getMessage().reply(replyAll);
616
617     MimeMessage JavaDoc mMsg = (MimeMessage JavaDoc) getMessage();
618
619     String JavaDoc textPart = getTextPart(false, false, getMaxMessageDisplayLength(), getTruncationMessage());
620     if (textPart == null) {
621       textPart = "";
622     }
623
624     if (isHtml()) {
625       net.suberic.pooka.htmlparser.PookaStringBean psb = new net.suberic.pooka.htmlparser.PookaStringBean();
626       psb.setContent(textPart, null);
627       textPart = psb.getStrings();
628     }
629
630     if (textPart == null) {
631       textPart = "";
632     }
633
634     UserProfile up = getDefaultProfile();
635     if (up == null)
636       up = Pooka.getPookaManager().getUserProfileManager().getDefaultProfile();
637
638     String JavaDoc parsedText;
639     String JavaDoc replyPrefix;
640     String JavaDoc parsedIntro;
641
642     if (up != null && up.getMailProperties() != null) {
643       replyPrefix = up.getMailProperties().getProperty("replyPrefix", Pooka.getProperty("Pooka.replyPrefix", "> "));
644       parsedIntro = parseMsgString(mMsg, up.getMailProperties().getProperty("replyIntro", Pooka.getProperty("Pooka.replyIntro", "On %d, %n wrote:")), true);
645     } else {
646       replyPrefix = Pooka.getProperty("Pooka.replyPrefix", "> ");
647       parsedIntro = parseMsgString(mMsg, Pooka.getProperty("Pooka.replyIntro", "On %d, %n wrote:"), true);
648     }
649     parsedText = prefixMessage(textPart, replyPrefix, parsedIntro);
650     newMsg.setText(parsedText);
651
652     if (replyAll && Pooka.getProperty("Pooka.excludeSelfInReply", "true").equalsIgnoreCase("true")) {
653       up.removeFromAddress(newMsg);
654     }
655
656     NewMessageInfo returnValue = new NewMessageInfo(newMsg);
657
658     if (withAttachments) {
659       returnValue.attachments = new AttachmentBundle();
660       returnValue.attachments.addAll(attachments);
661       returnValue.attachmentsLoaded=true;
662     }
663
664     return returnValue;
665   }
666
667   /**
668    * This populates a message which is a reply to the current
669    * message.
670    */

671   public NewMessageInfo populateReply(boolean replyAll)
672     throws MessagingException {
673     return populateReply(replyAll, false);
674   }
675
676   /**
677    * This populates a new message which is a forwarding of the
678    * current message.
679    */

680   public NewMessageInfo populateForward(boolean withAttachments, int method)
681     throws MessagingException {
682     MimeMessage JavaDoc mMsg = (MimeMessage JavaDoc) getMessage();
683     MimeMessage JavaDoc newMsg = new MimeMessage JavaDoc(Pooka.getDefaultSession());
684
685     String JavaDoc parsedText = "";
686
687     if (method == FORWARD_QUOTED) {
688       String JavaDoc textPart = getTextPart(false, false, getMaxMessageDisplayLength(), getTruncationMessage());
689
690       UserProfile up = getDefaultProfile();
691       if (up == null) {
692         up = Pooka.getPookaManager().getUserProfileManager().getDefaultProfile();
693       }
694
695       String JavaDoc forwardPrefix;
696       String JavaDoc parsedIntro;
697
698       if (up != null && up.getMailProperties() != null) {
699         forwardPrefix = up.getMailProperties().getProperty("forwardPrefix", Pooka.getProperty("Pooka.forwardPrefix", "> "));
700         parsedIntro = parseMsgString(mMsg, up.getMailProperties().getProperty("forwardIntro", Pooka.getProperty("Pooka.forwardIntro", "Forwarded message from %n:")), true);
701       } else {
702         forwardPrefix = Pooka.getProperty("Pooka.forwardPrefix", "> ");
703         parsedIntro = parseMsgString(mMsg, Pooka.getProperty("Pooka.forwardIntro", "Forwarded message from %n:"), true);
704       }
705       parsedText = prefixMessage(textPart, forwardPrefix, parsedIntro);
706
707     } else if (method == FORWARD_AS_INLINE) {
708
709       String JavaDoc textPart = getTextPart(true, false, getMaxMessageDisplayLength(), getTruncationMessage());
710
711       parsedText = Pooka.getProperty("Pooka.forwardInlineIntro", "---------- Original Message ----------\n") + textPart;
712
713     }
714
715     newMsg.setText(parsedText);
716     newMsg.setSubject(parseMsgString(mMsg, Pooka.getProperty("Pooka.forwardSubject", "Fwd: %s"), false));
717
718     NewMessageInfo returnValue = new NewMessageInfo(newMsg);
719
720     // handle attachments.
721
if (method == FORWARD_AS_ATTACHMENT) {
722       UpdatableMBP mbp = new UpdatableMBP();
723       mbp.setContent(getRealMessage(), "message/rfc822");
724       mbp.updateMyHeaders();
725       String JavaDoc subject = (String JavaDoc) getMessageProperty("Subject");
726       if (subject != null && subject.length() > 0) {
727         mbp.setFileName(subject);
728       } else {
729         mbp.setFileName("forwarded message");
730       }
731       mbp.setDisposition(Part.ATTACHMENT);
732
733       AttachmentBundle returnAttachments = returnValue.getAttachmentBundle();
734       Attachment messageAttachment = new MBPAttachment(mbp);
735       returnAttachments.addAttachment(messageAttachment, false);
736
737
738     } else if (withAttachments) {
739       returnValue.attachments = new AttachmentBundle();
740       Vector JavaDoc fromAttachments = attachments.getAttachments();
741       if (fromAttachments != null) {
742         AttachmentBundle returnAttachments = returnValue.getAttachmentBundle();
743         for (int i = 0; i < fromAttachments.size(); i++) {
744           Attachment current = (Attachment) fromAttachments.elementAt(i);
745           Attachment newAttachment = null;
746
747           MimeBodyPart JavaDoc mbp = new MimeBodyPart JavaDoc();
748           mbp.setDataHandler(current.getDataHandler());
749           newAttachment = new MBPAttachment(mbp);
750           returnAttachments.addAttachment(newAttachment, false);
751         }
752       }
753     }
754
755     return returnValue;
756   }
757
758   /**
759    * This populates a new message which is a forwarding of the
760    * current message.
761    */

762   public NewMessageInfo populateForward()
763     throws MessagingException {
764     return populateForward(false, FORWARD_QUOTED);
765   }
766
767   /**
768    * Runs folder filters on this MessageInfo.
769    */

770   public void runBackendFilters() {
771     FolderInfo fi = getFolderInfo();
772     java.util.LinkedList JavaDoc list = new java.util.LinkedList JavaDoc();
773     list.add(getMessageProxy());
774     fi.applyFilters(list);
775   }
776
777   /**
778    * Runs the configured spam action on this message.
779    */

780   public void runSpamAction() {
781     FilterAction spamFilter = null;
782     try {
783       spamFilter = MessageFilter.generateFilterAction("Pooka.spamAction");
784     } catch (Exception JavaDoc e) {
785       int configureNow = Pooka.getUIFactory().showConfirmDialog("Spam action currently not configured. Would you like to configure it now?", "Configure Spam action", javax.swing.JOptionPane.YES_NO_OPTION);
786       if (configureNow == javax.swing.JOptionPane.YES_OPTION) {
787         // show configure screen.
788
Pooka.getUIFactory().showEditorWindow(Pooka.getProperty("Preferences.Spam.label", "Spam"), "Pooka.spamAction");
789       }
790
791     }
792     if (spamFilter != null) {
793       Vector JavaDoc v = new Vector JavaDoc();
794       v.add(this.getMessageProxy());
795       java.util.List JavaDoc removed = spamFilter.performFilter(v);
796       if (removed != null && removed.size() > 0) {
797         try {
798           getFolderInfo().expunge();
799         } catch (MessagingException me) {
800           // throw it away
801
}
802       }
803       return;
804     }
805   }
806
807   /**
808    * Caches the current messages.
809    */

810   public void cacheMessage() throws MessagingException {
811     FolderInfo fi = getFolderInfo();
812     if (fi != null && fi instanceof net.suberic.pooka.cache.CachingFolderInfo) {
813       ((net.suberic.pooka.cache.CachingFolderInfo) fi).cacheMessage(this, net.suberic.pooka.cache.MessageCache.MESSAGE);
814
815     }
816   }
817
818   /**
819    * As specified by interface net.suberic.pooka.UserProfileContainer.
820    *
821    * If the MessageInfo's folderInfo is set, this returns the
822    * DefaultProfile of that folderInfo. If not, returns null.
823    */

824   public UserProfile getDefaultProfile() {
825     if (getFolderInfo() != null) {
826       return getFolderInfo().getDefaultProfile();
827     } else
828       return null;
829   }
830
831   /**
832    * Saves the message to the given filename.
833    */

834   public void saveMessageAs(File saveFile) throws MessagingException{
835     try {
836       FileOutputStream fos = new FileOutputStream(saveFile);
837       ((MimeMessage JavaDoc)getMessage()).writeTo(fos);
838     } catch (IOException ioe) {
839       MessagingException me = new MessagingException(Pooka.getProperty("error.errorCreatingAttachment", "Error attaching message"));
840       me.setNextException(ioe);
841       throw me;
842
843     }
844   }
845
846   /**
847    * Adds the sender of the message to the current AddressBook, if any.
848    */

849   public void addAddress(AddressBook book, boolean useVcard) throws MessagingException {
850     boolean found = false;
851     if (useVcard) {
852       Attachment vcard = null;
853
854       // see if there's a Vcard attachment on here.
855
Vector JavaDoc attachList = getAttachments();
856       if (attachList != null) {
857         for (int i = 0; i < attachList.size() && vcard==null; i++) {
858           Attachment current = (Attachment)attachList.get(i);
859           if (current.getMimeType().match("text/x-vcard")) {
860             vcard = current;
861           }
862         }
863
864         if (vcard != null) {
865           try {
866             String JavaDoc vcardText = (String JavaDoc) vcard.getContent();
867             BufferedReader reader = new BufferedReader(new StringReader(vcardText));
868             net.suberic.pooka.vcard.Vcard addressEntry = net.suberic.pooka.vcard.Vcard.parse(reader);
869             book.addAddress(addressEntry);
870             found = true;
871           } catch (Exception JavaDoc e) {
872             // if we get any exceptions parsing the Vcard, just fall back to
873
// using the fromAddress. do print out a debugging message,
874
// though.
875
getMessageProxy().showError(Pooka.getProperty("error.parsingVcard", "Error parsing Vcard"), e);
876           }
877         }
878       }
879     }
880
881     if (!found) {
882       Address[] fromAddresses = getMessage().getFrom();
883       javax.mail.internet.InternetAddress JavaDoc addr = (javax.mail.internet.InternetAddress JavaDoc) fromAddresses[0];
884
885       // let's not support multiple froms.
886
//AddressBookEntry entry = new net.suberic.pooka.vcard.Vcard(new java.util.Properties());
887
AddressBookEntry entry = book.newAddressBookEntry();
888
889       String JavaDoc personalName = addr.getPersonal();
890       if (personalName == null)
891         personalName = addr.getAddress();
892
893       entry.setPersonalName(personalName);
894       entry.setAddress(addr);
895       book.addAddress(entry);
896     }
897   }
898
899   /**
900    * Returns the Message that this MessageInfo is wrapping.
901    */

902   public Message JavaDoc getMessage() {
903     return message;
904   }
905
906   /**
907    * Returns the real, modifiable message that this MessageInfo is
908    * wrapping.
909    */

910   public Message JavaDoc getRealMessage() throws MessagingException {
911     if (getFolderInfo() != null) {
912       return getFolderInfo().getRealMessage(this);
913     }
914     return message;
915   }
916
917   /**
918    * Returns the FolderInfo to which this message belongs.
919    */

920   public FolderInfo getFolderInfo() {
921     return folderInfo;
922   }
923
924   /**
925    * Convenience method. Returns whether or not that message has been
926    * seen.
927    */

928   public boolean isSeen() {
929
930     if (folderInfo != null && ! folderInfo.tracksUnreadMessages()) {
931       return true;
932     } else
933       try {
934         return flagIsSet("FLAG.SEEN");
935       } catch (MessagingException me) {
936         return true;
937       }
938   }
939
940   /**
941    * Sets the seen parameter to the newValue. This basically calls
942    * setFlag(Flags.Flag.SEEN, newValue) on the wrapped Message.
943    */

944   public void setSeen(boolean newValue) throws MessagingException {
945     if (folderInfo != null && ! folderInfo.tracksUnreadMessages())
946       return;
947     else {
948       boolean seen = isSeen();
949       if (newValue != seen) {
950         //Message m = getRealMessage();
951
Message JavaDoc m = getMessage();
952         m.setFlag(Flags.Flag.SEEN, newValue);
953         getFolderInfo().fireMessageChangedEvent(new MessageChangedEvent(this, MessageChangedEvent.FLAGS_CHANGED, getMessage()));
954       }
955     }
956   }
957
958   public boolean isLoaded() {
959     return loaded;
960   }
961
962   /**
963    * This sets the loaded value for the MessageInfo to false. This
964    * should be called only if the TableInfo of the Message has been
965    * changed and needs to be reloaded.
966    */

967   public void unloadTableInfo() {
968     loaded=false;
969   }
970
971   public boolean hasLoadedAttachments() {
972     return attachmentsLoaded;
973   }
974
975   boolean mHasAttachments = false;
976   boolean mHasCheckedAttachments = false;
977
978   /**
979    * Returns whether or not this message has attachments.
980    */

981   public boolean hasAttachments() throws MessagingException {
982     if (mHasCheckedAttachments) {
983       return mHasAttachments;
984     } else {
985       if (hasLoadedAttachments()) {
986         if (getAttachments() != null && getAttachments().size() > 0)
987           mHasAttachments = true;
988
989         mHasCheckedAttachments = true;
990
991         return mHasAttachments;
992
993       } else {
994         try {
995           javax.mail.internet.ContentType JavaDoc type = new javax.mail.internet.ContentType JavaDoc(getMessage().getContentType());
996           if (new String JavaDoc("multipart").equalsIgnoreCase(type.getPrimaryType()) && ! new String JavaDoc("alternative").equalsIgnoreCase(type.getSubType())) {
997             return true;
998           } else {
999             return false;
1000          }
1001        } catch (javax.mail.internet.ParseException JavaDoc pe) {
1002          if (Pooka.isDebug()) {
1003            System.out.println("unable to parse content-type: " + getMessage().getContentType());
1004          }
1005          mHasAttachments = false;
1006        }
1007      }
1008    }
1009
1010    return mHasAttachments;
1011  }
1012
1013  /**
1014   * Returns whether or not this message has encryption on it.
1015   */

1016  public boolean hasEncryption() throws MessagingException {
1017    return (cryptoInfo.isEncrypted() || cryptoInfo.isSigned());
1018  }
1019
1020  /**
1021   * Returns the cryptoInfo object for this MessageInfo.
1022   */

1023  public MessageCryptoInfo getCryptoInfo() {
1024    return cryptoInfo;
1025  }
1026
1027  /**
1028   * Returns the attachments for this MessageInfo. If the attachments
1029   * have not yet been loaded, attempts to load the attachments.
1030   */

1031  public Vector JavaDoc getAttachments() throws MessagingException {
1032    if (hasLoadedAttachments())
1033      return attachments.getAttachments(getMaxMessageDisplayLength());
1034    else {
1035      loadAttachmentInfo();
1036      return attachments.getAttachments(getMaxMessageDisplayLength());
1037    }
1038
1039  }
1040
1041  /**
1042   * Returns the AttachmentBundle for this MessageInfo.
1043   */

1044  AttachmentBundle getAttachmentBundle() throws MessagingException {
1045    if (hasLoadedAttachments())
1046      return attachments;
1047    else {
1048      loadAttachmentInfo();
1049      return attachments;
1050    }
1051  }
1052
1053  /**
1054   * Returns the MessageProxy for this MessageInfo, if any.
1055   */

1056  public MessageProxy getMessageProxy() {
1057    return messageProxy;
1058  }
1059
1060  /**
1061   * Sets the primary MessageProxy for this MessageInfo.
1062   */

1063  public void setMessageProxy(MessageProxy newMp) {
1064    messageProxy = newMp;
1065  }
1066
1067  /**
1068   * Returns the default maximum display length for this MessageInfo.
1069   */

1070  public int getMaxMessageDisplayLength() {
1071    int displayLength = 10000;
1072    try {
1073      displayLength = Integer.parseInt(Pooka.getProperty("Pooka.attachmentDisplayMaxLength", "100000"));
1074    } catch (NumberFormatException JavaDoc nfe) {
1075    }
1076    return displayLength;
1077  }
1078
1079  /**
1080   * Returns the message to use if the message is displayed truncated (if the
1081   * MaxMessageDisplayLenght is exceeded.
1082   */

1083  public String JavaDoc getTruncationMessage() {
1084    return Pooka.getProperty("Pooka.messageTruncation", "------ Message truncated ------");
1085  }
1086
1087  /**
1088   * Returns the message to use if the message is displayed truncated (if the
1089   * MaxMessageDisplayLenght is exceeded.
1090   */

1091  public String JavaDoc getHtmlTruncationMessage() {
1092    return Pooka.getProperty("Pooka.html.messageTruncation", "<br><br><b>------ Message truncated ------</b><br><br>");
1093  }
1094
1095  public String JavaDoc getAttachmentSeparator() {
1096    return Pooka.getProperty("Pooka.attachmentSeparator", "\n\n");
1097  }
1098
1099  public String JavaDoc getHtmlAttachmentSeparator() {
1100    return Pooka.getProperty("Pooka.html.attachmentSeparator", "<br><hr><br>");
1101  }
1102
1103  /**
1104   * Returns whether or not this message has an HTML version available.
1105   */

1106  public boolean containsHtml() throws MessagingException {
1107    if (!hasLoadedAttachments())
1108      loadAttachmentInfo();
1109
1110    return attachments.containsHtml();
1111  }
1112
1113  /**
1114   * Returns true if the main content of this message exists only as
1115   * HTML.
1116   */

1117  public boolean isHtml() throws MessagingException {
1118    if (!hasLoadedAttachments())
1119      loadAttachmentInfo();
1120
1121    return attachments.isHtml();
1122  }
1123
1124  /**
1125   * Returns whether or not the underlying Message object has been
1126   * fetch()ed from the server yet.
1127   */

1128  public boolean hasBeenFetched() {
1129    return fetched;
1130  }
1131
1132  /**
1133   * Sets whether or not the underlying Message has been fetch()ed from
1134   * the server.
1135   */

1136  public void setFetched(boolean newValue) {
1137    fetched = newValue;
1138  }
1139}
1140
1141
1142
1143
1144
1145
1146
1147
Popular Tags