KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.suberic.pooka;
2
3 import java.util.Vector JavaDoc;
4 import java.util.StringTokenizer JavaDoc;
5 import java.util.LinkedList JavaDoc;
6 import java.util.Iterator JavaDoc;
7 import java.util.List JavaDoc;
8 import java.util.logging.Logger JavaDoc;
9 import javax.mail.*;
10 import javax.mail.internet.*;
11 import java.io.IOException JavaDoc;
12 import java.io.UnsupportedEncodingException JavaDoc;
13 import java.io.ByteArrayOutputStream JavaDoc;
14 import java.io.InputStream JavaDoc;
15
16 import net.suberic.crypto.EncryptionManager;
17 import net.suberic.crypto.EncryptionUtils;
18
19 public class MailUtilities {
20
21   public MailUtilities() {
22   }
23   
24   /**
25    * This returns the value of an array of Address objects as a String.
26    */

27   public static String JavaDoc decodeAddressString(Address[] addresses) {
28     if (addresses == null)
29       return null;
30     
31     StringBuffer JavaDoc returnValue = new StringBuffer JavaDoc();
32     for (int i = 0; i < addresses.length; i++) {
33       if (addresses[i] != null) {
34         if (i > 0)
35           returnValue.append(", ");
36         if (addresses[i] instanceof javax.mail.internet.InternetAddress JavaDoc)
37           returnValue.append(((javax.mail.internet.InternetAddress JavaDoc)addresses[i]).toUnicodeString());
38         else
39           returnValue.append(addresses[i].toString());
40       }
41     }
42
43     return returnValue.toString();
44   }
45
46   /**
47    * This decoded an RFC 2047 encoded string. If there are any errors
48    * in decoding the string, the raw string is returned.
49    */

50   public static String JavaDoc decodeText(String JavaDoc encodedString) {
51     if (encodedString == null)
52       return null;
53
54     String JavaDoc value = null;
55     try {
56       value = javax.mail.internet.MimeUtility.decodeText(encodedString);
57     } catch (UnsupportedEncodingException JavaDoc e) {
58       // Don't care
59
value = encodedString;
60     }
61     return value;
62   }
63
64   /**
65    * This parses the message given into an AttachmentBundle.
66    */

67   public static AttachmentBundle parseAttachments(Message m) throws MessagingException, java.io.IOException JavaDoc {
68     AttachmentBundle bundle = new AttachmentBundle((MimeMessage)m);
69
70     handlePart((MimeMessage)m, bundle);
71
72     return bundle;
73   }
74   
75   /**
76    * This parses a Mulitpart object into an AttachmentBundle.
77    */

78   public static AttachmentBundle parseAttachments(Multipart mp) throws MessagingException, java.io.IOException JavaDoc {
79     AttachmentBundle bundle = new AttachmentBundle();
80     for (int i = 0; i < mp.getCount(); i++) {
81       MimeBodyPart mbp = (MimeBodyPart)mp.getBodyPart(i);
82       
83       handlePart(mbp, bundle);
84     }
85     return bundle;
86   }
87
88   /**
89    * Handles a MimeBodyPart.
90    */

91   public static void handlePart(MimePart mp, AttachmentBundle bundle) throws MessagingException, java.io.IOException JavaDoc {
92     
93     String JavaDoc encryptionType = EncryptionManager.checkEncryptionType(mp);
94     
95     EncryptionUtils utils = null;
96     if (encryptionType != null) {
97       try {
98         utils = EncryptionManager.getEncryptionUtils(encryptionType);
99       } catch (java.security.NoSuchProviderException JavaDoc nspe) {
100       }
101     }
102     
103     if (utils != null) {
104       
105       int encryptionStatus = utils.getEncryptionStatus(mp);
106
107       if (encryptionStatus == EncryptionUtils.ENCRYPTED) {
108         Attachment newAttach = new net.suberic.pooka.crypto.CryptoAttachment(mp);
109         bundle.addAttachment(newAttach);
110       } else if (encryptionStatus == EncryptionUtils.SIGNED) {
111         // in the case of signed attachments, we should get the wrapped body.
112

113         Attachment newAttach = new net.suberic.pooka.crypto.SignedAttachment(mp);
114
115         MimeBodyPart signedMbp = ((net.suberic.pooka.crypto.SignedAttachment) newAttach).getSignedPart();
116     
117         if (signedMbp != null) {
118           handlePart(signedMbp, bundle);
119         }
120     
121         bundle.addAttachment(newAttach);
122     
123       } else if (encryptionStatus == EncryptionUtils.ATTACHED_KEYS) {
124         bundle.addAttachment(new net.suberic.pooka.crypto.KeyAttachment(mp));
125       } else {
126         // FIXME
127
bundle.addAttachment(new Attachment(mp));
128       }
129       
130     } else {
131       ContentType ct = new ContentType(mp.getContentType());
132       if (ct.getPrimaryType().equalsIgnoreCase("multipart")) {
133         if (mp.getContent() instanceof Multipart) {
134           if (ct.getSubType().equalsIgnoreCase("alternative"))
135             parseAlternativeAttachment(bundle, mp);
136           else
137             bundle.addAll(parseAttachments((Multipart)mp.getContent()));
138         } else {
139           Attachment attachment = new Attachment(mp);
140           bundle.addAttachment(attachment);
141         }
142       } else if (ct.getPrimaryType().equalsIgnoreCase("Message")) {
143         bundle.addAttachment(new Attachment(mp));
144         Object JavaDoc msgContent;
145         msgContent = mp.getContent();
146     
147         if (msgContent instanceof Message)
148           bundle.addAll(parseAttachments((Message)msgContent));
149         else if (msgContent instanceof java.io.InputStream JavaDoc)
150           bundle.addAll(parseAttachments(new MimeMessage(Pooka.getDefaultSession(), (java.io.InputStream JavaDoc)msgContent)));
151         else
152           System.out.println("Error: unsupported Message Type: " + msgContent.getClass().getName());
153     
154       } else {
155         bundle.addAttachment(new Attachment(mp), ct);
156       }
157     }
158   }
159
160   /**
161    * Creates an AlternativeAttachment and adds it properly to the
162    * given AttachmentBundle.
163    */

164   public static void parseAlternativeAttachment(AttachmentBundle bundle, MimePart mbp) throws MessagingException, java.io.IOException JavaDoc {
165     Multipart amp = (Multipart) mbp.getContent();
166     
167     MimeBodyPart altTextPart = null;
168     MimeBodyPart altHtmlPart = null;
169     List JavaDoc extraList = new LinkedList JavaDoc();
170     
171     for (int j = 0; j < amp.getCount(); j++) {
172       MimeBodyPart current = (MimeBodyPart)amp.getBodyPart(j);
173       ContentType ct2 = new ContentType(current.getContentType());
174       if (ct2.match("text/plain") && altTextPart == null)
175         altTextPart = current;
176       else if (ct2.match("text/html") && altHtmlPart == null)
177         altHtmlPart = current;
178       else
179         extraList.add(new Attachment(current));
180     }
181     
182     if (altHtmlPart != null && altTextPart != null) {
183       Attachment attachment = new AlternativeAttachment(altTextPart, altHtmlPart);
184       bundle.addAttachment(attachment);
185       Iterator JavaDoc it = extraList.iterator();
186       while (it.hasNext()) {
187         bundle.addAttachment((Attachment) it.next());
188       }
189     } else {
190       // hurm
191
bundle.addAll(parseAttachments(amp));
192     }
193   }
194   
195   /**
196    * This method takes a given String offset and returns the offset
197    * position at which a line break should occur.
198    *
199    * If no break is necessary, the full buffer length is returned.
200    *
201    */

202   public static int getBreakOffset(String JavaDoc buffer, int breakLength, int tabSize) {
203     // what we'll do is to modify the break length to make it fit tabs.
204

205     int nextTab = buffer.indexOf('\t');
206     int tabAccumulator = 0;
207     int tabAddition = 0;
208     while (nextTab >=0 && nextTab < breakLength) {
209       tabAddition = tabSize - ((tabSize + nextTab + tabAccumulator + 1) % tabSize);
210       breakLength=breakLength - tabAddition;
211       tabAccumulator = tabAccumulator + tabAddition;
212       if (nextTab + 1 < buffer.length())
213         nextTab = buffer.indexOf('\t', nextTab + 1);
214       else
215         nextTab = -1;
216     }
217     
218     
219     if ( buffer.length() <= breakLength ) {
220       return buffer.length();
221     }
222     
223     int breakLocation = -1;
224     for (int caret = breakLength; breakLocation == -1 && caret >= 0; caret--) {
225       if (Character.isWhitespace(buffer.charAt(caret))) {
226         breakLocation=caret + 1;
227         if (breakLocation < buffer.length()) {
228           // check to see if the next character is a line feed of some sort.
229
char nextChar = buffer.charAt(breakLocation);
230           if (nextChar == '\n')
231             breakLocation ++;
232           else if (nextChar == '\r') {
233             if (breakLocation + 1< buffer.length() && buffer.charAt(breakLocation + 1) == '\n') {
234               breakLocation +=2;
235             } else {
236               breakLocation ++;
237             }
238           }
239         }
240       }
241     }
242     
243     if (breakLocation == -1)
244       breakLocation = breakLength;
245     
246     return breakLocation;
247   }
248   
249   /**
250    * This takes a String and word wraps it at length wrapLength. It also will
251    * convert any alternative linebreaks (LF, CR, or CRLF) to the
252    * <code>newLine</code> given.
253    */

254   public static String JavaDoc wrapText(String JavaDoc originalText, int wrapLength, String JavaDoc newLine, int tabSize) {
255     if (originalText == null)
256       return null;
257     
258     Logger.getLogger("Pooka.debug").finest("calling wrapText with wrapLength=" + wrapLength + " on:");
259     Logger.getLogger("Pooka.debug").finest("--- begin text ---");
260     Logger.getLogger("Pooka.debug").finest(originalText);
261     Logger.getLogger("Pooka.debug").finest("--- end text ---");
262     Logger.getLogger("Pooka.debug").finest("");
263
264     StringBuffer JavaDoc wrappedText = new StringBuffer JavaDoc();
265     
266     // so the idea is that we'll get each entry denoted by a line break
267
// and then add soft breaks into there.
268
int currentStart = 0;
269     int nextHardBreak = nextNewLine(originalText, currentStart);
270     while (nextHardBreak != -1) {
271       // get the current string with a newline at the end.
272
String JavaDoc currentString = getSubstringWithNewLine(originalText, currentStart, nextHardBreak, newLine);
273
274       Logger.getLogger("Pooka.debug").finest("current string:");
275       Logger.getLogger("Pooka.debug").finest("--- begin current string ---");
276       Logger.getLogger("Pooka.debug").finest(currentString);
277       Logger.getLogger("Pooka.debug").finest("--- end current string ---");
278       Logger.getLogger("Pooka.debug").finest("");
279       
280       int nextSoftBreak = getBreakOffset(currentString, wrapLength, tabSize);
281       while (nextSoftBreak < currentString.length()) {
282         wrappedText.append(currentString.substring(0, nextSoftBreak));
283         wrappedText.append(newLine);
284
285         Logger.getLogger("Pooka.debug").finest("appending '" + currentString.substring(0, nextSoftBreak) + "', plus newline.");
286
287         currentString = currentString.substring(nextSoftBreak);
288         Logger.getLogger("Pooka.debug").finest("in loop: new current string:");
289         Logger.getLogger("Pooka.debug").finest("--- begin current string ---");
290         Logger.getLogger("Pooka.debug").finest(currentString);
291         Logger.getLogger("Pooka.debug").finest("--- end current string ---");
292         Logger.getLogger("Pooka.debug").finest("");
293       
294         nextSoftBreak = getBreakOffset(currentString, wrapLength, tabSize);
295         Logger.getLogger("Pooka.debug").finest("nextSoftBreak=" + nextSoftBreak);
296       }
297       Logger.getLogger("Pooka.debug").finest("appending '" + currentString + "', which should include newline.");
298       wrappedText.append(currentString);
299       
300       // get the next string including the newline.
301
currentStart = afterNewLine(originalText, nextHardBreak);
302       nextHardBreak= nextNewLine(originalText, currentStart);
303       Logger.getLogger("Pooka.debug").finest("new currentStart = " + currentStart + ", nextHardBreak = " + nextHardBreak);
304     }
305        
306     return wrappedText.toString();
307   }
308   
309   /**
310    * Returns the next new line.
311    */

312   public static int nextNewLine(String JavaDoc text, int start) {
313     if (start >= text.length())
314       return -1;
315
316     // go through each character, looking for \r or \n
317
int foundIndex = -1;
318     for (int i = start; foundIndex == -1 && i < text.length(); i++) {
319       char current = text.charAt(i);
320       if (current == '\r') {
321         if (i + 1 < text.length() && text.charAt(i+1) == '\n')
322           foundIndex = i+1;
323         else
324           foundIndex = i;
325       } else if (current == '\n') {
326         foundIndex = i;
327       }
328     }
329
330     if (foundIndex == -1) {
331       return text.length();
332     } else {
333       return foundIndex;
334     }
335   }
336
337   /**
338    * Returns the position after the newline indicated by index. If
339    * that's the end of the string, or an invalid index is given, returns
340    * an index equal to the length of text (i.e. one more than the last
341    * valid index in text).
342    */

343   public static int afterNewLine(String JavaDoc text, int index) {
344     // if index is invalid, or if index is the last character in the
345
// string, return
346
if (index < 0 || index >= text.length() || index == text.length() -1)
347       return text.length();
348
349     char newLineChar = text.charAt(index);
350     if (newLineChar == '\r' && text.charAt(index + 1) == '\n')
351       return index + 2;
352     else
353       return index + 1;
354   }
355
356   /**
357    * Gets the indicated substring with the given newline.
358    */

359   public static String JavaDoc getSubstringWithNewLine(String JavaDoc originalText, int start, int end, String JavaDoc newLine) {
360     String JavaDoc origSubString = originalText.substring(start,end);
361     Logger.getLogger("Pooka.debug").finest("getSubStringWtihNewLine: origSubString='" + origSubString + "'");
362
363     if (origSubString.endsWith("\r\n")) {
364       if (newLine.equals("\r\n"))
365         return origSubString;
366       else {
367         return origSubString.substring(0, origSubString.length() - 2) + newLine;
368       }
369     } else if (origSubString.endsWith("\n")) {
370       if (newLine.equals("\n"))
371         return origSubString;
372       else
373         return origSubString.substring(0, origSubString.length() - 1) + newLine;
374     } else if (origSubString.endsWith("\r")) {
375       if (newLine.equals("\r"))
376         return origSubString;
377       else
378         return origSubString.substring(0, origSubString.length() - 1) + newLine;
379     } else {
380       return origSubString + newLine;
381     }
382   }
383
384   /**
385    * A convenience method which wraps the given string using the
386    * length specified by Pooka.lineLength.
387    */

388   public static String JavaDoc wrapText(String JavaDoc originalText) {
389     int wrapLength;
390     int tabSize;
391     try {
392       String JavaDoc wrapLengthString = Pooka.getProperty("Pooka.lineLength");
393       wrapLength = Integer.parseInt(wrapLengthString);
394     } catch (Exception JavaDoc e) {
395       wrapLength = 72;
396     }
397     
398     try {
399       String JavaDoc tabSizeString = Pooka.getProperty("Pooka.tabSize", "8");
400       tabSize = Integer.parseInt(tabSizeString);
401     } catch (Exception JavaDoc e) {
402       tabSize = 8;
403     }
404     return wrapText(originalText, wrapLength, "\r\n", tabSize);
405   }
406   
407   /**
408    * Escapes html special characters.
409    */

410   public static String JavaDoc escapeHtml(String JavaDoc input) {
411     char[] characters = input.toCharArray();
412     StringBuffer JavaDoc retVal = new StringBuffer JavaDoc();
413     for (int i = 0; i < characters.length; i++) {
414       if (characters[i] == '&')
415         retVal.append("&amp;");
416       else if (characters[i] == '<')
417         retVal.append("&lt;");
418       else if (characters[i] == '>')
419         retVal.append("&gt;");
420       else
421         retVal.append(characters[i]);
422     }
423     return retVal.toString();
424   }
425
426 }
427
428
429
Popular Tags