1 package net.suberic.pooka; 2 3 import java.util.Vector ; 4 import java.util.StringTokenizer ; 5 import java.util.LinkedList ; 6 import java.util.Iterator ; 7 import java.util.List ; 8 import java.util.logging.Logger ; 9 import javax.mail.*; 10 import javax.mail.internet.*; 11 import java.io.IOException ; 12 import java.io.UnsupportedEncodingException ; 13 import java.io.ByteArrayOutputStream ; 14 import java.io.InputStream ; 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 27 public static String decodeAddressString(Address[] addresses) { 28 if (addresses == null) 29 return null; 30 31 StringBuffer returnValue = new StringBuffer (); 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 ) 37 returnValue.append(((javax.mail.internet.InternetAddress )addresses[i]).toUnicodeString()); 38 else 39 returnValue.append(addresses[i].toString()); 40 } 41 } 42 43 return returnValue.toString(); 44 } 45 46 50 public static String decodeText(String encodedString) { 51 if (encodedString == null) 52 return null; 53 54 String value = null; 55 try { 56 value = javax.mail.internet.MimeUtility.decodeText(encodedString); 57 } catch (UnsupportedEncodingException e) { 58 value = encodedString; 60 } 61 return value; 62 } 63 64 67 public static AttachmentBundle parseAttachments(Message m) throws MessagingException, java.io.IOException { 68 AttachmentBundle bundle = new AttachmentBundle((MimeMessage)m); 69 70 handlePart((MimeMessage)m, bundle); 71 72 return bundle; 73 } 74 75 78 public static AttachmentBundle parseAttachments(Multipart mp) throws MessagingException, java.io.IOException { 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 91 public static void handlePart(MimePart mp, AttachmentBundle bundle) throws MessagingException, java.io.IOException { 92 93 String 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 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 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 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 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 ) 150 bundle.addAll(parseAttachments(new MimeMessage(Pooka.getDefaultSession(), (java.io.InputStream )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 164 public static void parseAlternativeAttachment(AttachmentBundle bundle, MimePart mbp) throws MessagingException, java.io.IOException { 165 Multipart amp = (Multipart) mbp.getContent(); 166 167 MimeBodyPart altTextPart = null; 168 MimeBodyPart altHtmlPart = null; 169 List extraList = new LinkedList (); 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 it = extraList.iterator(); 186 while (it.hasNext()) { 187 bundle.addAttachment((Attachment) it.next()); 188 } 189 } else { 190 bundle.addAll(parseAttachments(amp)); 192 } 193 } 194 195 202 public static int getBreakOffset(String buffer, int breakLength, int tabSize) { 203 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 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 254 public static String wrapText(String originalText, int wrapLength, String 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 wrappedText = new StringBuffer (); 265 266 int currentStart = 0; 269 int nextHardBreak = nextNewLine(originalText, currentStart); 270 while (nextHardBreak != -1) { 271 String 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 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 312 public static int nextNewLine(String text, int start) { 313 if (start >= text.length()) 314 return -1; 315 316 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 343 public static int afterNewLine(String text, int index) { 344 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 359 public static String getSubstringWithNewLine(String originalText, int start, int end, String newLine) { 360 String 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 388 public static String wrapText(String originalText) { 389 int wrapLength; 390 int tabSize; 391 try { 392 String wrapLengthString = Pooka.getProperty("Pooka.lineLength"); 393 wrapLength = Integer.parseInt(wrapLengthString); 394 } catch (Exception e) { 395 wrapLength = 72; 396 } 397 398 try { 399 String tabSizeString = Pooka.getProperty("Pooka.tabSize", "8"); 400 tabSize = Integer.parseInt(tabSizeString); 401 } catch (Exception e) { 402 tabSize = 8; 403 } 404 return wrapText(originalText, wrapLength, "\r\n", tabSize); 405 } 406 407 410 public static String escapeHtml(String input) { 411 char[] characters = input.toCharArray(); 412 StringBuffer retVal = new StringBuffer (); 413 for (int i = 0; i < characters.length; i++) { 414 if (characters[i] == '&') 415 retVal.append("&"); 416 else if (characters[i] == '<') 417 retVal.append("<"); 418 else if (characters[i] == '>') 419 retVal.append(">"); 420 else 421 retVal.append(characters[i]); 422 } 423 return retVal.toString(); 424 } 425 426 } 427 428 429 | Popular Tags |