1 17 18 package org.apache.james.core; 19 20 import javax.activation.DataHandler ; 21 import javax.mail.Address ; 22 import javax.mail.Flags ; 23 import javax.mail.Header ; 24 import javax.mail.Message ; 25 import javax.mail.MessagingException ; 26 import javax.mail.Multipart ; 27 import javax.mail.Session ; 28 import javax.mail.internet.InternetAddress ; 29 import javax.mail.internet.InternetHeaders ; 30 import javax.mail.internet.MimeMessage ; 31 import javax.mail.internet.MimeUtility ; 32 import javax.mail.internet.NewsAddress ; 33 import java.io.BufferedWriter ; 34 import java.io.ByteArrayInputStream ; 35 import java.io.InputStream ; 36 import java.io.InputStreamReader ; 37 import java.io.IOException ; 38 import java.io.LineNumberReader ; 39 import java.io.OutputStream ; 40 import java.io.OutputStreamWriter ; 41 import java.io.PrintWriter ; 42 import java.io.SequenceInputStream ; 43 import java.io.UnsupportedEncodingException ; 44 import java.text.ParseException ; 45 import java.util.ArrayList ; 46 import java.util.Date ; 47 import java.util.Enumeration ; 48 49 import org.apache.james.util.InternetPrintWriter; 50 import org.apache.james.util.RFC2822Headers; 51 import org.apache.james.util.RFC822DateFormat; 52 53 import org.apache.avalon.framework.activity.Disposable; 54 import org.apache.avalon.excalibur.io.IOUtil; 55 56 61 public class MimeMessageWrapper 62 extends MimeMessage 63 implements Disposable { 64 65 68 MimeMessageSource source = null; 69 72 MailHeaders headers = null; 73 76 MimeMessage message = null; 77 80 boolean modified = false; 81 84 RFC822DateFormat mailDateFormat = new RFC822DateFormat(); 85 86 92 public MimeMessageWrapper(MimeMessageSource source) { 93 super(Session.getDefaultInstance(System.getProperties(), null)); 94 this.source = source; 95 } 96 97 102 public String getSourceId() { 103 return source.getSourceId(); 104 } 105 106 112 private synchronized void loadHeaders() throws MessagingException { 113 if (headers != null) { 114 return; 116 } 117 try { 118 InputStream in = source.getInputStream(); 119 try { 120 headers = new MailHeaders(in); 121 } finally { 122 IOUtil.shutdownStream(in); 123 } 124 } catch (IOException ioe) { 125 throw new MessagingException ("Unable to parse headers from stream: " + ioe.getMessage(), ioe); 126 } 127 } 128 129 135 private synchronized void loadMessage() throws MessagingException { 136 if (message != null) { 137 return; 139 } 140 InputStream in = null; 141 try { 142 in = source.getInputStream(); 143 headers = new MailHeaders(in); 144 145 ByteArrayInputStream headersIn 146 = new ByteArrayInputStream (headers.toByteArray()); 147 in = new SequenceInputStream (headersIn, in); 148 149 message = new MimeMessage (session, in); 150 } catch (IOException ioe) { 151 throw new MessagingException ("Unable to parse stream: " + ioe.getMessage(), ioe); 152 } finally { 153 IOUtil.shutdownStream(in); 154 } 155 } 156 157 160 private Address [] getAddressHeader(String name) throws MessagingException { 161 String addr = getHeader(name, ","); 162 if (addr == null) { 163 return null; 164 } else { 165 return InternetAddress.parse(addr); 166 } 167 } 168 169 170 173 private String getHeaderName(Message.RecipientType recipienttype) throws MessagingException { 174 String s; 175 if (recipienttype == Message.RecipientType.TO) { 176 s = RFC2822Headers.TO; 177 } else if (recipienttype == Message.RecipientType.CC) { 178 s = RFC2822Headers.CC; 179 } else if (recipienttype == Message.RecipientType.BCC) { 180 s = RFC2822Headers.BCC; 181 } else if (recipienttype == RecipientType.NEWSGROUPS) { 182 s = "Newsgroups"; 183 } else { 184 throw new MessagingException ("Invalid Recipient Type"); 185 } 186 return s; 187 } 188 189 190 195 public boolean isModified() { 196 return modified; 197 } 198 199 202 public void writeTo(OutputStream os) throws IOException , MessagingException { 203 if (message == null || !isModified()) { 204 InputStream in = source.getInputStream(); 207 try { 208 copyStream(in, os); 209 } finally { 210 IOUtil.shutdownStream(in); 211 } 212 } else { 213 writeTo(os, os); 214 } 215 } 216 217 220 public void writeTo(OutputStream os, String [] ignoreList) throws IOException , MessagingException { 221 writeTo(os, os, ignoreList); 222 } 223 224 227 public void writeTo(OutputStream headerOs, OutputStream bodyOs) throws IOException , MessagingException { 228 writeTo(headerOs, bodyOs, new String [0]); 229 } 230 231 public void writeTo(OutputStream headerOs, OutputStream bodyOs, String [] ignoreList) throws IOException , MessagingException { 232 if (message == null || !isModified()) { 233 236 InputStream in = source.getInputStream(); 238 try { 239 InternetHeaders headers = new InternetHeaders (in); 240 PrintWriter pos = new InternetPrintWriter(new BufferedWriter (new OutputStreamWriter (headerOs), 512), true); 241 for (Enumeration e = headers.getNonMatchingHeaderLines(ignoreList); e.hasMoreElements(); ) { 242 String header = (String )e.nextElement(); 243 pos.println(header); 244 } 245 pos.println(); 246 pos.flush(); 247 copyStream(in, bodyOs); 248 } finally { 249 IOUtil.shutdownStream(in); 250 } 251 } else { 252 writeTo(message, headerOs, bodyOs, ignoreList); 253 } 254 } 255 256 260 public static void writeTo(MimeMessage message, OutputStream headerOs, OutputStream bodyOs) throws IOException , MessagingException { 261 writeTo(message, headerOs, bodyOs, null); 262 } 263 264 268 public static void writeTo(MimeMessage message, OutputStream headerOs, OutputStream bodyOs, String [] ignoreList) throws IOException , MessagingException { 269 if (message instanceof MimeMessageWrapper) { 270 MimeMessageWrapper wrapper = (MimeMessageWrapper)message; 271 wrapper.writeTo(headerOs, bodyOs, ignoreList); 272 } else { 273 if(message.getMessageID() == null) { 274 message.saveChanges(); 275 } 276 277 Enumeration headers = message.getNonMatchingHeaderLines(ignoreList); 279 PrintWriter hos = new InternetPrintWriter(new BufferedWriter (new OutputStreamWriter (headerOs), 512), true); 280 while (headers.hasMoreElements()) { 281 hos.println((String )headers.nextElement()); 282 } 283 hos.println(); 285 hos.flush(); 286 287 InputStream bis = null; 288 OutputStream bos = null; 289 291 308 309 try { 310 bos = MimeUtility.encode(bodyOs, message.getEncoding()); 315 bis = message.getInputStream(); 316 } catch(javax.activation.UnsupportedDataTypeException udte) { 317 336 337 try { 338 bis = message.getRawInputStream(); 339 bos = bodyOs; 340 } catch(javax.mail.MessagingException _) { 341 throw udte; 342 } 343 } 344 catch(javax.mail.MessagingException me) { 345 355 try { 356 bis = message.getRawInputStream(); 357 bos = bodyOs; 358 } catch(javax.mail.MessagingException _) { 359 throw me; 360 } 361 } 362 363 try { 364 copyStream(bis, bos); 365 } 366 finally { 367 IOUtil.shutdownStream(bis); 368 } 369 } 370 } 371 372 375 public Address [] getFrom() throws MessagingException { 376 if (headers == null) { 377 loadHeaders(); 378 } 379 Address from[] = getAddressHeader(RFC2822Headers.FROM); 380 if(from == null) { 381 from = getAddressHeader(RFC2822Headers.SENDER); 382 } 383 return from; 384 } 385 386 public Address [] getRecipients(Message.RecipientType type) throws MessagingException { 387 if (headers == null) { 388 loadHeaders(); 389 } 390 if (type == RecipientType.NEWSGROUPS) { 391 String s = headers.getHeader("Newsgroups", ","); 392 if(s == null) { 393 return null; 394 } else { 395 return NewsAddress.parse(s); 396 } 397 } else { 398 return getAddressHeader(getHeaderName(type)); 399 } 400 } 401 402 public Address [] getAllRecipients() throws MessagingException { 403 if (headers == null) { 404 loadHeaders(); 405 } 406 Address toAddresses[] = getRecipients(RecipientType.TO); 407 Address ccAddresses[] = getRecipients(RecipientType.CC); 408 Address bccAddresses[] = getRecipients(RecipientType.BCC); 409 Address newsAddresses[] = getRecipients(RecipientType.NEWSGROUPS); 410 if(ccAddresses == null && bccAddresses == null && newsAddresses == null) { 411 return toAddresses; 412 } 413 int i = (toAddresses == null ? 0 : toAddresses.length) 414 + (ccAddresses == null ? 0 : ccAddresses.length) 415 + (bccAddresses == null ? 0 : bccAddresses.length) 416 + (newsAddresses == null ? 0 : newsAddresses.length); 417 Address allAddresses[] = new Address [i]; 418 int j = 0; 419 if (toAddresses != null) { 420 System.arraycopy(toAddresses, 0, allAddresses, j, toAddresses.length); 421 j += toAddresses.length; 422 } 423 if(ccAddresses != null) { 424 System.arraycopy(ccAddresses, 0, allAddresses, j, ccAddresses.length); 425 j += ccAddresses.length; 426 } 427 if(bccAddresses != null) { 428 System.arraycopy(bccAddresses, 0, allAddresses, j, bccAddresses.length); 429 j += bccAddresses.length; 430 } 431 if(newsAddresses != null) { 432 System.arraycopy(newsAddresses, 0, allAddresses, j, newsAddresses.length); 433 j += newsAddresses.length; 434 } 435 return allAddresses; 436 } 437 438 public Address [] getReplyTo() throws MessagingException { 439 if (headers == null) { 440 loadHeaders(); 441 } 442 Address replyTo[] = getAddressHeader(RFC2822Headers.REPLY_TO); 443 if(replyTo == null) { 444 replyTo = getFrom(); 445 } 446 return replyTo; 447 } 448 449 public String getSubject() throws MessagingException { 450 if (headers == null) { 451 loadHeaders(); 452 } 453 String subject = getHeader(RFC2822Headers.SUBJECT, null); 454 if (subject == null) { 455 return null; 456 } 457 try { 458 return MimeUtility.decodeText(subject); 459 } catch(UnsupportedEncodingException _ex) { 460 return subject; 461 } 462 } 463 464 public Date getSentDate() throws MessagingException { 465 if (headers == null) { 466 loadHeaders(); 467 } 468 String header = getHeader(RFC2822Headers.DATE, null); 469 if(header != null) { 470 try { 471 return mailDateFormat.parse(header); 472 } catch(ParseException _ex) { 473 return null; 474 } 475 } else { 476 return null; 477 } 478 } 479 480 485 public Date getReceivedDate() throws MessagingException { 486 if (headers == null) { 487 loadHeaders(); 488 } 489 return null; 490 } 491 492 497 public int getSize() throws MessagingException { 498 if (message == null) { 499 loadMessage(); 500 } 501 return message.getSize(); 502 } 503 504 509 public int getLineCount() throws MessagingException { 510 InputStream in=null; 511 try{ 512 in = getContentStream(); 513 }catch(Exception e){ 514 return -1; 515 } 516 if (in == null) { 517 return -1; 518 } 519 try { 522 LineNumberReader counter = new LineNumberReader (new InputStreamReader (in, getEncoding())); 523 char[] block = new char[4096]; 525 while (counter.read(block) > -1) { 526 } 528 return counter.getLineNumber(); 529 } catch (IOException ioe) { 530 return -1; 531 } finally { 532 IOUtil.shutdownStream(in); 533 } 534 } 535 536 541 public long getMessageSize() throws MessagingException { 542 try { 543 return source.getMessageSize(); 544 } catch (IOException ioe) { 545 throw new MessagingException ("Error retrieving message size", ioe); 546 } 547 } 548 549 public String getContentType() throws MessagingException { 550 if (headers == null) { 551 loadHeaders(); 552 } 553 String value = getHeader(RFC2822Headers.CONTENT_TYPE, null); 554 if (value == null) { 555 return "text/plain"; 556 } else { 557 return value; 558 } 559 } 560 561 public boolean isMimeType(String mimeType) throws MessagingException { 562 if (message == null) { 563 loadMessage(); 564 } 565 return message.isMimeType(mimeType); 566 } 567 568 public String getDisposition() throws MessagingException { 569 if (message == null) { 570 loadMessage(); 571 } 572 return message.getDisposition(); 573 } 574 575 public String getEncoding() throws MessagingException { 576 if (message == null) { 577 loadMessage(); 578 } 579 return message.getEncoding(); 580 } 581 582 public String getContentID() throws MessagingException { 583 if (headers == null) { 584 loadHeaders(); 585 } 586 return getHeader("Content-Id", null); 587 } 588 589 public String getContentMD5() throws MessagingException { 590 if (headers == null) { 591 loadHeaders(); 592 } 593 return getHeader("Content-MD5", null); 594 } 595 596 public String getDescription() throws MessagingException { 597 if (message == null) { 598 loadMessage(); 599 } 600 return message.getDescription(); 601 } 602 603 public String [] getContentLanguage() throws MessagingException { 604 if (message == null) { 605 loadMessage(); 606 } 607 return message.getContentLanguage(); 608 } 609 610 public String getMessageID() throws MessagingException { 611 if (headers == null) { 612 loadHeaders(); 613 } 614 return getHeader(RFC2822Headers.MESSAGE_ID, null); 615 } 616 617 public String getFileName() throws MessagingException { 618 if (message == null) { 619 loadMessage(); 620 } 621 return message.getFileName(); 622 } 623 624 public InputStream getInputStream() throws IOException , MessagingException { 625 if (message == null) { 626 loadMessage(); 630 return message.getInputStream(); 631 } else { 632 return message.getInputStream(); 633 } 634 } 635 636 public DataHandler getDataHandler() throws MessagingException { 637 if (message == null) { 638 loadMessage(); 639 } 640 return message.getDataHandler(); 641 } 642 643 public Object getContent() throws IOException , MessagingException { 644 if (message == null) { 645 loadMessage(); 646 } 647 return message.getContent(); 648 } 649 650 public String [] getHeader(String name) throws MessagingException { 651 if (headers == null) { 652 loadHeaders(); 653 } 654 return headers.getHeader(name); 655 } 656 657 public String getHeader(String name, String delimiter) throws MessagingException { 658 if (headers == null) { 659 loadHeaders(); 660 } 661 return headers.getHeader(name, delimiter); 662 } 663 664 public Enumeration getAllHeaders() throws MessagingException { 665 if (headers == null) { 666 loadHeaders(); 667 } 668 return headers.getAllHeaders(); 669 } 670 671 public Enumeration getMatchingHeaders(String [] names) throws MessagingException { 672 if (headers == null) { 673 loadHeaders(); 674 } 675 return headers.getMatchingHeaders(names); 676 } 677 678 public Enumeration getNonMatchingHeaders(String [] names) throws MessagingException { 679 if (headers == null) { 680 loadHeaders(); 681 } 682 return headers.getNonMatchingHeaders(names); 683 } 684 685 public Enumeration getAllHeaderLines() throws MessagingException { 686 if (headers == null) { 687 loadHeaders(); 688 } 689 return headers.getAllHeaderLines(); 690 } 691 692 public Enumeration getMatchingHeaderLines(String [] names) throws MessagingException { 693 if (headers == null) { 694 loadHeaders(); 695 } 696 return headers.getMatchingHeaderLines(names); 697 } 698 699 public Enumeration getNonMatchingHeaderLines(String [] names) throws MessagingException { 700 if (headers == null) { 701 loadHeaders(); 702 } 703 return headers.getNonMatchingHeaderLines(names); 704 } 705 706 public Flags getFlags() throws MessagingException { 707 if (message == null) { 708 loadMessage(); 709 } 710 return message.getFlags(); 711 } 712 713 public boolean isSet(Flags.Flag flag) throws MessagingException { 714 if (message == null) { 715 loadMessage(); 716 } 717 return message.isSet(flag); 718 } 719 720 721 726 public void writeContentTo(OutputStream outs) 727 throws java.io.IOException , MessagingException { 728 if (message == null) { 729 loadMessage(); 730 } 731 InputStream in = getContentStream(); 732 try { 733 copyStream(in, outs); 734 } finally { 735 IOUtil.shutdownStream(in); 736 } 737 } 738 739 742 private static void copyStream(InputStream in, OutputStream out) throws IOException { 743 byte[] block = new byte[1024]; 746 int read = 0; 747 while ((read = in.read(block)) > -1) { 748 out.write(block, 0, read); 749 } 750 out.flush(); 751 } 752 753 756 757 public void setFrom(Address address) throws MessagingException { 758 if (message == null) { 759 loadMessage(); 760 } 761 modified = true; 762 message.setFrom(address); 763 } 764 765 public void setFrom() throws MessagingException { 766 if (message == null) { 767 loadMessage(); 768 } 769 modified = true; 770 message.setFrom(); 771 } 772 773 public void addFrom(Address [] addresses) throws MessagingException { 774 if (message == null) { 775 loadMessage(); 776 } 777 modified = true; 778 message.addFrom(addresses); 779 } 780 781 public void setRecipients(Message.RecipientType type, Address [] addresses) throws MessagingException { 782 if (message == null) { 783 loadMessage(); 784 } 785 modified = true; 786 message.setRecipients(type, addresses); 787 } 788 789 public void addRecipients(Message.RecipientType type, Address [] addresses) throws MessagingException { 790 if (message == null) { 791 loadMessage(); 792 } 793 modified = true; 794 message.addRecipients(type, addresses); 795 } 796 797 public void setReplyTo(Address [] addresses) throws MessagingException { 798 if (message == null) { 799 loadMessage(); 800 } 801 modified = true; 802 message.setReplyTo(addresses); 803 } 804 805 public void setSubject(String subject) throws MessagingException { 806 if (message == null) { 807 loadMessage(); 808 } 809 modified = true; 810 headers.setHeader(RFC2822Headers.SUBJECT, subject); 811 message.setSubject(subject); 812 } 813 814 public void setSubject(String subject, String charset) throws MessagingException { 815 if (message == null) { 816 loadMessage(); 817 } 818 modified = true; 819 try { 821 headers.setHeader(RFC2822Headers.SUBJECT, new String (subject.getBytes(charset))); 822 } 823 catch (java.io.UnsupportedEncodingException _) { } 824 message.setSubject(subject, charset); 825 } 826 827 public void setSentDate(Date d) throws MessagingException { 828 if (message == null) { 829 loadMessage(); 830 } 831 modified = true; 832 headers.setHeader(RFC2822Headers.DATE, mailDateFormat.format(d)); 833 message.setSentDate(d); 834 } 835 836 public void setDisposition(String disposition) throws MessagingException { 837 if (message == null) { 838 loadMessage(); 839 } 840 modified = true; 841 message.setDisposition(disposition); 842 } 843 844 public void setContentID(String cid) throws MessagingException { 845 if (message == null) { 846 loadMessage(); 847 } 848 modified = true; 849 message.setContentID(cid); 850 } 851 852 public void setContentMD5(String md5) throws MessagingException { 853 if (message == null) { 854 loadMessage(); 855 } 856 modified = true; 857 message.setContentMD5(md5); 858 } 859 860 public void setDescription(String description) throws MessagingException { 861 if (message == null) { 862 loadMessage(); 863 } 864 modified = true; 865 message.setDescription(description); 866 } 867 868 public void setDescription(String description, String charset) throws MessagingException { 869 if (message == null) { 870 loadMessage(); 871 } 872 modified = true; 873 message.setDescription(description, charset); 874 } 875 876 public void setContentLanguage(String [] languages) throws MessagingException { 877 if (message == null) { 878 loadMessage(); 879 } 880 modified = true; 881 message.setContentLanguage(languages); 882 } 883 884 public void setFileName(String filename) throws MessagingException { 885 if (message == null) { 886 loadMessage(); 887 } 888 modified = true; 889 message.setFileName(filename); 890 } 891 892 public void setDataHandler(DataHandler dh) throws MessagingException { 893 if (message == null) { 894 loadMessage(); 895 } 896 modified = true; 897 message.setDataHandler(dh); 898 } 899 900 public void setContent(Object o, String type) throws MessagingException { 901 if (message == null) { 902 loadMessage(); 903 } 904 modified = true; 905 message.setContent(o, type); 906 } 907 908 public void setText(String text) throws MessagingException { 909 if (message == null) { 910 loadMessage(); 911 } 912 modified = true; 913 message.setText(text); 914 } 915 916 public void setText(String text, String charset) throws MessagingException { 917 if (message == null) { 918 loadMessage(); 919 } 920 modified = true; 921 message.setText(text, charset); 922 } 923 924 public void setContent(Multipart mp) throws MessagingException { 925 if (message == null) { 926 loadMessage(); 927 } 928 modified = true; 929 message.setContent(mp); 930 } 931 932 public Message reply(boolean replyToAll) throws MessagingException { 933 if (message == null) { 934 loadMessage(); 935 } 936 modified = true; 937 return message.reply(replyToAll); 938 } 939 940 public void setHeader(String name, String value) throws MessagingException { 941 if (message == null) { 942 loadMessage(); 943 } 944 modified = true; 945 headers.setHeader(name, value); 946 message.setHeader(name, value); 947 } 948 949 public void addHeader(String name, String value) throws MessagingException { 950 if (message == null) { 951 loadMessage(); 952 } 953 modified = true; 954 headers.addHeader(name, value); 955 message.addHeader(name, value); 956 } 957 958 public void removeHeader(String name) throws MessagingException { 959 if (message == null) { 960 loadMessage(); 961 } 962 modified = true; 963 headers.removeHeader(name); 964 message.removeHeader(name); 965 } 966 967 public void addHeaderLine(String line) throws MessagingException { 968 if (message == null) { 969 loadMessage(); 970 } 971 headers.addHeaderLine(line); 972 message.addHeaderLine(line); 973 } 974 975 public void setFlags(Flags flag, boolean set) throws MessagingException { 976 if (message == null) { 977 loadMessage(); 978 } 979 modified = true; 980 message.setFlags(flag, set); 981 } 982 983 public void saveChanges() throws MessagingException { 984 if (message == null) { 985 loadMessage(); 986 } 987 modified = true; 988 message.saveChanges(); 989 } 990 991 994 public InputStream getRawInputStream() throws MessagingException { 995 if (message == null) { 996 loadMessage(); 997 } 998 return message.getRawInputStream(); 999 } 1000 1001 public void addRecipients(Message.RecipientType type, String addresses) throws MessagingException { 1002 if (message == null) { 1003 loadMessage(); 1004 } 1005 modified = true; 1006 message.addRecipients(type, addresses); 1007 } 1008 1009 public void setRecipients(Message.RecipientType type, String addresses) throws MessagingException { 1010 if (message == null) { 1011 loadMessage(); 1012 } 1013 modified = true; 1014 message.setRecipients(type, addresses); 1015 } 1016 1017 1020 public void dispose() { 1021 if (source instanceof Disposable) { 1022 ((Disposable)source).dispose(); 1023 } 1024 } 1025} 1026 | Popular Tags |