KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > EudoraMailImportFilter


1 /*
2  * EudoraMailImportFilter.java Created 2003-05-14 by Karl Peder Olesen
3  *
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with the
7  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
11  * the specific language governing rights and limitations under the License.
12  *
13  * The Original Code is Eudora Mail Import Filter plugin for Columba.
14  *
15  * The Initial Developer of the Original Code is Karl Peder Olesen. Portions
16  * created by Karl Peder Olesen are Copyright (C) 2003
17  *
18  * All Rights Reserved.
19  *
20  */

21
22 package org.columba.mail;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileReader JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.StringReader JavaDoc;
29 import java.text.SimpleDateFormat JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33
34 import org.columba.api.command.IWorkerStatusController;
35 import org.columba.mail.folder.IMailbox;
36 import org.columba.mail.folder.mailboximport.AbstractMailboxImporter;
37 import org.columba.ristretto.coder.EncodedWord;
38
39 /**
40  * Class used to import Eudora mail boxes. Plugin to Columba
41  *
42  * @author Karl Peder Olesen
43  * @version 1.0
44  */

45 public class EudoraMailImportFilter extends AbstractMailboxImporter {
46
47     /** JDK 1.4+ logging framework logger, used for logging. */
48     private static final Logger JavaDoc LOG = Logger.getLogger("org.columba.mail");
49
50     /** Time zone, e.g. "+0100", used for new Date headers (= host default) */
51     private static final String JavaDoc TIME_ZONE = (new SimpleDateFormat JavaDoc("Z"))
52             .format(new Date JavaDoc());
53
54     /**
55      * Charset, e.g. "iso-8859-1", when nothing else is specified (= host
56      * default)
57      */

58     private static final String JavaDoc DEFAULT_CHARSET = System
59             .getProperty("file.encoding");
60
61     public EudoraMailImportFilter() {
62         super();
63     }
64
65     /**
66      * Creates a new EudoraMailImportFilter object
67      *
68      * @param destinationFolder
69      * Where to import mails to (folder inside Columba)
70      * @param sourceFiles
71      * Mailboxes to import
72      */

73     public EudoraMailImportFilter(IMailbox destinationFolder, File JavaDoc[] sourceFiles) {
74         super(destinationFolder, sourceFiles);
75     }
76
77     /**
78      * Returns which type of import is supported
79      *
80      * @return type of import supported - here TYPE_FILE (=0)
81      */

82     public int getType() {
83         return TYPE_FILE;
84     }
85
86     public String JavaDoc getDescription() {
87         return "Eudora Mail Pro 4.0\n";
88     }
89
90     /**
91      * Imports a single mailbox file. This one is called from importMailbox
92      * (defined in DefaultMailboxImporter), which iterates over the source files
93      * to be imported - and calls this method for each file.
94      *
95      * @param file
96      * Mailbox file to import
97      * @param worker
98      * Used for handling user interuption
99      * @param destFolder
100      * Which mail folder inside Columba to import into
101      */

102     public void importMailboxFile(File JavaDoc file, IWorkerStatusController worker,
103             IMailbox destFolder) throws Exception JavaDoc {
104         LOG.fine("Starting to import Eudora mbox file: "
105                 + file.getAbsolutePath());
106
107         StringBuffer JavaDoc strbuf = new StringBuffer JavaDoc();
108         BufferedReader JavaDoc in = new BufferedReader JavaDoc(new FileReader JavaDoc(file));
109         String JavaDoc str;
110         int msgCounter = 0; // counts how many messages has been
111
// processed
112
String JavaDoc replacementDate = null; // date fetched from "From ???@??? ..."
113

114         // parse line by line
115
while ((str = in.readLine()) != null) {
116             // if user cancelled task exit immediately
117
if (worker.cancelled()) {
118                 return;
119             }
120
121             // Lines not starting with "From ???@???" is part of the message
122
// (headers or body)
123
if (!str.startsWith("From ???@???") || (str.length() == 0)) {
124                 strbuf.append(str + "\n");
125             } else // we reached "From ..." (start of new message)
126
{
127                 // If a msg has been read, import it into Columba
128
if (strbuf.length() != 0) {
129                     if (convertAndSaveMessage(strbuf.toString(),
130                             replacementDate, worker, destFolder)) {
131                         msgCounter++;
132                     }
133                 }
134                 // reset for new message
135
if (str.length() >= 13)
136                     replacementDate = str.substring(13); // fetch date from
137
// "From ???@???
138
// ..."
139
else
140                     replacementDate = "";
141                 strbuf = new StringBuffer JavaDoc();
142             }
143
144         }
145
146         // save last message (while loop terminated before last msg was saved)
147
if (strbuf.length() > 0) {
148             if (convertAndSaveMessage(strbuf.toString(), replacementDate,
149                     worker, destFolder)) {
150                 msgCounter++;
151             }
152         }
153
154         LOG.fine("Import of Eudora mbox file completed. " + msgCounter
155                 + " messages imported");
156         in.close();
157
158     } // ** End of method importMailboxFile
159

160     /**
161      * Returns a new date header from a date string like "Tue Apr 01 23:17:33
162      * 2003". The date header returned will be on a format like: "Date: Tue, 01
163      * Apr 2003 23:17:33 +0100", where +0100 is the time zone
164      *
165      * @param dateStr
166      * date string
167      * @param timeZone
168      * time zone, e.g. +0100
169      * @return date header without "\n"
170      */

171     private String JavaDoc getNewDateHeader(String JavaDoc dateStr, String JavaDoc timeZone) {
172         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(dateStr);
173         try {
174             String JavaDoc dow = tok.nextToken(); // day of week
175
String JavaDoc mon = tok.nextToken(); // month
176
String JavaDoc day = tok.nextToken(); // day of month
177
String JavaDoc time = tok.nextToken(); // time
178
String JavaDoc year = tok.nextToken(); // year
179

180             StringBuffer JavaDoc dateHeader = new StringBuffer JavaDoc();
181             dateHeader.append("Date: ");
182             dateHeader.append(dow + ",");
183             dateHeader.append(" " + day + " " + mon + " " + year);
184             dateHeader.append(" " + time);
185             if ((!(timeZone == null)) && (!timeZone.equals(""))) {
186                 dateHeader.append(" " + timeZone);
187             }
188
189             return dateHeader.toString();
190         } catch (java.util.NoSuchElementException JavaDoc e) {
191             // invalid date format - not enough tokens in it!!
192

193             // Logging.log.severe(
194
// "Not enough tokens in \""
195
// + dateStr
196
// + "\" to create Date: header. Returning null",
197
// e);
198
LOG.severe("Not enough tokens in \"" + dateStr
199                     + "\" to create Date: header. Returning null");
200             return null;
201         }
202     } // ** End of method getDateHeader
203

204     /**
205      * Handles a single message, i.e.: 1) Creates a new date header if necessary
206      * (from replacement date) 2) Modifies the Content-Type: header if necessary
207      * 3) Create attachment lists as a "multipart" in the msg, either from lines
208      * stating "Attachment Converted:" or from "X-Attachments" header ... and
209      * then saves the msg to the specified folder
210      *
211      * @param msg
212      * Message incl. both headers and body
213      * @param replDate
214      * Replacement date in a string like "Tue Apr 01 23:17:33 2003"
215      * @param worker
216      * Used for handling user interuption
217      * @param destFolder
218      * Which mail folder inside Columba to import into
219      * @return True on success, false on error
220      */

221     private boolean convertAndSaveMessage(String JavaDoc msg, String JavaDoc replacementDate,
222             IWorkerStatusController worker, IMailbox destFolder) {
223         // divide message into headers and body
224
String JavaDoc[] divided = divideMessage(msg);
225         if (divided == null) {
226             LOG.severe("Error splitting message into headers and body");
227             return false;
228         }
229         String JavaDoc headers = divided[0];
230         String JavaDoc body = divided[1];
231
232         // loop over headers and modify them as needed
233
HeaderTokenizer tokenizer = new HeaderTokenizer(headers);
234         EncodedWord decoder = new EncodedWord();
235         StringBuffer JavaDoc headerBuf = new StringBuffer JavaDoc();
236         boolean dateFound = false;
237         boolean contentTypeFound = false;
238         String JavaDoc line = tokenizer.nextLine();
239         while (line != null) {
240             if (line.indexOf(':') != -1) {
241                 // a header
242
String JavaDoc key = line.substring(0, line.indexOf(':'));
243                 String JavaDoc header = EncodedWord.decode(
244                         (CharSequence JavaDoc) line.substring(line.indexOf(':') + 1)
245                                 .trim()).toString();
246
247                 // handle header
248
if (key.equalsIgnoreCase("Date")) {
249                     // Date header
250
dateFound = true; // we got a date header (store this
251
// fact for later use
252
} else if (key.equalsIgnoreCase("Content-Type")) {
253                     contentTypeFound = true;
254
255                     /*
256                      * For multipart Content-Types we need to take action (if
257                      * boundary is nonexistent): Eudora stores content type =
258                      * multipart even though the message is not really multipart -
259                      * e.g. because an attachment already has has been decoded
260                      * by Eudora)
261                      */

262                     ContentType conType = new ContentType(header); // parse
263
// Content-Type
264
if ((conType.getType().equalsIgnoreCase("multipart"))
265                             && (body.indexOf("--" + conType.getBoundary()) == -1)) {
266                         // boundary not found - Content-Type must be changed
267
if (conType.getSubType()
268                                 .equalsIgnoreCase("alternative")) {
269                             // just convert it to text/plain or text/html
270
header = guessBodyContentType(body);
271                             LOG
272                                     .fine("Content-Type: multipart/alternative replaced with "
273                                             + header);
274                         } else {
275                             /*
276                              * mixed or unknown multipart type (to be treated as
277                              * mixed). This is typically a message with
278                              * attachments. Eudora just stores links to them -
279                              * therefore we create a new multipart/mixed message
280                              * with 2nd part = html page with links to
281                              * attachments
282                              */

283                             String JavaDoc[] split = createAttachmentListFromAttachmentConverted(body);
284                             if ((split == null) || (split.length == 1)) {
285                                 // no attachments found - just convert it to
286
// text/plain or text/html
287
header = guessBodyContentType(body);
288                                 LOG.fine("Content-Type: multipart/"
289                                         + conType.getSubType()
290                                         + " replaced by " + header);
291                             } else {
292                                 header = "multipart/mixed;\n\tboundary="
293                                         + conType.getBoundary();
294                                 body = createBodyFromParts(split, conType
295                                         .getBoundary());
296                                 LOG
297                                         .fine("Content-Type: multipart/mixed. Boundaries added to msg body");
298                             }
299                         }
300                     }
301                 } else if (key.equalsIgnoreCase("X-Attachments")) {
302                     /*
303                      * Such a header is used by Eudora to indicate attachments
304                      * for outgoing messages. Outgoing messages have no
305                      * Content-Type specified. Therefore the Content-Type header
306                      * can be safely set here without risk of conflicts with the
307                      * modifications made above
308                      */

309                     if (header.length() > 0) {
310                         // attachments found
311
String JavaDoc[] split = createAttachmentListFromHeader(body,
312                                 header);
313
314                         if ((split == null) || (split.length == 1)) {
315                             // no attachments found - just insert a
316
// Content-Type header
317
headerBuf.append("MIME-Version: 1.0\n"); // extra
318
// header
319
// necessary
320
key = "Content-Type"; // X-Attachments header is
321
// replaced
322
header = guessBodyContentType(body);
323                             contentTypeFound = true;
324                             LOG
325                                     .fine("X-Attachments header replaced by Content-Type: "
326                                             + header);
327                         } else {
328                             // get unique boundary (not checked against att.
329
// list part - but guess its ok)
330
String JavaDoc unique = getUniqueBoundary(body);
331                             headerBuf.append("MIME-Version: 1.0\n"); // extra
332
// header
333
// necessary
334
key = "Content-Type"; // X-Attachments header is
335
// replaced
336
header = "multipart/mixed;\n\tboundary=" + unique;
337                             contentTypeFound = true; // we have now added
338
// such a header
339
body = createBodyFromParts(split, unique);
340                             LOG
341                                     .fine("X-Attachments header replaced by Content-Type: multipart/mixed");
342                         }
343                     }
344                 }
345
346                 // store header after processing
347
headerBuf.append(key + ": " + header + "\n");
348
349             }
350             line = tokenizer.nextLine();
351         } // ** End of while loop over headers
352

353         /*
354          * If no Date header was found, it is necessary to contruct a new one
355          * (this is the case for outgoing messages from Eudora)
356          */

357         if (!dateFound) {
358             LOG.fine("Date header missing - constructing new one");
359             String JavaDoc dateHeader = getNewDateHeader(replacementDate, TIME_ZONE);
360             if (dateHeader != null)
361                 headerBuf.append(dateHeader + "\n"); // append the new Date
362
// header
363
}
364
365         /*
366          * If no Content-Type header was found, it is necessary to construct a
367          * new one (for outgoing msg Eudora never includes a Content-Type =>
368          * html msg is not shown correctly).
369          */

370         if (!contentTypeFound) {
371             LOG.fine("Content-Type header missing - constructing new one");
372             String JavaDoc contHeader = "Content-Type: " + guessBodyContentType(body);
373             headerBuf.append("MIME-Version: 1.0\n");
374             headerBuf.append(contHeader + "\n");
375         }
376
377         // save message to destination folder
378
return saveMessage(headerBuf.toString(), body, worker, destFolder);
379
380     } // ** End of method convertAndSavemessage
381

382     /**
383      * Used to save messages to destination folder. Called from
384      * convertAndSaveMessage.
385      *
386      * @param headers
387      * Header part of message, without the last "\n" separator (it is
388      * added here)
389      * @param body
390      * Body part of message
391      * @param worker
392      * @param destFolder
393      * Folder in Columba to save message in
394      * @return True on success, false on error
395      */

396     private boolean saveMessage(String JavaDoc headers, String JavaDoc body,
397             IWorkerStatusController worker, IMailbox destFolder) {
398         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
399         // create full msg from headers and body
400
buf.append(headers);
401         buf.append("\n");
402         buf.append(body);
403
404         // ... and save it
405
try {
406             // NB: This is the saveMessage method def. in
407
// DefaultMessageImporter
408
saveMessage(buf.toString(), worker, destFolder);
409             return true;
410         } catch (Exception JavaDoc e) {
411             // Logging.log.severe("Error saving converted message", e);
412
LOG.severe("Error saving converted message: " + e.getMessage());
413             return false;
414         }
415     } // ** End of method saveMessage
416

417     /**
418      * Creates a multipart body from different body parts separated by the given
419      * boundary. The different part must have Content-Type etc. specified, since
420      * this is not done here.
421      *
422      * @param parts
423      * The different body parts (MUST have at least one element
424      * @param boundary
425      * Boundary for separating elements (without beginning "--")
426      * @return The new body
427      */

428     private String JavaDoc createBodyFromParts(String JavaDoc[] parts, String JavaDoc boundary) {
429         // build new message body
430
StringBuffer JavaDoc newBody = new StringBuffer JavaDoc();
431         for (int i = 0; i < parts.length; i++) {
432             newBody.append("--" + boundary + "\n");
433             newBody.append(parts[i]);
434         }
435         newBody.append("--" + boundary + "--\n");
436         return newBody.toString();
437     }
438
439     /**
440      * Generates a boundary, which is unique in relation to the message body. It
441      * is guaranteed that the string ("--" + boundary) is not found in the msg
442      * body
443      *
444      * @param body
445      * The message body
446      * @return A unique boundary
447      */

448     private String JavaDoc getUniqueBoundary(String JavaDoc body) {
449         String JavaDoc boundary = "BOUNDARY"; // initial guess
450
int i = 0;
451         boolean found = true;
452         while (found) {
453             if (body.indexOf("--" + boundary) == -1)
454                 found = false;
455             else {
456                 boundary = boundary + String.valueOf(i);
457                 i++;
458             }
459         }
460         // unique boundary found
461
return boundary;
462     }
463
464     /**
465      * Used to divide a message (RFC822 compliant headers) into headers and
466      * body. Method found in and copied from
467      * org.columba.mail.parser.AbstractParser
468      *
469      * @param input
470      * message to divide
471      * @return Array with [0] = headers and [1] = body (null on error)
472      */

473     private String JavaDoc[] divideMessage(String JavaDoc input) {
474         String JavaDoc[] output = new String JavaDoc[2];
475         int emptyLinePos;
476
477         if (input.length() == 0)
478             return null;
479
480         if (input.charAt(0) == '\n') {
481             output[0] = new String JavaDoc();
482             output[1] = input;
483             return output;
484         }
485
486         emptyLinePos = input.indexOf("\n\n");
487
488         if (input.indexOf("\n\n") != -1) {
489             output[0] = input.substring(0, emptyLinePos + 1);
490             output[1] = input.substring(emptyLinePos + 2);
491         } else {
492             output[0] = input;
493             output[1] = new String JavaDoc();
494         }
495
496         return output;
497     } // ** End of method divideMessage
498

499     /**
500      * Simple method for guessing whether a message body is text/plain or
501      * text/html.
502      *
503      * @param body
504      * The message body
505      * @return The Content-type as "text/html" (possibly with a charset if
506      * found) or "text/plain" (default)
507      */

508     private String JavaDoc guessBodyContentType(String JavaDoc body) {
509         // is it HTML or plain text
510
boolean isHTML = false;
511         if (((body.indexOf("<x-html>") != -1) || (body.indexOf("<X-HTML>") != -1))
512                 && ((body.indexOf("</x-html>") != -1) || (body
513                         .indexOf("</X-HTML>") != -1)))
514             isHTML = true;
515         else if (((body.indexOf("<HTML>") != -1) || (body.indexOf("<html>") != -1))
516                 && ((body.indexOf("</HTML>") != -1) || (body.indexOf("</html>") != -1)))
517             isHTML = true;
518
519         if (!isHTML) {
520             if ((DEFAULT_CHARSET != null) && (DEFAULT_CHARSET.length() > 0))
521                 return "text/plain; charset=" + DEFAULT_CHARSET;
522             else
523                 return "text/plain";
524         } else {
525             /*
526              * It is HTML, try to find out which charset from meta tag: NB: The
527              * seach for charset below is very simple. It assumes that the meta
528              * tag to find is on ITS OWN LINE, i.e. " <meta" can be found at the
529              * beginning of the line, and all the content of the tag is found on
530              * the same line! Could be better, but this is first shot...
531              */

532             BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(body));
533             String JavaDoc line = null;
534             try {
535                 line = reader.readLine();
536             } catch (IOException JavaDoc e) {
537                 // Logging.log.severe("Error while looking for charset", e);
538
LOG
539                         .severe("Error while looking for charset: "
540                                 + e.getMessage());
541             }
542             String JavaDoc charset = null;
543             while (line != null) {
544                 line = line.trim();
545                 if ((line.length() > 5)
546                         && (line.substring(0, 5).equalsIgnoreCase("<meta"))) {
547                     String JavaDoc lcLine = line.toLowerCase(); // for easier search /
548
// matching
549
if ((lcLine.indexOf("http-equiv=content-type") != -1)
550                             || (lcLine.indexOf("http-equiv=\"content-type\"") != -1)) {
551                         // meta tag with content definition found
552
int pos = lcLine.indexOf("charset");
553                         if (pos != -1) {
554                             // charset is specified - find it
555
pos = lcLine.indexOf('=', pos);
556                             pos++;
557                             while (lcLine.charAt(pos) == ' ') {
558                                 pos++;
559                             } // step
560
// past
561
// spaces
562
// find position of '>', '"'. or ' ' which is = end
563
// of charset name
564
int end = lcLine.length();
565                             int tmp = lcLine.indexOf('>', pos);
566                             if (tmp != -1)
567                                 end = tmp;
568                             tmp = lcLine.indexOf('"', pos);
569                             if ((tmp != -1) && (tmp < end))
570                                 end = tmp;
571                             tmp = lcLine.indexOf(' ', pos);
572                             if ((tmp != -1) && (tmp < end))
573                                 end = tmp;
574                             // charset is found from line, not lcLine => not
575
// forced lower case
576
charset = line.substring(pos, end);
577                             break; // we found what we were looking for
578
}
579                     }
580                 }
581                 try {
582                     line = reader.readLine();
583                 } catch (IOException JavaDoc e) {
584                     // Logging.log.severe(
585
// "Error while looking for charset",
586
// e);
587
LOG.severe("Error while looking for charset: "
588                             + e.getMessage());
589                     line = null; // this will terminate the loop
590
}
591             } // end of while loop
592

593             if ((charset != null) && (charset.length() > 0))
594                 return "text/html; charset=" + charset;
595             else {
596                 if ((DEFAULT_CHARSET != null) && (DEFAULT_CHARSET.length() > 0))
597                     return "text/html; charset=" + DEFAULT_CHARSET;
598                 else
599                     return "text/html";
600             }
601         }
602
603     } // ** End of method guessBodyContentType
604

