1 17 18 package org.apache.james.imapserver.store; 19 20 import org.apache.avalon.framework.logger.AbstractLogEnabled; 21 import org.apache.james.util.RFC822DateFormat; 22 import org.apache.mailet.MailAddress; 23 24 import javax.mail.BodyPart ; 25 import javax.mail.MessagingException ; 26 import javax.mail.internet.AddressException ; 27 import javax.mail.internet.InternetAddress ; 28 import javax.mail.internet.MimeMessage ; 29 import javax.mail.internet.MimeMultipart ; 30 import javax.mail.internet.MimePart ; 31 import javax.mail.internet.ParseException ; 32 import java.util.ArrayList ; 33 import java.util.Date ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Set ; 38 39 49 public class SimpleMessageAttributes 50 extends AbstractLogEnabled 51 implements ImapMessageAttributes 52 { 53 54 private final static String SP = " "; 55 private final static String NIL = "NIL"; 56 private final static String Q = "\""; 57 private final static String LB = "("; 58 private final static String RB = ")"; 59 private final static boolean DEBUG = false; 60 private final static String MULTIPART = "MULTIPART"; 61 private final static String MESSAGE = "MESSAGE"; 62 63 private int uid; 64 private int messageSequenceNumber; 65 private Date internalDate; 66 private String internalDateString; 67 private String bodyStructure; 68 private String envelope; 69 private int size; 70 private int lineCount; 71 public ImapMessageAttributes[] parts; 72 private List headers; 73 74 private String subject; 77 private String [] from; 78 private String [] sender; 79 private String [] replyTo; 80 private String [] to; 81 private String [] cc; 82 private String [] bcc; 83 private String [] inReplyTo; 84 private String [] date; 85 private String [] messageID; 86 private String contentType; 87 private String primaryType; private String secondaryType; private Set parameters; private String contentID; 91 private String contentDesc; 92 private String contentEncoding; 93 94 SimpleMessageAttributes() { 95 } 96 97 void setAttributesFor(MimeMessage msg) throws MessagingException { 98 size = msg.getSize(); 99 try { 100 internalDate = msg.getSentDate(); 101 } catch (MessagingException me) { 102 internalDate = new Date (); 103 } 104 105 internalDateString = RFC822DateFormat.toString(internalDate); parseMimePart(msg); 107 envelope = null; 108 bodyStructure = null; 109 } 110 111 void setUID(int thisUID) { 112 uid = thisUID; 113 } 114 115 119 void parseMimePart(MimePart part) { 120 if (part instanceof MimeMessage ) { 122 try { 123 subject = ((MimeMessage )part).getSubject(); 124 } catch (MessagingException me) { 125 if (DEBUG) getLogger().debug("Messaging Exception for getSubject: " + me); 126 } 127 } 128 try { 129 from = part.getHeader("From"); 130 } catch (MessagingException me) { 131 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(From): " + me); 132 } 133 try { 134 sender = part.getHeader("Sender"); 135 } catch (MessagingException me) { 136 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(Sender): " + me); 137 } 138 try { 139 replyTo = part.getHeader("Reply To"); 140 } catch (MessagingException me) { 141 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(Reply To): " + me); 142 } 143 try { 144 to = part.getHeader("To"); 145 } catch (MessagingException me) { 146 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(To): " + me); 147 } 148 try { 149 cc = part.getHeader("Cc"); 150 } catch (MessagingException me) { 151 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(To): " + me); 152 } 153 try { 154 bcc = part.getHeader("Bcc"); 155 } catch (MessagingException me) { 156 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(To): " + me); 157 } 158 try { 159 inReplyTo = part.getHeader("In Reply To"); 160 } catch (MessagingException me) { 161 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(In Reply To): " + me); 162 } 163 try { 164 date = part.getHeader("Date"); 165 } catch (MessagingException me) { 166 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(Date): " + me); 167 } 168 try { 169 messageID = part.getHeader("Message-ID"); 170 } catch (MessagingException me) { 171 if (DEBUG) getLogger().debug("Messaging Exception for getHeader(messageID): " + me); 172 } 173 String contentTypeLine = null; 174 try { 175 contentTypeLine = part.getContentType(); 176 } catch (MessagingException me) { 177 if (DEBUG) getLogger().debug("Messaging Exception for getContentType(): " + me); 178 } 179 if (contentTypeLine !=null ) { 180 decodeContentType(contentTypeLine); 181 } 182 try { 183 contentID = part.getContentID(); 184 } catch (MessagingException me) { 185 if (DEBUG) getLogger().debug("Messaging Exception for getContentUD(): " + me); 186 } 187 try { 188 contentDesc = part.getDescription(); 189 } catch (MessagingException me) { 190 if (DEBUG) getLogger().debug("Messaging Exception for getDescription(): " + me); 191 } 192 try { 193 contentEncoding = part.getEncoding(); 194 if ( contentEncoding == null ) { 196 contentEncoding = "7BIT"; 197 } 198 } catch (MessagingException me) { 199 if (DEBUG) getLogger().debug("Messaging Exception for getEncoding(): " + me); 200 } 201 if (DEBUG) { 202 try { 203 String contentDisposition = part.getDisposition(); 204 } catch (MessagingException me) { 205 getLogger().debug("Messaging Exception for getEncoding(): " + me); 206 } 207 } 208 209 try { 210 lineCount = part.getLineCount(); 212 } catch (MessagingException me) { 213 if (DEBUG) getLogger().debug("Messaging Exception for getLineCount(): " + me); 214 } catch (Exception e) { 215 if (DEBUG) getLogger().debug("Exception for getLineCount(): " + e); 216 } 217 218 if (primaryType.equalsIgnoreCase(MULTIPART)) { 220 MimeMultipart container; 221 try { 222 container =(MimeMultipart ) part.getContent(); 223 int count = container.getCount(); 224 parts = new SimpleMessageAttributes[count]; 225 for (int i = 0; i < count ; i ++) { 226 BodyPart nextPart = container.getBodyPart(i); 227 228 if (nextPart instanceof MimePart ) { 229 SimpleMessageAttributes partAttrs = new SimpleMessageAttributes(); 230 setupLogger(partAttrs); partAttrs.parseMimePart((MimePart )nextPart); 232 parts[i] = partAttrs; 233 234 } else { 235 getLogger().info("Found a non-Mime bodyPart"); 236 } 237 } 238 } catch (Exception e) { 239 getLogger().debug("Messaging Exception for getContent(): " + e); 240 e.printStackTrace(); 241 } 242 } else if (primaryType.equalsIgnoreCase("message")) { 243 getLogger().info("This part contains an embedded message of subtype: " + secondaryType); 244 getLogger().info("Uses java class: " + part.getClass().getName()); 245 if (secondaryType.equalsIgnoreCase("RFC822")) { 246 248 264 } else { 269 getLogger().info("Unknown subtype of message encountered."); 270 System.out.println("Unknown subtype of message encountered."); 271 } 272 } 273 else { 274 System.out.println("parseMimePart: its just a plain message"); 275 } 276 } 277 278 281 String parseEnvelope() { 282 List response = new ArrayList (); 283 response.add( LB + Q + internalDateString + Q + SP); 284 if (subject != null && (!subject.equals(""))) { 285 response.add( Q + subject + Q + SP ); 286 } else { 287 response.add( NIL + SP ); 288 } 289 if (from != null && from.length > 0) { 290 response.add(LB); 291 for (int i=0; i<from.length; i++) { 292 response.add(parseAddress( from[i]) ); 293 } 294 response.add(RB); 295 } else { 296 response.add( NIL); 297 } 298 response.add(SP); 299 if (sender != null && sender.length >0) { 300 if (DEBUG) getLogger().debug("parsingEnvelope - sender[0] is: " + sender[0]); 301 if (sender[0].indexOf("@") == -1) { 303 response.add(LB + (String )response.get(3) + RB); } else { 305 response.add(LB); 306 for (int i=0; i<sender.length; i++) { 307 response.add( parseAddress(sender[i])); 308 } 309 response.add(RB); 310 } 311 } else { 312 if (from != null && from.length > 0) { 313 response.add(LB + (String )response.get(3) + RB); } else { 315 response.add( NIL); 316 } 317 } 318 response.add(SP); 319 if (replyTo != null && replyTo.length >0) { 320 if (replyTo[0].indexOf("@") == -1) { 321 response.add(LB + (String )response.get(3) + RB); } else { 323 response.add(LB); 324 for (int i=0; i<replyTo.length; i++) { 325 response.add( parseAddress(replyTo[i])); 326 } 327 response.add(RB); 328 } 329 } else { 330 if (from != null && from.length > 0) { 331 response.add(LB + (String )response.get(3) + RB); } else { 333 response.add( NIL); 334 } 335 } 336 response.add(SP); 337 if (to != null && to.length >0) { 338 response.add(LB); 339 for (int i=0; i<to.length; i++) { 340 response.add( parseAddress(to[i])); 341 } 342 response.add(RB); 343 } else { 344 response.add( NIL); 345 } 346 response.add(SP); 347 if (cc != null && cc.length >0) { 348 response.add(LB); 349 for (int i=0; i<cc.length; i++) { 350 response.add( parseAddress(cc[i])); 351 } 352 response.add(RB); 353 } else { 354 response.add( NIL); 355 } 356 response.add(SP); 357 if (bcc != null && bcc.length >0) { 358 response.add(LB); 359 for (int i=0; i<bcc.length; i++) { 360 response.add( parseAddress(bcc[i])); 361 } 362 response.add(RB); 363 } else { 364 response.add( NIL); 365 } 366 response.add(SP); 367 if (inReplyTo != null && inReplyTo.length>0) { 368 response.add( inReplyTo[0]); 369 } else { 370 response.add( NIL); 371 } 372 response.add(SP); 373 if (messageID != null && messageID.length>0) { 374 response.add(Q + messageID[0] + Q); 375 } else { 376 response.add( NIL); 377 } 378 response.add(RB); 379 380 StringBuffer buf = new StringBuffer (16 * response.size()); 381 for (int j=0; j<response.size(); j++) { 382 buf.append((String )response.get(j)); 383 } 384 385 return buf.toString(); 386 } 387 388 391 String parseAddress(String address) { 392 int comma = address.indexOf(","); 393 StringBuffer buf = new StringBuffer (); 394 if (comma == -1) { buf.append(LB); 396 InternetAddress netAddr = null; 397 try { 398 netAddr = new InternetAddress (address); 399 } catch (AddressException ae) { 400 return null; 401 } 402 String personal = netAddr.getPersonal(); 403 if (personal != null && (!personal.equals(""))) { 404 buf.append(Q + personal + Q); 405 } else { 406 buf.append( NIL); 407 } 408 buf.append( SP); 409 buf.append( NIL) ; buf.append( SP); 411 try { 412 MailAddress mailAddr = new MailAddress(netAddr); 413 buf.append(Q + mailAddr.getUser() + Q); 414 buf.append(SP); 415 buf.append(Q + mailAddr.getHost() + Q); 416 } catch (ParseException pe) { 417 buf.append( NIL + SP + NIL); 418 } 419 buf.append(RB); 420 } else { 421 buf.append(parseAddress(address.substring(0, comma))); 422 buf.append(SP); 423 buf.append(parseAddress(address.substring(comma + 1))); 424 } 425 return buf.toString(); 426 } 427 428 431 void decodeContentType(String rawLine) { 432 int slash = rawLine.indexOf("/"); 433 if( slash == -1){ 434 if (DEBUG) getLogger().debug("decoding ... no slash found"); 435 return; 436 } else { 437 primaryType = rawLine.substring(0, slash).trim(); 438 } 439 int semicolon = rawLine.indexOf(";"); 440 if (semicolon == -1) { 441 if (DEBUG) getLogger().debug("decoding ... no semicolon found"); 442 secondaryType = rawLine.substring(slash + 1).trim(); 443 return; 444 } 445 parameters = new HashSet (); 447 secondaryType = rawLine.substring(slash + 1, semicolon).trim(); 448 int pos = semicolon; 449 int nextsemi = rawLine.indexOf(";", pos+1); 450 while (nextsemi != -1) { 451 if (DEBUG) getLogger().debug("decoding ... found another semicolon"); 452 String param = rawLine.substring(pos + 1, nextsemi); 453 int esign = param.indexOf("=") ; 454 if (esign == -1) { 455 if (DEBUG) getLogger().debug("Whacky parameter found: " + param); 456 } else { 457 String name = param.substring(0, esign).trim(); 458 String value = param.substring(esign + 1).trim(); 459 parameters.add(name + SP + value); 460 if (DEBUG) getLogger().debug("Found parameter: " + name + SP + value); 461 } 462 pos = nextsemi; 463 nextsemi = rawLine.indexOf(";", pos +1); 464 } 465 String lastParam = rawLine.substring(pos + 1); 466 int esign = lastParam.indexOf("=") ; 467 if (esign == -1) { 468 if (DEBUG) getLogger().debug("Whacky parameter found: " + lastParam); 469 } else { 470 String name = lastParam.substring(0, esign).trim(); 471 String value = lastParam.substring(esign + 1).trim(); 472 parameters.add(Q + name + Q + SP + Q + value + Q); 473 if (DEBUG) getLogger().debug("Found parameter: " + name + SP + value); 474 } 475 } 476 477 String parseBodyFields() { 478 StringBuffer buf = new StringBuffer (); 479 if (parameters == null || parameters.isEmpty()) { 480 buf.append(NIL); 481 } else { 482 buf.append(LB); 483 Iterator it = parameters.iterator(); 484 while(it.hasNext()) { 485 buf.append((String )it.next()); 486 } 487 buf.append(RB); 488 } 489 buf.append(SP); 490 if(contentID == null) { 491 buf.append(NIL); 492 } else { 493 buf.append(Q + contentID + Q); 494 } 495 buf.append(SP); 496 if(contentDesc == null) { 497 buf.append(NIL); 498 } else { 499 buf.append(Q + contentDesc + Q); 500 } 501 buf.append(SP); 502 if(contentEncoding == null) { 503 buf.append( NIL ); 504 } else { 505 buf.append(Q + contentEncoding + Q); 506 } 507 buf.append(SP); 508 buf.append(size); 509 return buf.toString(); 510 } 511 512 516 String parseBodyStructure() { 517 try { 518 String fields = parseBodyFields(); 519 StringBuffer buf = new StringBuffer (); 520 buf.append(LB); 521 if (primaryType.equalsIgnoreCase("Text")) { 522 buf.append("\"TEXT\" \"" ); 523 buf.append( secondaryType.toUpperCase() ); 524 buf.append( "\" "); 525 buf.append( fields ); 526 buf.append( " " ); 527 buf.append( lineCount ); 528 529 533 } else if (primaryType.equalsIgnoreCase(MESSAGE) && secondaryType.equalsIgnoreCase("rfc822")) { 534 buf.append("\"MESSAGE\" \"RFC822\" "); 535 buf.append(fields + SP); 536 setupLogger(parts[0]); buf.append(parts[0].getEnvelope() + SP); 538 buf.append(parts[0].getBodyStructure( false ) + SP); 539 buf.append(lineCount); 540 } else if (primaryType.equalsIgnoreCase(MULTIPART)) { 541 for (int i=0; i<parts.length; i++) { 542 setupLogger(parts[i]); buf.append(parts[i].getBodyStructure( false )); 544 } 545 buf.append(SP + secondaryType); 546 } 547 buf.append(RB); 548 return buf.toString(); 549 } catch (Exception e) { 550 getLogger().error("Exception while parsing BodyStrucuture: " + e); 551 e.printStackTrace(); 552 throw new RuntimeException ("Exception in parseBodyStructure"); 553 } 554 } 555 556 562 public int getMessageSequenceNumber() { 563 return messageSequenceNumber; 564 } 565 566 void setMessageSequenceNumber(int newMsn) { 567 messageSequenceNumber = newMsn; 568 } 569 570 571 580 public int getUID() { 581 return uid; 582 } 583 584 595 public Date getInternalDate() { 596 return internalDate; 597 } 598 599 public String getInternalDateAsString() { 600 return internalDateString; 601 } 602 603 608 public int getSize() { 609 return size; 610 } 611 612 617 public String getEnvelope() { 618 return parseEnvelope(); 619 } 620 621 626 public String getBodyStructure( boolean includeExtensions ) { 627 return parseBodyStructure(); 628 } 629 } 630 | Popular Tags |