1 17 18 package org.apache.james.transport.mailets; 19 20 import java.io.PrintWriter ; 21 import java.io.StringWriter ; 22 23 import java.util.Collection ; 24 import java.util.Date ; 25 import java.util.Enumeration ; 26 import java.util.HashSet ; 27 import java.util.Iterator ; 28 import java.util.Locale ; 29 import java.util.ArrayList ; 30 31 32 import javax.mail.Message ; 33 import javax.mail.MessagingException ; 34 import javax.mail.internet.ParseException ; 35 import javax.mail.Session ; 36 import javax.mail.internet.InternetAddress ; 37 import javax.mail.internet.MimeBodyPart ; 38 import javax.mail.internet.MimeMessage ; 39 import javax.mail.internet.MimeMultipart ; 40 import javax.mail.internet.AddressException ; 41 42 import org.apache.james.util.RFC2822Headers; 43 import org.apache.james.util.RFC822DateFormat; 44 import org.apache.james.core.MailImpl; 45 46 import org.apache.mailet.GenericMailet; 47 import org.apache.mailet.Mail; 48 import org.apache.mailet.MailAddress; 49 50 51 130 131 public abstract class AbstractRedirect extends GenericMailet { 132 133 138 protected String [] getAllowedInitParameters() { 139 return null; 140 } 141 142 145 protected boolean isDebug = false; 146 147 150 protected boolean isStatic = false; 151 152 private static class AddressMarker { 153 public static MailAddress SENDER; 154 public static MailAddress REVERSE_PATH; 155 public static MailAddress FROM; 156 public static MailAddress REPLY_TO; 157 public static MailAddress TO; 158 public static MailAddress RECIPIENTS; 159 public static MailAddress DELETE; 160 public static MailAddress UNALTERED; 161 public static MailAddress NULL; 162 163 static { 164 try { 165 SENDER = new MailAddress("sender","address.marker"); 166 REVERSE_PATH = new MailAddress("reverse.path","address.marker"); 167 FROM = new MailAddress("from","address.marker"); 168 REPLY_TO = new MailAddress("reply.to","address.marker"); 169 TO = new MailAddress("to","address.marker"); 170 RECIPIENTS = new MailAddress("recipients","address.marker"); 171 DELETE = new MailAddress("delete","address.marker"); 172 UNALTERED = new MailAddress("unaltered","address.marker"); 173 NULL = new MailAddress("null","address.marker"); 174 175 } catch (Exception _) {} 176 } 177 } 178 179 184 protected static class SpecialAddress { 185 public static final MailAddress SENDER = AddressMarker.SENDER; 186 public static final MailAddress REVERSE_PATH = AddressMarker.REVERSE_PATH; 187 public static final MailAddress FROM = AddressMarker.FROM; 188 public static final MailAddress REPLY_TO = AddressMarker.REPLY_TO; 189 public static final MailAddress TO = AddressMarker.TO; 190 public static final MailAddress RECIPIENTS = AddressMarker.RECIPIENTS; 191 public static final MailAddress DELETE = AddressMarker.DELETE; 192 public static final MailAddress UNALTERED = AddressMarker.UNALTERED; 193 public static final MailAddress NULL = AddressMarker.NULL; 194 } 195 196 199 protected static final int UNALTERED = 0; 200 201 protected static final int HEADS = 1; 202 203 protected static final int BODY = 2; 204 205 protected static final int ALL = 3; 206 207 protected static final int NONE = 4; 208 209 protected static final int MESSAGE = 5; 210 211 private boolean passThrough = false; 212 private boolean fakeDomainCheck = true; 213 private int attachmentType = NONE; 214 private int inLineType = BODY; 215 private String messageText; 216 private Collection recipients; 217 private MailAddress replyTo; 218 private MailAddress reversePath; 219 private MailAddress sender; 220 private String subject; 221 private String subjectPrefix; 222 private InternetAddress [] apparentlyTo; 223 private boolean attachError = false; 224 private boolean isReply = false; 225 226 private RFC822DateFormat rfc822DateFormat = new RFC822DateFormat(); 227 228 229 230 231 232 247 protected boolean isStatic() { 248 return true; 249 } 250 251 258 protected boolean getPassThrough() throws MessagingException { 259 return new Boolean (getInitParameter("passThrough")).booleanValue(); 260 } 261 262 269 protected boolean getPassThrough(Mail originalMail) throws MessagingException { 270 boolean passThrough = (isStatic()) ? this.passThrough : getPassThrough(); 271 return passThrough; 272 } 273 274 281 protected boolean getFakeDomainCheck() throws MessagingException { 282 return new Boolean (getInitParameter("fakeDomainCheck")).booleanValue(); 283 } 284 285 292 protected boolean getFakeDomainCheck(Mail originalMail) throws MessagingException { 293 boolean fakeDomainCheck = (isStatic()) ? this.fakeDomainCheck : getFakeDomainCheck(); 294 return fakeDomainCheck; 295 } 296 297 312 protected int getInLineType() throws MessagingException { 313 if(getInitParameter("inline") == null) { 314 return UNALTERED; 315 } else { 316 return getTypeCode(getInitParameter("inline")); 317 } 318 } 319 320 327 protected int getInLineType(Mail originalMail) throws MessagingException { 328 int inLineType = (isStatic()) ? this.inLineType : getInLineType(); 329 return inLineType; 330 } 331 332 346 protected int getAttachmentType() throws MessagingException { 347 if(getInitParameter("attachment") == null) { 348 return NONE; 349 } else { 350 return getTypeCode(getInitParameter("attachment")); 351 } 352 } 353 354 361 protected int getAttachmentType(Mail originalMail) throws MessagingException { 362 int attachmentType = (isStatic()) ? this.attachmentType : getAttachmentType(); 363 return attachmentType; 364 } 365 366 374 protected String getMessage() throws MessagingException { 375 if(getInitParameter("message") == null) { 376 return ""; 377 } else { 378 return getInitParameter("message"); 379 } 380 } 381 382 389 protected String getMessage(Mail originalMail) throws MessagingException { 390 String messageText = (isStatic()) ? this.messageText : getMessage(); 391 return messageText; 392 } 393 394 410 protected Collection getRecipients() throws MessagingException { 411 Collection newRecipients = new HashSet (); 412 String addressList = getInitParameter("recipients"); 413 414 if (addressList == null) { 416 return null; 417 } 418 419 try { 420 InternetAddress [] iaarray = InternetAddress.parse(addressList, false); 421 for (int i = 0; i < iaarray.length; i++) { 422 String addressString = iaarray[i].getAddress(); 423 MailAddress specialAddress = getSpecialAddress(addressString, 424 new String [] {"postmaster", "sender", "from", "replyTo", "reversePath", "unaltered", "recipients", "to", "null"}); 425 if (specialAddress != null) { 426 newRecipients.add(specialAddress); 427 } else { 428 newRecipients.add(new MailAddress(iaarray[i])); 429 } 430 } 431 } catch (Exception e) { 432 throw new MessagingException ("Exception thrown in getRecipients() parsing: " + addressList, e); 433 } 434 if (newRecipients.size() == 0) { 435 throw new MessagingException ("Failed to initialize \"recipients\" list; empty <recipients> init parameter found."); 436 } 437 438 return newRecipients; 439 } 440 441 448 protected Collection getRecipients(Mail originalMail) throws MessagingException { 449 Collection recipients = (isStatic()) ? this.recipients : getRecipients(); 450 if (recipients != null) { 451 if (recipients.size() == 1 && (recipients.contains(SpecialAddress.UNALTERED) || recipients.contains(SpecialAddress.RECIPIENTS))) { 452 recipients = null; 453 } else { 454 recipients = replaceMailAddresses(originalMail, recipients); 455 } 456 } 457 return recipients; 458 } 459 460 465 protected void setRecipients(Mail newMail, Collection recipients, Mail originalMail) throws MessagingException { 466 if (recipients != null) { 467 ((MailImpl) newMail).setRecipients(recipients); 468 if (isDebug) { 469 log("recipients set to: " + arrayToString(recipients.toArray())); 470 } 471 } 472 } 473 474 490 protected InternetAddress [] getTo() throws MessagingException { 491 InternetAddress [] iaarray = null; 492 String addressList = getInitParameter("to"); 493 494 if (addressList == null) { 496 return null; 497 } 498 499 try { 500 iaarray = InternetAddress.parse(addressList, false); 501 for(int i = 0; i < iaarray.length; ++i) { 502 String addressString = iaarray[i].getAddress(); 503 MailAddress specialAddress = getSpecialAddress(addressString, 504 new String [] {"postmaster", "sender", "from", "replyTo", "reversePath", "unaltered", "recipients", "to", "null"}); 505 if (specialAddress != null) { 506 iaarray[i] = specialAddress.toInternetAddress(); 507 } 508 } 509 } catch (Exception e) { 510 throw new MessagingException ("Exception thrown in getTo() parsing: " + addressList, e); 511 } 512 if (iaarray.length == 0) { 513 throw new MessagingException ("Failed to initialize \"to\" list; empty <to> init parameter found."); 514 } 515 516 return iaarray; 517 } 518 519 528 protected InternetAddress [] getTo(Mail originalMail) throws MessagingException { 529 InternetAddress [] apparentlyTo = (isStatic()) ? this.apparentlyTo : getTo(); 530 if (apparentlyTo != null) { 531 if ( apparentlyTo.length == 1 532 && ( apparentlyTo[0].equals(SpecialAddress.UNALTERED.toInternetAddress()) 533 || apparentlyTo[0].equals(SpecialAddress.TO.toInternetAddress()) 534 )) { 535 apparentlyTo = null; 536 } else { 537 Collection toList = new ArrayList (apparentlyTo.length); 538 for (int i = 0; i < apparentlyTo.length; i++) { 539 toList.add(apparentlyTo[i]); 540 } 541 544 apparentlyTo = (InternetAddress []) replaceInternetAddresses(originalMail, toList).toArray(new InternetAddress [0]); 545 } 546 } 547 548 return apparentlyTo; 549 } 550 551 556 protected void setTo(Mail newMail, InternetAddress [] to, Mail originalMail) throws MessagingException { 557 if (to != null) { 558 newMail.getMessage().setRecipients(Message.RecipientType.TO, to); 559 if (isDebug) { 560 log("apparentlyTo set to: " + arrayToString(to)); 561 } 562 } 563 } 564 565 578 protected MailAddress getReplyTo() throws MessagingException { 579 String addressString = getInitParameter("replyTo"); 580 if (addressString == null) { 581 addressString = getInitParameter("replyto"); 582 } 583 if(addressString != null) { 584 MailAddress specialAddress = getSpecialAddress(addressString, 585 new String [] {"postmaster", "sender", "null", "unaltered"}); 586 if (specialAddress != null) { 587 return specialAddress; 588 } 589 590 try { 591 return new MailAddress(addressString); 592 } catch(Exception e) { 593 throw new MessagingException ("Exception thrown in getReplyTo() parsing: " + addressString, e); 594 } 595 } 596 597 return null; 598 } 599 600 609 protected MailAddress getReplyTo(Mail originalMail) throws MessagingException { 610 MailAddress replyTo = (isStatic()) ? this.replyTo : getReplyTo(); 611 if (replyTo != null) { 612 if (replyTo == SpecialAddress.UNALTERED) { 613 replyTo = null; 614 } else if (replyTo == SpecialAddress.SENDER) { 615 replyTo = originalMail.getSender(); 616 } 617 } 618 return replyTo; 619 } 620 621 627 protected void setReplyTo(Mail newMail, MailAddress replyTo, Mail originalMail) throws MessagingException { 628 if(replyTo != null) { 629 InternetAddress [] iart = null; 630 if (replyTo != SpecialAddress.NULL) { 631 iart = new InternetAddress [1]; 632 iart[0] = replyTo.toInternetAddress(); 633 } 634 635 newMail.getMessage().setReplyTo(iart); 637 638 if (isDebug) { 639 log("replyTo set to: " + replyTo); 640 } 641 } 642 } 643 644 657 protected MailAddress getReversePath() throws MessagingException { 658 String addressString = getInitParameter("reversePath"); 659 if(addressString != null) { 660 MailAddress specialAddress = getSpecialAddress(addressString, 661 new String [] {"postmaster", "sender", "null", "unaltered"}); 662 if (specialAddress != null) { 663 return specialAddress; 664 } 665 666 try { 667 return new MailAddress(addressString); 668 } catch(Exception e) { 669 throw new MessagingException ("Exception thrown in getReversePath() parsing: " + addressString, e); 670 } 671 } 672 673 return null; 674 } 675 676 688 protected MailAddress getReversePath(Mail originalMail) throws MessagingException { 689 MailAddress reversePath = (isStatic()) ? this.reversePath : getReversePath(); 690 if (reversePath != null) { 691 if (reversePath == SpecialAddress.UNALTERED || reversePath == SpecialAddress.REVERSE_PATH) { 692 reversePath = null; 693 } 694 else if (reversePath == SpecialAddress.SENDER) { 695 reversePath = null; 696 } 697 } 698 return reversePath; 699 } 700 701 707 protected void setReversePath(Mail newMail, MailAddress reversePath, Mail originalMail) throws MessagingException { 708 if(reversePath != null) { 709 String reversePathString; 710 if (reversePath == SpecialAddress.NULL) { 711 reversePath = null; 712 reversePathString = ""; 713 } else { 714 reversePathString = reversePath.toString(); 715 } 716 ((MailImpl) newMail).setSender(reversePath); 717 newMail.getMessage().setHeader(RFC2822Headers.RETURN_PATH, "<" + reversePathString + ">"); 718 if (isDebug) { 719 log("reversePath set to: " + reversePath); 720 } 721 } 722 } 723 724 736 protected MailAddress getSender() throws MessagingException { 737 String addressString = getInitParameter("sender"); 738 if(addressString != null) { 739 MailAddress specialAddress = getSpecialAddress(addressString, 740 new String [] {"postmaster", "sender", "unaltered"}); 741 if (specialAddress != null) { 742 return specialAddress; 743 } 744 745 try { 746 return new MailAddress(addressString); 747 } catch(Exception e) { 748 throw new MessagingException ("Exception thrown in getSender() parsing: " + addressString, e); 749 } 750 } 751 752 return null; 753 } 754 755 764 protected MailAddress getSender(Mail originalMail) throws MessagingException { 765 MailAddress sender = (isStatic()) ? this.sender : getSender(); 766 if (sender != null) { 767 if (sender == SpecialAddress.UNALTERED || sender == SpecialAddress.SENDER) { 768 sender = null; 769 } 770 } 771 return sender; 772 } 773 774 779 protected void setSender(Mail newMail, MailAddress sender, Mail originalMail) throws MessagingException { 780 if (sender != null) { 781 newMail.getMessage().setFrom(sender.toInternetAddress()); 782 783 if (isDebug) { 784 log("sender set to: " + sender); 785 } 786 } 787 } 788 789 796 protected String getSubject() throws MessagingException { 797 if(getInitParameter("subject") == null) { 798 return null; 799 } else { 800 return getInitParameter("subject"); 801 } 802 } 803 804 811 protected String getSubject(Mail originalMail) throws MessagingException { 812 String subject = (isStatic()) ? this.subject : getSubject(); 813 return subject; 814 } 815 816 823 protected String getSubjectPrefix() throws MessagingException { 824 if(getInitParameter("prefix") == null) { 825 return null; 826 } else { 827 return getInitParameter("prefix"); 828 } 829 } 830 831 838 protected String getSubjectPrefix(Mail originalMail) throws MessagingException { 839 String subjectPrefix = (isStatic()) ? this.subjectPrefix : getSubjectPrefix(); 840 return subjectPrefix; 841 } 842 843 848 protected void setSubjectPrefix(Mail newMail, String subjectPrefix, Mail originalMail) throws MessagingException { 849 String subject = getSubject(originalMail); 850 if ((subjectPrefix != null && subjectPrefix.length() > 0) || subject != null) { 851 if (subject == null) { 852 subject = originalMail.getMessage().getSubject(); 853 } else { 854 if (isDebug) { 856 log("subject set to: " + subject); 857 } 858 } 859 if (subject == null) { 861 subject = ""; 862 } 863 864 if (subjectPrefix != null) { 865 subject = subjectPrefix + subject; 866 if (isDebug) { 868 log("subjectPrefix set to: " + subjectPrefix); 869 } 870 } 871 changeSubject(newMail.getMessage(), subject); 873 } 874 } 875 876 884 protected boolean attachError() throws MessagingException { 885 return new Boolean (getInitParameter("attachError")).booleanValue(); 886 } 887 888 895 protected boolean attachError(Mail originalMail) throws MessagingException { 896 boolean attachError = (isStatic()) ? this.attachError : attachError(); 897 return attachError; 898 } 899 900 909 protected boolean isReply() throws MessagingException { 910 return new Boolean (getInitParameter("isReply")).booleanValue(); 911 } 912 913 920 protected boolean isReply(Mail originalMail) throws MessagingException { 921 boolean isReply = (isStatic()) ? this.isReply : isReply(); 922 return isReply; 923 } 924 925 929 protected void setIsReply(Mail newMail, boolean isReply, Mail originalMail) throws MessagingException { 930 if (isReply) { 931 String messageId = originalMail.getMessage().getMessageID(); 932 if (messageId != null) { 933 newMail.getMessage().setHeader(RFC2822Headers.IN_REPLY_TO, messageId); 934 if (isDebug) { 935 log("IN_REPLY_TO set to: " + messageId); 936 } 937 } 938 } 939 } 940 941 942 943 944 945 950 public void init() throws MessagingException { 951 isDebug = (getInitParameter("debug") == null) ? false : new Boolean (getInitParameter("debug")).booleanValue(); 952 953 isStatic = (getInitParameter("static") == null) ? false : new Boolean (getInitParameter("static")).booleanValue(); 954 955 if (isDebug) { 956 log("Initializing"); 957 } 958 959 checkInitParameters(getAllowedInitParameters()); 961 962 if(isStatic()) { 963 passThrough = getPassThrough(); 964 fakeDomainCheck = getFakeDomainCheck(); 965 attachmentType = getAttachmentType(); 966 inLineType = getInLineType(); 967 messageText = getMessage(); 968 recipients = getRecipients(); 969 replyTo = getReplyTo(); 970 reversePath = getReversePath(); 971 sender = getSender(); 972 subject = getSubject(); 973 subjectPrefix = getSubjectPrefix(); 974 apparentlyTo = getTo(); 975 attachError = attachError(); 976 isReply = isReply(); 977 if (isDebug) { 978 StringBuffer logBuffer = 979 new StringBuffer (1024) 980 .append("static") 981 .append(", passThrough=").append(passThrough) 982 .append(", fakeDomainCheck=").append(fakeDomainCheck) 983 .append(", sender=").append(sender) 984 .append(", replyTo=").append(replyTo) 985 .append(", reversePath=").append(reversePath) 986 .append(", message=").append(messageText) 987 .append(", recipients=").append(arrayToString(recipients == null ? null : recipients.toArray())) 988 .append(", subject=").append(subject) 989 .append(", subjectPrefix=").append(subjectPrefix) 990 .append(", apparentlyTo=").append(arrayToString(apparentlyTo)) 991 .append(", attachError=").append(attachError) 992 .append(", isReply=").append(isReply) 993 .append(", attachmentType=").append(attachmentType) 994 .append(", inLineType=").append(inLineType) 995 .append(" "); 996 log(logBuffer.toString()); 997 } 998 } 999 } 1000 1001 1007 public void service(Mail originalMail) throws MessagingException { 1008 1009 boolean keepMessageId = false; 1010 1011 Mail newMail = ((MailImpl) originalMail).duplicate(newName((MailImpl) originalMail)); 1013 try { 1017 ((MailImpl) newMail).setRemoteAddr(java.net.InetAddress.getLocalHost().getHostAddress()); 1018 ((MailImpl) newMail).setRemoteHost(java.net.InetAddress.getLocalHost().getHostName()); 1019 } catch (java.net.UnknownHostException _) { 1020 ((MailImpl) newMail).setRemoteAddr("127.0.0.1"); 1021 ((MailImpl) newMail).setRemoteHost("localhost"); 1022 } 1023 1024 if (isDebug) { 1025 MailImpl newMailImpl = (MailImpl) newMail; 1026 log("New mail - sender: " + newMailImpl.getSender() 1027 + ", recipients: " + arrayToString(newMailImpl.getRecipients().toArray()) 1028 + ", name: " + newMailImpl.getName() 1029 + ", remoteHost: " + newMailImpl.getRemoteHost() 1030 + ", remoteAddr: " + newMailImpl.getRemoteAddr() 1031 + ", state: " + newMailImpl.getState() 1032 + ", lastUpdated: " + newMailImpl.getLastUpdated() 1033 + ", errorMessage: " + newMailImpl.getErrorMessage()); 1034 } 1035 1036 if(getInLineType(originalMail) != UNALTERED) { 1038 if (isDebug) { 1039 log("Alter message"); 1040 } 1041 newMail.setMessage(new MimeMessage (Session.getDefaultInstance(System.getProperties(), 1042 null))); 1043 1044 buildAlteredMessage(newMail, originalMail); 1046 1047 } else { 1048 if (getPassThrough(originalMail)) { 1050 newMail.setMessage(new MimeMessage (originalMail.getMessage()) { 1051 protected void updateHeaders() throws MessagingException { 1052 if (getMessageID() == null) super.updateHeaders(); 1053 else { 1054 modified = false; 1055 } 1056 } 1057 }); 1058 } 1059 if (isDebug) { 1060 log("Message resent unaltered."); 1061 } 1062 keepMessageId = true; 1063 } 1064 1065 1067 setRecipients(newMail, getRecipients(originalMail), originalMail); 1068 1069 setTo(newMail, getTo(originalMail), originalMail); 1070 1071 setSubjectPrefix(newMail, getSubjectPrefix(originalMail), originalMail); 1072 1073 if(newMail.getMessage().getHeader(RFC2822Headers.DATE) == null) { 1074 newMail.getMessage().setHeader(RFC2822Headers.DATE, rfc822DateFormat.format(new Date ())); 1075 } 1076 1077 setReplyTo(newMail, getReplyTo(originalMail), originalMail); 1078 1079 setReversePath(newMail, getReversePath(originalMail), originalMail); 1080 1081 setSender(newMail, getSender(originalMail), originalMail); 1082 1083 setIsReply(newMail, isReply(originalMail), originalMail); 1084 1085 newMail.getMessage().saveChanges(); 1086 1087 if (keepMessageId) { 1088 setMessageId(newMail, originalMail); 1089 } 1090 1091 if (senderDomainIsValid(newMail)) { 1092 getMailetContext().sendMail(newMail); 1094 } else { 1095 StringBuffer logBuffer = new StringBuffer (256) 1096 .append(getMailetName()) 1097 .append(" mailet cannot forward ") 1098 .append(((MailImpl) originalMail).getName()) 1099 .append(". Invalid sender domain for ") 1100 .append(newMail.getSender()) 1101 .append(". Consider using the Resend mailet ") 1102 .append("using a different sender."); 1103 throw new MessagingException (logBuffer.toString()); 1104 } 1105 1106 if(!getPassThrough(originalMail)) { 1107 originalMail.setState(Mail.GHOST); 1108 } 1109 } 1110 1111 private static final java.util.Random random = new java.util.Random (); 1113 1119 private String newName(MailImpl mail) throws MessagingException { 1120 String oldName = mail.getName(); 1121 1122 if (oldName.length() > 76) { 1127 int count = 0; 1128 int index = 0; 1129 while ((index = oldName.indexOf('!', index + 1)) >= 0) { 1130 count++; 1131 } 1132 if (count > 7) { 1134 throw new MessagingException ("Unable to create a new message name: too long." 1135 + " Possible loop in config.xml."); 1136 } 1137 else { 1138 oldName = oldName.substring(0, 76); 1139 } 1140 } 1141 1142 StringBuffer nameBuffer = 1143 new StringBuffer (64) 1144 .append(oldName) 1145 .append("-!") 1146 .append(random.nextInt(1048576)); 1147 return nameBuffer.toString(); 1148 } 1149 1150 1156 protected int getTypeCode(String param) { 1157 param = param.toLowerCase(Locale.US); 1158 if(param.compareTo("unaltered") == 0) { 1159 return UNALTERED; 1160 } 1161 if(param.compareTo("heads") == 0) { 1162 return HEADS; 1163 } 1164 if(param.compareTo("body") == 0) { 1165 return BODY; 1166 } 1167 if(param.compareTo("all") == 0) { 1168 return ALL; 1169 } 1170 if(param.compareTo("none") == 0) { 1171 return NONE; 1172 } 1173 if(param.compareTo("message") == 0) { 1174 return MESSAGE; 1175 } 1176 return NONE; 1177 } 1178 1179 1185 protected MailAddress getExistingReturnPath(Mail mail) throws MessagingException { 1186 MailAddress mailAddress = null; 1187 String [] returnPathHeaders = mail.getMessage().getHeader(RFC2822Headers.RETURN_PATH); 1188 String returnPathHeader = null; 1189 if (returnPathHeaders != null) { 1190 returnPathHeader = returnPathHeaders[0]; 1191 if (returnPathHeader != null) { 1192 returnPathHeader = returnPathHeader.trim(); 1193 if (returnPathHeader.equals("<>")) { 1194 mailAddress = SpecialAddress.NULL; 1195 } else { 1196 mailAddress = new MailAddress(new InternetAddress (returnPathHeader)); 1197 } 1198 } 1199 } 1200 return mailAddress; 1201 } 1202 1203 1206 private String arrayToString(Object [] array) { 1207 if (array == null) { 1208 return "null"; 1209 } 1210 StringBuffer sb = new StringBuffer (1024); 1211 sb.append("["); 1212 for (int i = 0; i < array.length; i++) { 1213 if (i > 0) { 1214 sb.append(","); 1215 } 1216 sb.append(array[i]); 1217 } 1218 sb.append("]"); 1219 return sb.toString(); 1220 } 1221 1222 1226 private String getMessageHeaders(MimeMessage message) throws MessagingException { 1227 Enumeration heads = message.getAllHeaderLines(); 1228 StringBuffer headBuffer = new StringBuffer (1024); 1229 while(heads.hasMoreElements()) { 1230 headBuffer.append(heads.nextElement().toString()).append("\r\n"); 1231 } 1232 return headBuffer.toString(); 1233 } 1234 1235 1239 private String getMessageBody(MimeMessage message) throws Exception { 1240 java.io.InputStream bis = null; 1241 java.io.OutputStream bos = null; 1242 java.io.ByteArrayOutputStream bodyOs = new java.io.ByteArrayOutputStream (); 1243 1244 try { 1245 bos = javax.mail.internet.MimeUtility.encode(bodyOs, message.getEncoding()); 1250 bis = message.getInputStream(); 1251 } catch(javax.activation.UnsupportedDataTypeException udte) { 1252 1271 1272 try { 1273 bis = message.getRawInputStream(); 1274 bos = bodyOs; 1275 } catch(javax.mail.MessagingException _) { 1276 throw udte; 1277 } 1278 } 1279 catch(javax.mail.MessagingException me) { 1280 1290 try { 1291 bis = message.getRawInputStream(); 1292 bos = bodyOs; 1293 } catch(javax.mail.MessagingException _) { 1294 throw me; 1295 } 1296 } 1297 1298 try { 1299 byte[] block = new byte[1024]; 1300 int read = 0; 1301 while ((read = bis.read(block)) > -1) { 1302 bos.write(block, 0, read); 1303 } 1304 bos.flush(); 1305 return bodyOs.toString(); 1306 } 1307 finally { 1308 bis.close(); 1309 } 1310 } 1311 1312 1318 protected void buildAlteredMessage(Mail newMail, Mail originalMail) throws MessagingException { 1319 1320 MimeMessage originalMessage = originalMail.getMessage(); 1321 MimeMessage newMessage = newMail.getMessage(); 1322 1323 String [] relevantHeaderNames = 1325 {RFC2822Headers.DATE, 1326 RFC2822Headers.FROM, 1327 RFC2822Headers.REPLY_TO, 1328 RFC2822Headers.TO, 1329 RFC2822Headers.SUBJECT, 1330 RFC2822Headers.RETURN_PATH}; 1331 Enumeration headerEnum = originalMessage.getMatchingHeaderLines(relevantHeaderNames); 1332 while (headerEnum.hasMoreElements()) { 1333 newMessage.addHeaderLine((String ) headerEnum.nextElement()); 1334 } 1335 1336 StringWriter sout = new StringWriter (); 1337 PrintWriter out = new PrintWriter (sout, true); 1338 String head = getMessageHeaders(originalMessage); 1339 boolean all = false; 1340 1341 String messageText = getMessage(originalMail); 1342 if(messageText != null) { 1343 out.println(messageText); 1344 } 1345 1346 if (isDebug) { 1347 log("inline:" + getInLineType(originalMail)); 1348 } 1349 switch(getInLineType(originalMail)) { 1350 case ALL: all = true; 1352 case HEADS: out.println("Message Headers:"); 1354 out.println(head); 1355 if(!all) { 1356 break; 1357 } 1358 case BODY: out.println("Message:"); 1360 try { 1361 out.println(getMessageBody(originalMessage)); 1362 } catch(Exception e) { 1363 out.println("body unavailable"); 1364 } 1365 break; 1366 default: 1367 case NONE: break; 1369 } 1370 1371 try { 1372 MimeMultipart multipart = new MimeMultipart ("mixed"); 1374 1375 MimeMultipart mpContent = new MimeMultipart ("alternative"); 1377 MimeBodyPart contentPartRoot = new MimeBodyPart (); 1378 contentPartRoot.setContent(mpContent); 1379 1380 multipart.addBodyPart(contentPartRoot); 1381 1382 MimeBodyPart part = new MimeBodyPart (); 1383 part.setText(sout.toString()); 1384 part.setDisposition("inline"); 1385 mpContent.addBodyPart(part); 1386 if (isDebug) { 1387 log("attachmentType:" + getAttachmentType(originalMail)); 1388 } 1389 if(getAttachmentType(originalMail) != NONE) { 1390 part = new MimeBodyPart (); 1391 switch(getAttachmentType(originalMail)) { 1392 case HEADS: part.setText(head); 1394 break; 1395 case BODY: try { 1397 part.setText(getMessageBody(originalMessage)); 1398 } catch(Exception e) { 1399 part.setText("body unavailable"); 1400 } 1401 break; 1402 case ALL: StringBuffer textBuffer = 1404 new StringBuffer (1024) 1405 .append(head) 1406 .append("\r\nMessage:\r\n") 1407 .append(getMessageBody(originalMessage)); 1408 part.setText(textBuffer.toString()); 1409 break; 1410 case MESSAGE: part.setContent(originalMessage, "message/rfc822"); 1412 break; 1413 } 1414 if ((originalMessage.getSubject() != null) && (originalMessage.getSubject().trim().length() > 0)) { 1415 part.setFileName(originalMessage.getSubject().trim()); 1416 } else { 1417 part.setFileName("No Subject"); 1418 } 1419 part.setDisposition("Attachment"); 1420 multipart.addBodyPart(part); 1421 } 1422 if (attachError(originalMail) && originalMail.getErrorMessage() != null) { 1424 part = new MimeBodyPart (); 1425 part.setContent(originalMail.getErrorMessage(), "text/plain"); 1426 part.setHeader(RFC2822Headers.CONTENT_TYPE, "text/plain"); 1427 part.setFileName("Reasons"); 1428 part.setDisposition(javax.mail.Part.ATTACHMENT); 1429 multipart.addBodyPart(part); 1430 } 1431 newMail.getMessage().setContent(multipart); 1432 newMail.getMessage().setHeader(RFC2822Headers.CONTENT_TYPE, multipart.getContentType()); 1433 1434 } catch (Exception ioe) { 1435 throw new MessagingException ("Unable to create multipart body", ioe); 1436 } 1437 } 1438 1439 1442 private void setMessageId(Mail newMail, Mail originalMail) throws MessagingException { 1443 String messageId = originalMail.getMessage().getMessageID(); 1444 if (messageId != null) { 1445 newMail.getMessage().setHeader(RFC2822Headers.MESSAGE_ID, messageId); 1446 if (isDebug) { 1447 log("MESSAGE_ID restored to: " + messageId); 1448 } 1449 } 1450 } 1451 1452 1462 protected final MailAddress getSpecialAddress(String addressString, String [] allowedSpecials) throws MessagingException { 1463 if (addressString == null) { 1464 return null; 1465 } 1466 1467 addressString = addressString.toLowerCase(Locale.US); 1468 addressString = addressString.trim(); 1469 1470 MailAddress specialAddress = null; 1471 1472 if(addressString.compareTo("postmaster") == 0) { 1473 specialAddress = getMailetContext().getPostmaster(); 1474 } 1475 if(addressString.compareTo("sender") == 0) { 1476 specialAddress = SpecialAddress.SENDER; 1477 } 1478 if(addressString.compareTo("reversepath") == 0) { 1479 specialAddress = SpecialAddress.REVERSE_PATH; 1480 } 1481 if(addressString.compareTo("from") == 0) { 1482 specialAddress = SpecialAddress.FROM; 1483 } 1484 if(addressString.compareTo("replyto") == 0) { 1485 specialAddress = SpecialAddress.REPLY_TO; 1486 } 1487 if(addressString.compareTo("to") == 0) { 1488 specialAddress = SpecialAddress.TO; 1489 } 1490 if(addressString.compareTo("recipients") == 0) { 1491 specialAddress = SpecialAddress.RECIPIENTS; 1492 } 1493 if(addressString.compareTo("delete") == 0) { 1494 specialAddress = SpecialAddress.DELETE; 1495 } 1496 if(addressString.compareTo("unaltered") == 0) { 1497 specialAddress = SpecialAddress.UNALTERED; 1498 } 1499 if(addressString.compareTo("null") == 0) { 1500 specialAddress = SpecialAddress.NULL; 1501 } 1502 1503 if (specialAddress != null) { 1505 boolean allowed = false; 1507 for (int i = 0; i < allowedSpecials.length; i++) { 1508 String allowedSpecial = allowedSpecials[i]; 1509 allowedSpecial = allowedSpecial.toLowerCase(Locale.US); 1510 allowedSpecial = allowedSpecial.trim(); 1511 if(addressString.compareTo(allowedSpecial) == 0) { 1512 allowed = true; 1513 break; 1514 } 1515 } 1516 if (!allowed) { 1517 throw new MessagingException ("Special (\"magic\") address found not allowed: " + addressString + 1518 ", allowed values are \"" + arrayToString(allowedSpecials) + "\""); 1519 } 1520 } 1521 1522 return specialAddress; 1523 } 1524 1525 1541 protected final boolean senderDomainIsValid(Mail mail) throws MessagingException { 1542 if (getFakeDomainCheck(mail)) { 1543 return mail.getSender() == null || getMailetContext().getMailServers(mail.getSender().getHost()).size() != 0; 1544 } else return true; 1545 } 1546 1547 1551 private void checkInitParameters(String [] allowedArray) throws MessagingException { 1552 if (allowedArray == null) { 1554 return; 1555 } 1556 1557 Collection allowed = new HashSet (); 1558 Collection bad = new ArrayList (); 1559 1560 for (int i = 0; i < allowedArray.length; i++) { 1561 allowed.add(allowedArray[i]); 1562 } 1563 1564 Iterator iterator = getInitParameterNames(); 1565 while (iterator.hasNext()) { 1566 String parameter = (String ) iterator.next(); 1567 if (!allowed.contains(parameter)) { 1568 bad.add(parameter); 1569 } 1570 } 1571 1572 if (bad.size() > 0) { 1573 throw new MessagingException ("Unexpected init parameters found: " 1574 + arrayToString(bad.toArray())); 1575 } 1576 } 1577 1578 1611 public static void changeSubject(MimeMessage message, String newValue) 1612 throws MessagingException 1613 { 1614 String rawSubject = message.getHeader(RFC2822Headers.SUBJECT, null); 1615 String mimeCharset = determineMailHeaderEncodingCharset(rawSubject); 1616 if (mimeCharset == null) { message.setSubject(newValue); 1620 return; 1621 } else { String javaCharset = javax.mail.internet.MimeUtility.javaCharset(mimeCharset); 1623 try { 1624 message.setSubject(newValue, javaCharset); 1625 } catch (MessagingException e) { 1626 message.setSubject(newValue); } 1633 } 1634 } 1635 1636 1648 static private String determineMailHeaderEncodingCharset(String rawText) 1649 { 1650 if (rawText == null) return null; 1651 int iEncodingPrefix = rawText.indexOf("=?"); 1652 if (iEncodingPrefix == -1) return null; 1653 int iCharsetBegin = iEncodingPrefix + 2; 1654 int iSecondQuestionMark = rawText.indexOf('?', iCharsetBegin); 1655 if (iSecondQuestionMark == -1) return null; 1656 if (iSecondQuestionMark == iCharsetBegin) return null; int iThirdQuestionMark = rawText.indexOf('?', iSecondQuestionMark + 1); 1659 if (iThirdQuestionMark == -1) return null; if (-1 == rawText.indexOf("?=", iThirdQuestionMark + 1)) return null; String mimeCharset = rawText.substring(iCharsetBegin, iSecondQuestionMark); 1662 return mimeCharset; 1663 } 1664 1665 1679 protected Collection replaceMailAddresses(Mail mail, Collection list) { 1680 Collection newList = new HashSet (list.size()); 1681 Iterator iterator = list.iterator(); 1682 while (iterator.hasNext()) { 1683 MailAddress mailAddress = (MailAddress) iterator.next(); 1684 if (!mailAddress.getHost().equalsIgnoreCase("address.marker")) { 1685 newList.add(mailAddress); 1686 } else if (mailAddress == SpecialAddress.SENDER || mailAddress == SpecialAddress.FROM) { 1687 MailAddress sender = mail.getSender(); 1688 if (sender != null) { 1689 newList.add(sender); 1690 } 1691 } else if (mailAddress == SpecialAddress.REPLY_TO) { 1692 int parsedAddressCount = 0; 1693 try { 1694 InternetAddress [] replyToArray = (InternetAddress []) mail.getMessage().getReplyTo(); 1695 if (replyToArray != null) { 1696 for (int i = 0; i < replyToArray.length; i++) { 1697 try { 1698 newList.add(new MailAddress(replyToArray[i])); 1699 parsedAddressCount++; 1700 } catch (ParseException pe) { 1701 log("Unable to parse a \"REPLY_TO\" header address in the original message: " + replyToArray[i] + "; ignoring."); 1702 } 1703 } 1704 } 1705 } catch (MessagingException ae) { 1706 log("Unable to parse the \"REPLY_TO\" header in the original message; ignoring."); 1707 } 1708 if (parsedAddressCount == 0) { 1710 MailAddress sender = mail.getSender(); 1711 if (sender != null) { 1712 newList.add(sender); 1713 } 1714 } 1715 } else if (mailAddress == SpecialAddress.REVERSE_PATH) { 1716 MailAddress reversePath = mail.getSender(); 1717 if (reversePath != null) { 1718 newList.add(reversePath); 1719 } 1720 } else if (mailAddress == SpecialAddress.RECIPIENTS || mailAddress == SpecialAddress.TO) { 1721 newList.addAll(mail.getRecipients()); 1722 } else if (mailAddress == SpecialAddress.UNALTERED) { 1723 continue; 1724 } else if (mailAddress == SpecialAddress.NULL) { 1725 continue; 1726 } else { 1727 newList.add(mailAddress); 1728 } 1729 } 1730 return newList; 1731 } 1732 1733 1748 protected Collection replaceInternetAddresses(Mail mail, Collection list) throws MessagingException { 1749 Collection newList = new HashSet (list.size()); 1750 Iterator iterator = list.iterator(); 1751 while (iterator.hasNext()) { 1752 InternetAddress internetAddress = (InternetAddress ) iterator.next(); 1753 MailAddress mailAddress = new MailAddress(internetAddress); 1754 if (!mailAddress.getHost().equalsIgnoreCase("address.marker")) { 1755 newList.add(internetAddress); 1756 } else if (internetAddress.equals(SpecialAddress.SENDER.toInternetAddress())) { 1757 MailAddress sender = mail.getSender(); 1758 if (sender != null) { 1759 newList.add(sender.toInternetAddress()); 1760 } 1761 } else if (internetAddress.equals(SpecialAddress.REVERSE_PATH.toInternetAddress())) { 1762 MailAddress reversePath = mail.getSender(); 1763 if (reversePath != null) { 1764 newList.add(reversePath.toInternetAddress()); 1765 } 1766 } else if (internetAddress.equals(SpecialAddress.FROM.toInternetAddress())) { 1767 try { 1768 InternetAddress [] fromArray = (InternetAddress []) mail.getMessage().getFrom(); 1769 if (fromArray != null) { 1770 for (int i = 0; i < fromArray.length; i++) { 1771 newList.add(fromArray[i]); 1772 } 1773 } else { 1774 MailAddress reversePath = mail.getSender(); 1775 if (reversePath != null) { 1776 newList.add(reversePath.toInternetAddress()); 1777 } 1778 } 1779 } catch (MessagingException me) { 1780 log("Unable to parse the \"FROM\" header in the original message; ignoring."); 1781 } 1782 } else if (internetAddress.equals(SpecialAddress.REPLY_TO.toInternetAddress())) { 1783 try { 1784 InternetAddress [] replyToArray = (InternetAddress []) mail.getMessage().getReplyTo(); 1785 if (replyToArray != null) { 1786 for (int i = 0; i < replyToArray.length; i++) { 1787 newList.add(replyToArray[i]); 1788 } 1789 } else { 1790 MailAddress reversePath = mail.getSender(); 1791 if (reversePath != null) { 1792 newList.add(reversePath.toInternetAddress()); 1793 } 1794 } 1795 } catch (MessagingException me) { 1796 log("Unable to parse the \"REPLY_TO\" header in the original message; ignoring."); 1797 } 1798 } else if (internetAddress.equals(SpecialAddress.TO.toInternetAddress()) 1799 || internetAddress.equals(SpecialAddress.RECIPIENTS.toInternetAddress())) { 1800 try { 1801 String [] toHeaders = mail.getMessage().getHeader(RFC2822Headers.TO); 1802 if (toHeaders != null) { 1803 for (int i = 0; i < toHeaders.length; i++) { 1804 try { 1805 InternetAddress [] originalToInternetAddresses = InternetAddress.parse(toHeaders[i], false); 1806 for (int j = 0; j < originalToInternetAddresses.length; j++) { 1807 newList.add(originalToInternetAddresses[j]); 1808 } 1809 } catch (MessagingException ae) { 1810 log("Unable to parse a \"TO\" header address in the original message: " + toHeaders[i] + "; ignoring."); 1811 } 1812 } 1813 } 1814 } catch (MessagingException ae) { 1815 log("Unable to parse the \"TO\" header in the original message; ignoring."); 1816 } 1817 } else if (internetAddress.equals(SpecialAddress.UNALTERED.toInternetAddress())) { 1818 continue; 1819 } else if (internetAddress.equals(SpecialAddress.NULL.toInternetAddress())) { 1820 continue; 1821 } else { 1822 newList.add(internetAddress); 1823 } 1824 } 1825 return newList; 1826 } 1827 1828} 1829 | Popular Tags |