605     /**
606      * Divides a message body into two parts with content types defined: The
607      * message it self and a list of attachments (as html). The attachments are
608      * found as a list of files in a header, separated by ; and not enclosed by ".
609      * If no attachments are found, the body will be left untouched.
610      *
611      * @param body
612      * The message body
613      * @param xAttachments
614      * Header with attachment file names (X-Attachments header)
615      * @return Body in first array entry, attachment list (if present) in second
616      * array entry (null on error)
617      */

618     private String JavaDoc[] createAttachmentListFromHeader(String JavaDoc body,
619             String JavaDoc xAttachments) {
620         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(xAttachments, ";");
621         StringBuffer JavaDoc attachBuf = new StringBuffer JavaDoc();
622         while (tok.hasMoreTokens()) {
623             // handle attachment (by creating a link)
624
String JavaDoc name = tok.nextToken().trim();
625             attachBuf.append("<a HREF=\"file://" + name + "\">" + name
626                     + "</a><br>\n");
627         }
628
629         if (attachBuf.length() == 0) {
630             // no attachments found - should in fact have been checked by the
631
// caller
632
String JavaDoc[] retVal = new String JavaDoc[1];
633             retVal[0] = body; // body untouched
634
return retVal;
635         } else {
636             // attachments found...
637
// insert start and end for html
638
attachBuf
639                     .insert(0,
640                             "<html><head><title>Attachment list</title></head><body><p>\n");
641             attachBuf.append("</p></body></html>\n");
642             // insert header for attachment list
643
String JavaDoc charset;
644             if ((DEFAULT_CHARSET != null) && (DEFAULT_CHARSET.length() > 0))
645                 charset = "; charset=" + DEFAULT_CHARSET;
646             else
647                 charset = "";
648             attachBuf.insert(0, "Content-Type: text/html" + charset
649                     + "; name=\"attachmentlist.html\"\n\n");
650             // build new body part
651
StringBuffer JavaDoc bodyBuf = new StringBuffer JavaDoc();
652             String JavaDoc header = "Content-Type: "
653                     + guessBodyContentType(bodyBuf.toString());
654             bodyBuf.append(header + "\n\n");
655             bodyBuf.append(body);
656             // return parts
657
String JavaDoc[] retVal = new String JavaDoc[2];
658             retVal[0] = bodyBuf.toString();
659             retVal[1] = attachBuf.toString();
660             return retVal;
661         }
662     } // ** End of method createAttachmentListFromHeader
663

