1 21 22 27 28 package javax.mail.internet; 29 30 import javax.mail.*; 31 import javax.activation.*; 32 import java.lang.*; 33 import java.io.*; 34 import java.util.*; 35 import java.text.ParseException ; 36 import com.sun.mail.util.ASCIIUtility; 37 import com.sun.mail.util.LineOutputStream; 38 import javax.mail.util.SharedByteArrayInputStream; 39 40 90 91 public class MimeMessage extends Message implements MimePart { 92 93 96 protected DataHandler dh; 97 98 101 protected byte[] content; 102 103 112 protected InputStream contentStream; 113 114 118 protected InternetHeaders headers; 119 120 123 protected Flags flags; 124 125 135 protected boolean modified = false; 136 137 148 protected boolean saved = false; 149 150 private static MailDateFormat mailDateFormat = new MailDateFormat (); 152 153 private boolean strict = true; 155 156 162 public MimeMessage(Session session) { 163 super(session); 164 modified = true; 165 headers = new InternetHeaders (); 166 flags = new Flags(); initStrict(); 168 } 169 170 183 public MimeMessage(Session session, InputStream is) 184 throws MessagingException { 185 super(session); 186 flags = new Flags(); initStrict(); 188 parse(is); 189 saved = true; 190 } 191 192 204 public MimeMessage(MimeMessage source) throws MessagingException { 205 super(source.session); 206 flags = source.getFlags(); 207 ByteArrayOutputStream bos; 208 int size = source.getSize(); 209 if (size > 0) 210 bos = new ByteArrayOutputStream(size); 211 else 212 bos = new ByteArrayOutputStream(); 213 try { 214 strict = source.strict; 215 source.writeTo(bos); 216 bos.close(); 217 SharedByteArrayInputStream bis = 218 new SharedByteArrayInputStream(bos.toByteArray()); 219 parse(bis); 220 bis.close(); 221 saved = true; 222 } catch (IOException ex) { 223 throw new MessagingException("IOException while copying message", 225 ex); 226 } 227 } 228 229 235 protected MimeMessage(Folder folder, int msgnum) { 236 super(folder, msgnum); 237 flags = new Flags(); saved = true; 239 initStrict(); 240 } 241 242 255 protected MimeMessage(Folder folder, InputStream is, int msgnum) 256 throws MessagingException { 257 this(folder, msgnum); 258 initStrict(); 259 parse(is); 260 } 261 262 274 protected MimeMessage(Folder folder, InternetHeaders headers, 275 byte[] content, int msgnum) throws MessagingException { 276 this(folder, msgnum); 277 this.headers = headers; 278 this.content = content; 279 initStrict(); 280 } 281 282 285 private void initStrict() { 286 if (session != null) { 287 String s = session.getProperty("mail.mime.address.strict"); 288 strict = s == null || !s.equalsIgnoreCase("false"); 289 } 290 } 291 292 303 protected void parse(InputStream is) throws MessagingException { 304 305 if (!(is instanceof ByteArrayInputStream) && 306 !(is instanceof BufferedInputStream) && 307 !(is instanceof SharedInputStream )) 308 is = new BufferedInputStream(is); 309 310 headers = createInternetHeaders(is); 311 312 if (is instanceof SharedInputStream ) { 313 SharedInputStream sis = (SharedInputStream )is; 314 contentStream = sis.newStream(sis.getPosition(), -1); 315 } else { 316 try { 317 content = ASCIIUtility.getBytes(is); 318 } catch (IOException ioex) { 319 throw new MessagingException("IOException", ioex); 320 } 321 } 322 323 modified = false; 324 } 325 326 339 public Address[] getFrom() throws MessagingException { 340 Address[] a = getAddressHeader("From"); 341 if (a == null) 342 a = getAddressHeader("Sender"); 343 344 return a; 345 } 346 347 360 public void setFrom(Address address) throws MessagingException { 361 if (address == null) 362 removeHeader("From"); 363 else 364 setHeader("From", address.toString()); 365 } 366 367 378 public void setFrom() throws MessagingException { 379 InternetAddress me = InternetAddress.getLocalAddress(session); 380 if (me != null) 381 setFrom(me); 382 else 383 throw new MessagingException("No From address"); 384 } 385 386 398 public void addFrom(Address[] addresses) throws MessagingException { 399 addAddressHeader("From", addresses); 400 } 401 402 415 public Address getSender() throws MessagingException { 416 Address[] a = getAddressHeader("Sender"); 417 if (a == null || a.length == 0) 418 return null; 419 return a[0]; } 421 422 436 public void setSender(Address address) throws MessagingException { 437 if (address == null) 438 removeHeader("Sender"); 439 else 440 setHeader("Sender", address.toString()); 441 } 442 443 450 public static class RecipientType extends Message.RecipientType { 451 452 private static final long serialVersionUID = -5468290701714395543L; 453 454 457 public static final RecipientType NEWSGROUPS = 458 new RecipientType("Newsgroups"); 459 protected RecipientType(String type) { 460 super(type); 461 } 462 463 protected Object readResolve() throws ObjectStreamException { 464 if (type.equals("Newsgroups")) 465 return NEWSGROUPS; 466 else 467 return super.readResolve(); 468 } 469 } 470 471 499 public Address[] getRecipients(Message.RecipientType type) 500 throws MessagingException { 501 if (type == RecipientType.NEWSGROUPS) { 502 String s = getHeader("Newsgroups", ","); 503 return (s == null) ? null : NewsAddress.parse(s); 504 } else 505 return getAddressHeader(getHeaderName(type)); 506 } 507 508 519 public Address[] getAllRecipients() throws MessagingException { 520 Address[] all = super.getAllRecipients(); 521 Address[] ng = getRecipients(RecipientType.NEWSGROUPS); 522 523 if (ng == null) 524 return all; 526 int numRecip = 527 (all != null ? all.length : 0) + 528 (ng != null ? ng.length : 0); 529 Address[] addresses = new Address[numRecip]; 530 int pos = 0; 531 if (all != null) { 532 System.arraycopy(all, 0, addresses, pos, all.length); 533 pos += all.length; 534 } 535 if (ng != null) { 536 System.arraycopy(ng, 0, addresses, pos, ng.length); 537 pos += ng.length; 538 } 539 return addresses; 540 } 541 542 557 public void setRecipients(Message.RecipientType type, Address[] addresses) 558 throws MessagingException { 559 if (type == RecipientType.NEWSGROUPS) { 560 if (addresses == null || addresses.length == 0) 561 removeHeader("Newsgroups"); 562 else 563 setHeader("Newsgroups", NewsAddress.toString(addresses)); 564 } else 565 setAddressHeader(getHeaderName(type), addresses); 566 } 567 568 586 public void setRecipients(Message.RecipientType type, String addresses) 587 throws MessagingException { 588 if (type == RecipientType.NEWSGROUPS) { 589 if (addresses == null || addresses.length() == 0) 590 removeHeader("Newsgroups"); 591 else 592 setHeader("Newsgroups", addresses); 593 } else 594 setAddressHeader(getHeaderName(type), InternetAddress.parse(addresses)); 595 } 596 597 609 public void addRecipients(Message.RecipientType type, Address[] addresses) 610 throws MessagingException { 611 if (type == RecipientType.NEWSGROUPS) { 612 String s = NewsAddress.toString(addresses); 613 if (s != null) 614 addHeader("Newsgroups", s); 615 } else 616 addAddressHeader(getHeaderName(type), addresses); 617 } 618 619 634 public void addRecipients(Message.RecipientType type, String addresses) 635 throws MessagingException { 636 if (type == RecipientType.NEWSGROUPS) { 637 if (addresses != null && addresses.length() != 0) 638 addHeader("Newsgroups", addresses); 639 } else 640 addAddressHeader(getHeaderName(type), InternetAddress.parse(addresses)); 641 } 642 643 654 public Address[] getReplyTo() throws MessagingException { 655 Address[] a = getAddressHeader("Reply-To"); 656 if (a == null) 657 a = getFrom(); 658 return a; 659 } 660 661 672 public void setReplyTo(Address[] addresses) throws MessagingException { 673 setAddressHeader("Reply-To", addresses); 674 } 675 676 private Address[] getAddressHeader(String name) 678 throws MessagingException { 679 String s = getHeader(name, ","); 680 return (s == null) ? null : InternetAddress.parseHeader(s, strict); 681 } 682 683 private void setAddressHeader(String name, Address[] addresses) 685 throws MessagingException { 686 String s = InternetAddress.toString(addresses); 687 if (s == null) 688 removeHeader(name); 689 else 690 setHeader(name, s); 691 } 692 693 private void addAddressHeader(String name, Address[] addresses) 694 throws MessagingException { 695 String s = InternetAddress.toString(addresses); 696 if (s == null) 697 return; 698 addHeader(name, s); 699 } 700 701 716 public String getSubject() throws MessagingException { 717 String rawvalue = getHeader("Subject", null); 718 719 if (rawvalue == null) 720 return null; 721 722 try { 723 return MimeUtility.decodeText(MimeUtility.unfold(rawvalue)); 724 } catch (UnsupportedEncodingException ex) { 725 return rawvalue; 726 } 727 } 728 729 756 public void setSubject(String subject) throws MessagingException { 757 setSubject(subject, null); 758 } 759 760 787 public void setSubject(String subject, String charset) 788 throws MessagingException { 789 if (subject == null) 790 removeHeader("Subject"); 791 792 try { 793 setHeader("Subject", MimeUtility.fold(9, 794 MimeUtility.encodeText(subject, charset, null))); 795 } catch (UnsupportedEncodingException uex) { 796 throw new MessagingException("Encoding error", uex); 797 } 798 } 799 800 811 public Date getSentDate() throws MessagingException { 812 String s = getHeader("Date", null); 813 if (s != null) { 814 try { 815 synchronized (mailDateFormat) { 816 return mailDateFormat.parse(s); 817 } 818 } catch (ParseException pex) { 819 return null; 820 } 821 } 822 823 return null; 824 } 825 826 838 public void setSentDate(Date d) throws MessagingException { 839 if (d == null) 840 removeHeader("Date"); 841 else { 842 synchronized (mailDateFormat) { 843 setHeader("Date", mailDateFormat.format(d)); 844 } 845 } 846 } 847 848 861 public Date getReceivedDate() throws MessagingException { 862 return null; 863 } 864 865 882 public int getSize() throws MessagingException { 883 if (content != null) 884 return content.length; 885 if (contentStream != null) { 886 try { 887 int size = contentStream.available(); 888 if (size > 0) 891 return size; 892 } catch (IOException ex) { 893 } 895 } 896 return -1; 897 } 898 899 912 public int getLineCount() throws MessagingException { 913 return -1; 914 } 915 916 929 public String getContentType() throws MessagingException { 930 String s = getHeader("Content-Type", null); 931 if (s == null) 932 return "text/plain"; 933 return s; 934 } 935 936 950 public boolean isMimeType(String mimeType) throws MessagingException { 951 return MimeBodyPart.isMimeType(this, mimeType); 952 } 953 954 968 public String getDisposition() throws MessagingException { 969 return MimeBodyPart.getDisposition(this); 970 } 971 972 983 public void setDisposition(String disposition) throws MessagingException { 984 MimeBodyPart.setDisposition(this, disposition); 985 } 986 987 999 public String getEncoding() throws MessagingException { 1000 return MimeBodyPart.getEncoding(this); 1001 } 1002 1003 1014 public String getContentID() throws MessagingException { 1015 return getHeader("Content-Id", null); 1016 } 1017 1018 1029 public void setContentID(String cid) throws MessagingException { 1030 if (cid == null) 1031 removeHeader("Content-ID"); 1032 else 1033 setHeader("Content-ID", cid); 1034 } 1035 1036 1047 public String getContentMD5() throws MessagingException { 1048 return getHeader("Content-MD5", null); 1049 } 1050 1051 1060 public void setContentMD5(String md5) throws MessagingException { 1061 setHeader("Content-MD5", md5); 1062 } 1063 1064 1080 public String getDescription() throws MessagingException { 1081 return MimeBodyPart.getDescription(this); 1082 } 1083 1084 1109 public void setDescription(String description) throws MessagingException { 1110 setDescription(description, null); 1111 } 1112 1113 1139 public void setDescription(String description, String charset) 1140 throws MessagingException { 1141 MimeBodyPart.setDescription(this, description, charset); 1142 } 1143 1144 1156 public String [] getContentLanguage() throws MessagingException { 1157 return MimeBodyPart.getContentLanguage(this); 1158 } 1159 1160 1171 public void setContentLanguage(String [] languages) 1172 throws MessagingException { 1173 MimeBodyPart.setContentLanguage(this, languages); 1174 } 1175 1176 1190 public String getMessageID() throws MessagingException { 1191 return getHeader("Message-ID", null); 1192 } 1193 1194 1214 public String getFileName() throws MessagingException { 1215 return MimeBodyPart.getFileName(this); 1216 } 1217 1218 1238 public void setFileName(String filename) throws MessagingException { 1239 MimeBodyPart.setFileName(this, filename); 1240 } 1241 1242 private String getHeaderName(Message.RecipientType type) 1243 throws MessagingException { 1244 String headerName; 1245 1246 if (type == Message.RecipientType.TO) 1247 headerName = "To"; 1248 else if (type == Message.RecipientType.CC) 1249 headerName = "Cc"; 1250 else if (type == Message.RecipientType.BCC) 1251 headerName = "Bcc"; 1252 else if (type == MimeMessage.RecipientType.NEWSGROUPS) 1253 headerName = "Newsgroups"; 1254 else 1255 throw new MessagingException("Invalid Recipient Type"); 1256 return headerName; 1257 } 1258 1259 1260 1275 public InputStream getInputStream() 1276 throws IOException, MessagingException { 1277 return getDataHandler().getInputStream(); 1278 } 1279 1280 1293 protected InputStream getContentStream() throws MessagingException { 1294 if (contentStream != null) 1295 return ((SharedInputStream )contentStream).newStream(0, -1); 1296 if (content != null) 1297 return new SharedByteArrayInputStream(content); 1298 1299 throw new MessagingException("No content"); 1300 } 1301 1302 1317 public InputStream getRawInputStream() throws MessagingException { 1318 return getContentStream(); 1319 } 1320 1321 1349 public synchronized DataHandler getDataHandler() 1350 throws MessagingException { 1351 if (dh == null) 1352 dh = new DataHandler(new MimePartDataSource (this)); 1353 return dh; 1354 } 1355 1356 1379 public Object getContent() throws IOException, MessagingException { 1380 Object c = getDataHandler().getContent(); 1381 if (MimeBodyPart.cacheMultipart && 1382 (c instanceof Multipart || c instanceof Message) && 1383 !(dh instanceof CachedDataHandler) && 1384 (content != null || contentStream != null)) { 1385 dh = MimeBodyPart.createCachedDataHandler(c, getContentType()); 1386 } 1387 return c; 1388 } 1389 1390 1401 public synchronized void setDataHandler(DataHandler dh) 1402 throws MessagingException { 1403 this.dh = dh; 1404 MimeBodyPart.invalidateContentHeaders(this); 1405 } 1406 1407 1426 public void setContent(Object o, String type) 1427 throws MessagingException { 1428 setDataHandler(new DataHandler(o, type)); 1429 } 1430 1431 1450 public void setText(String text) throws MessagingException { 1451 setText(text, null); 1452 } 1453 1454 1465 public void setText(String text, String charset) 1466 throws MessagingException { 1467 MimeBodyPart.setText(this, text, charset, "plain"); 1468 } 1469 1470 1483 public void setText(String text, String charset, String subtype) 1484 throws MessagingException { 1485 MimeBodyPart.setText(this, text, charset, subtype); 1486 } 1487 1488 1499 public void setContent(Multipart mp) throws MessagingException { 1500 setDataHandler(new DataHandler(mp, mp.getContentType())); 1501 mp.setParent(this); 1502 } 1503 1504 1527 public Message reply(boolean replyToAll) throws MessagingException { 1528 MimeMessage reply = createMimeMessage(session); 1529 1536 String subject = getHeader("Subject", null); 1537 if (subject != null) { 1538 if (!subject.regionMatches(true, 0, "Re: ", 0, 4)) 1539 subject = "Re: " + subject; 1540 reply.setHeader("Subject", subject); 1541 } 1542 Address a[] = getReplyTo(); 1543 reply.setRecipients(Message.RecipientType.TO, a); 1544 if (replyToAll) { 1545 Vector v = new Vector(); 1546 InternetAddress me = InternetAddress.getLocalAddress(session); 1548 if (me != null) 1549 v.addElement(me); 1550 String alternates = null; 1552 if (session != null) 1553 alternates = session.getProperty("mail.alternates"); 1554 if (alternates != null) 1555 eliminateDuplicates(v, 1556 InternetAddress.parse(alternates, false)); 1557 String replyallccStr = null; 1559 if (session != null) 1560 replyallccStr = session.getProperty("mail.replyallcc"); 1561 boolean replyallcc = 1562 replyallccStr != null && replyallccStr.equalsIgnoreCase("true"); 1563 eliminateDuplicates(v, a); 1565 a = getRecipients(Message.RecipientType.TO); 1566 a = eliminateDuplicates(v, a); 1567 if (a != null && a.length > 0) { 1568 if (replyallcc) 1569 reply.addRecipients(Message.RecipientType.CC, a); 1570 else 1571 reply.addRecipients(Message.RecipientType.TO, a); 1572 } 1573 a = getRecipients(Message.RecipientType.CC); 1574 a = eliminateDuplicates(v, a); 1575 if (a != null && a.length > 0) 1576 reply.addRecipients(Message.RecipientType.CC, a); 1577 a = getRecipients(RecipientType.NEWSGROUPS); 1579 if (a != null && a.length > 0) 1580 reply.setRecipients(RecipientType.NEWSGROUPS, a); 1581 } 1582 String msgId = getHeader("Message-Id", null); 1583 if (msgId != null) 1584 reply.setHeader("In-Reply-To", msgId); 1585 try { 1586 setFlags(answeredFlag, true); 1587 } catch (MessagingException mex) { 1588 } 1590 return reply; 1591 } 1592 1593 private static final Flags answeredFlag = new Flags(Flags.Flag.ANSWERED); 1595 1596 1601 private Address[] eliminateDuplicates(Vector v, Address[] addrs) { 1602 if (addrs == null) 1603 return null; 1604 int gone = 0; 1605 for (int i = 0; i < addrs.length; i++) { 1606 boolean found = false; 1607 for (int j = 0; j < v.size(); j++) { 1609 if (((InternetAddress )v.elementAt(j)).equals(addrs[i])) { 1610 found = true; 1612 gone++; 1613 addrs[i] = null; 1614 break; 1615 } 1616 } 1617 if (!found) 1618 v.addElement(addrs[i]); } 1620 if (gone != 0) { 1622 Address[] a; 1623 if (addrs instanceof InternetAddress []) 1626 a = new InternetAddress [addrs.length - gone]; 1627 else 1628 a = new Address[addrs.length - gone]; 1629 for (int i = 0, j = 0; i < addrs.length; i++) 1630 if (addrs[i] != null) 1631 a[j++] = addrs[i]; 1632 addrs = a; 1633 } 1634 return addrs; 1635 } 1636 1637 1657 public void writeTo(OutputStream os) 1658 throws IOException, MessagingException { 1659 writeTo(os, null); 1660 } 1661 1662 1677 public void writeTo(OutputStream os, String [] ignoreList) 1678 throws IOException, MessagingException { 1679 if (!saved) 1680 saveChanges(); 1681 1682 if (modified) { 1683 MimeBodyPart.writeTo(this, os, ignoreList); 1684 return; 1685 } 1686 1687 Enumeration hdrLines = getNonMatchingHeaderLines(ignoreList); 1690 LineOutputStream los = new LineOutputStream(os); 1691 while (hdrLines.hasMoreElements()) 1692 los.writeln((String )hdrLines.nextElement()); 1693 1694 los.writeln(); 1696 1697 if (content == null) { 1699 InputStream is = getContentStream(); 1702 byte[] buf = new byte[8192]; 1704 int len; 1705 while ((len = is.read(buf)) > 0) 1706 os.write(buf, 0, len); 1707 is.close(); 1708 buf = null; 1709 } else { 1710 os.write(content); 1711 } 1712 os.flush(); 1713 } 1714 1715 1728 public String [] getHeader(String name) 1729 throws MessagingException { 1730 return headers.getHeader(name); 1731 } 1732 1733 1745 public String getHeader(String name, String delimiter) 1746 throws MessagingException { 1747 return headers.getHeader(name, delimiter); 1748 } 1749 1750 1766 public void setHeader(String name, String value) 1767 throws MessagingException { 1768 headers.setHeader(name, value); 1769 } 1770 1771 1786 public void addHeader(String name, String value) 1787 throws MessagingException { 1788 headers.addHeader(name, value); 1789 } 1790 1791 1799 public void removeHeader(String name) 1800 throws MessagingException { 1801 headers.removeHeader(name); 1802 } 1803 1804 1819 public Enumeration getAllHeaders() throws MessagingException { 1820 return headers.getAllHeaders(); 1821 } 1822 1823 1830 public Enumeration getMatchingHeaders(String [] names) 1831 throws MessagingException { 1832 return headers.getMatchingHeaders(names); 1833 } 1834 1835 1842 public Enumeration getNonMatchingHeaders(String [] names) 1843 throws MessagingException { 1844 return headers.getNonMatchingHeaders(names); 1845 } 1846 1847 1856 public void addHeaderLine(String line) throws MessagingException { 1857 headers.addHeaderLine(line); 1858 } 1859 1860 1867 public Enumeration getAllHeaderLines() throws MessagingException { 1868 return headers.getAllHeaderLines(); 1869 } 1870 1871 1878 public Enumeration getMatchingHeaderLines(String [] names) 1879 throws MessagingException { 1880 return headers.getMatchingHeaderLines(names); 1881 } 1882 1883 1890 public Enumeration getNonMatchingHeaderLines(String [] names) 1891 throws MessagingException { 1892 return headers.getNonMatchingHeaderLines(names); 1893 } 1894 1895 1907 public synchronized Flags getFlags() throws MessagingException { 1908 return (Flags)flags.clone(); 1909 } 1910 1911 1929 public synchronized boolean isSet(Flags.Flag flag) 1930 throws MessagingException { 1931 return (flags.contains(flag)); 1932 } 1933 1934 1945 public synchronized void setFlags(Flags flag, boolean set) 1946 throws MessagingException { 1947 if (set) 1948 flags.add(flag); 1949 else 1950 flags.remove(flag); 1951 } 1952 1953 1977 public void saveChanges() throws MessagingException { 1978 modified = true; 1979 saved = true; 1980 updateHeaders(); 1981 } 1982 1983 1990 protected void updateMessageID() throws MessagingException { 1991 setHeader("Message-ID", 1992 "<" + UniqueValue.getUniqueMessageIDValue(session) + ">"); 1993 1994 } 1995 1996 2011 protected void updateHeaders() throws MessagingException { 2012 MimeBodyPart.updateHeaders(this); 2013 setHeader("MIME-Version", "1.0"); 2014 updateMessageID(); 2015 } 2016 2017 2028 protected InternetHeaders createInternetHeaders(InputStream is) 2029 throws MessagingException { 2030 return new InternetHeaders (is); 2031 } 2032 2033 2044 protected MimeMessage createMimeMessage(Session session) 2045 throws MessagingException { 2046 return new MimeMessage (session); 2047 } 2048} 2049 | Popular Tags |