664     /**
665      * Divides a message body into two parts with content types defined: The
666      * message it self and a list of attachments (as html). If no attachments
667      * are found, the body will be left untouched.
668      *
669      * @param body
670      * The message body
671      * @return Body in first array entry, attachment list (if present) in second
672      * array entry (null on error)
673      */

674     private String JavaDoc[] createAttachmentListFromAttachmentConverted(String JavaDoc body) {
675         StringBuffer JavaDoc bodyBuf = new StringBuffer JavaDoc();
676         StringBuffer JavaDoc attachBuf = new StringBuffer JavaDoc();
677         BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(body));
678         try {
679             String JavaDoc line = reader.readLine();
680             while (line != null) {
681                 if (line.startsWith("Attachment Converted:")) {
682                     // handle attachment (by creating a link)
683
String JavaDoc name = line.substring(line.indexOf(':') + 1).trim();
684                     if (name.startsWith("\""))
685                         name = name.substring(1, name.length() - 1);
686                     attachBuf.append("<a HREF=\"file://" + name + "\">" + name
687                             + "</a><br>\n");
688                 } else {
689                     // part of body
690
bodyBuf.append(line + "\n");
691                 }
692                 line = reader.readLine();
693             }
694
695             if (attachBuf.length() > 0) {
696                 // attachments found
697

698                 // insert start and end for html
699
attachBuf
700                         .insert(0,
701                                 "<html><head><title>Attachment list</title></head><body><p>\n");
702                 attachBuf.append("</p></body></html>\n");
703                 // insert header for attachment list
704
String JavaDoc charset;
705                 if ((DEFAULT_CHARSET != null) && (DEFAULT_CHARSET.length() > 0))
706                     charset = "; charset=" + DEFAULT_CHARSET;
707                 else
708                     charset = "";
709                 attachBuf.insert(0, "Content-Type: text/html" + charset
710                         + "; name=\"attachmentlist.html\"\n\n");
711
712                 // build new body part
713
String JavaDoc header = "Content-Type: "
714                         + guessBodyContentType(bodyBuf.toString());
715                 bodyBuf.insert(0, header + "\n\n");
716
717                 String JavaDoc[] retVal = new String JavaDoc[2];
718                 retVal[0] = bodyBuf.toString();
719                 retVal[1] = attachBuf.toString();
720                 return retVal;
721             } else {
722                 // no attachments found
723
String JavaDoc[] retVal = new String JavaDoc[1];
724                 retVal[0] = body; // body untouched
725
return retVal;
726             }
727         } catch (IOException JavaDoc e) {
728             // Logging.log.severe("Error parsing body for attachments", e);
729
LOG.severe("Error parsing body for attachments: " + e.getMessage());
730             return null;
731         }
732     } // ** End of method createAttachmentListFromAttachmentConverted
733

734 } // ** End of class EudoraMailImportFilter
735
Popular Tags