vincenzo 2003/06/30 02:41:04
Modified: src/java/org/apache/james/transport/mailets
AbstractNotify.java AbstractRedirect.java
Bounce.java Forward.java GenericListserv.java
NotifyPostmaster.java NotifySender.java
Redirect.java Resend.java
Log:
AbstractRedirect hierarchy:
1) Enhancement and cleanup in default parameter management.
2) Throws MessagingException instead of log in case of address parsing errors.
3) Was not copying default headers in case of inline != unaltered - major fix.
4) Redirect supports <subject>
4) Applied Hontvari Joszef's patch for supporting non-ascii characters (involves
also GenericListserv).
Revision Changes Path
1.8 +4 -4
jakarta-james/src/java/org/apache/james/transport/mailets/AbstractNotify.java
Index: AbstractNotify.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/AbstractNotify.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- AbstractNotify.java 27 Jun 2003 14:25:46 -0000 1.7
+++ AbstractNotify.java 30 Jun 2003 09:41:03 -0000 1.8
@@ -258,10 +258,10 @@
}
/**
- * @return null
+ * @return [EMAIL PROTECTED] AbstractRedirect#getSender(Mail)}, meaning the new
requested sender if any
*/
- protected MailAddress getReturnPath() throws MessagingException {
- return null;
+ protected MailAddress getReturnPath(Mail originalMail) throws
MessagingException {
+ return getSender(originalMail);
}
/**
1.14 +169 -114
jakarta-james/src/java/org/apache/james/transport/mailets/AbstractRedirect.java
Index: AbstractRedirect.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/AbstractRedirect.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- AbstractRedirect.java 27 Jun 2003 14:25:46 -0000 1.13
+++ AbstractRedirect.java 30 Jun 2003 09:41:03 -0000 1.14
@@ -464,10 +464,12 @@
StringTokenizer st = new StringTokenizer(addressList, ",", false);
while(st.hasMoreTokens()) {
+ String token = null;
try {
- newRecipients.add(new MailAddress(st.nextToken()));
+ token = st.nextToken();
+ newRecipients.add(new MailAddress(token));
} catch(Exception e) {
- log("add recipient failed in getRecipients");
+ throw new MessagingException("Exception thrown in getRecipients()
parsing: " + token, e);
}
}
return newRecipients;
@@ -480,12 +482,13 @@
*
* @return [EMAIL PROTECTED] #getRecipients()},
* replacing <CODE>SpecialAddress.SENDER</CODE> if applicable with the original
sender
- * and <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null
+ * and <CODE>SpecialAddress.UNALTERED</CODE>
+ * and <CODE>SpecialAddress.RECIPIENTS</CODE> if applicable with null
*/
protected Collection getRecipients(Mail originalMail) throws MessagingException
{
Collection recipients = (isStatic()) ? this.recipients : getRecipients();
if (recipients != null && recipients.size() == 1) {
- if (recipients.contains(SpecialAddress.UNALTERED)) {
+ if (recipients.contains(SpecialAddress.UNALTERED) ||
recipients.contains(SpecialAddress.RECIPIENTS)) {
recipients = null;
} else if (recipients.contains(SpecialAddress.SENDER)) {
recipients = new ArrayList();
@@ -558,7 +561,7 @@
tokenx = rec.nextToken();
iaarray[i] = new InternetAddress(tokenx);
} catch(Exception e) {
- log("Internet address exception in getTo()");
+ throw new MessagingException("Exception thrown in getTo() parsing:
" + tokenx, e);
}
}
return iaarray;
@@ -583,6 +586,7 @@
* </LI>
* <LI>
* If <CODE>getTo()</CODE> returns
<CODE>SpecialAddress.UNALTERED</CODE>
+ * or <CODE>SpecialAddress.TO</CODE>
* it returns the original <I>TO:</I>.
* </LI>
* <LI>
@@ -595,7 +599,9 @@
* </UL>
*
* @return [EMAIL PROTECTED] #getTo()}, replacing
<CODE>SpecialAddress.SENDER</CODE>,
- * <CODE>SpecialAddress.SENDER</CODE> and <CODE>SpecialAddress.UNALTERED</CODE>
if applicable
+ * <CODE>SpecialAddress.SENDER</CODE>,
+ * <CODE>SpecialAddress.TO</CODE>,
+ * and <CODE>SpecialAddress.UNALTERED</CODE> if applicable
*/
protected InternetAddress[] getTo(Mail originalMail) throws MessagingException {
InternetAddress[] apparentlyTo = (isStatic()) ? this.apparentlyTo : getTo();
@@ -618,7 +624,8 @@
apparentlyTo = new InternetAddress[1];
apparentlyTo[0] = mailAddress.toInternetAddress();
}
- } else if
(apparentlyTo[0].equals(SpecialAddress.UNALTERED.toInternetAddress())) {
+ } else if
(apparentlyTo[0].equals(SpecialAddress.UNALTERED.toInternetAddress())
+ ||
apparentlyTo[0].equals(SpecialAddress.TO.toInternetAddress())) {
apparentlyTo = (InternetAddress[])
originalMail.getMessage().getRecipients(Message.RecipientType.TO);
} else if
(apparentlyTo[0].equals(SpecialAddress.RETURN_PATH.toInternetAddress())) {
MailAddress mailAddress = getExistingReturnPath(originalMail);
@@ -683,7 +690,7 @@
try {
return new MailAddress(addressString);
} catch(Exception e) {
- log("Parse error in getReplyTo: " + addressString);
+ throw new MessagingException("Exception thrown in getReplyTo()
parsing: " + addressString, e);
}
}
@@ -697,12 +704,15 @@
*
* @return [EMAIL PROTECTED] #getReplyTo()}
* replacing <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null
+ * and <CODE>SpecialAddress.SENDER</CODE> with the original mail sender
*/
protected MailAddress getReplyTo(Mail originalMail) throws MessagingException {
MailAddress replyTo = (isStatic()) ? this.replyTo : getReplyTo();
if (replyTo != null) {
if (replyTo == SpecialAddress.UNALTERED) {
replyTo = null;
+ } else if (replyTo == SpecialAddress.SENDER) {
+ replyTo = originalMail.getSender();
}
}
return replyTo;
@@ -710,25 +720,12 @@
/**
* <P>Sets the "Reply-To:" header of <I>newMail</I> to <I>replyTo</I>.</P>
- * <P>If the requested value is <CODE>SpecialAddress.SENDER</CODE> will use the
original "From:" header;
- * if this header is empty will use the original "Sender:" header;
- * if this header is empty will use the original sender.
* If the requested value is <CODE>SpecialAddress.NULL</CODE> will remove the
"Reply-To:" header.
* If the requested value is null does nothing.</P>
* Is a "setX(Mail, Tx, Mail)" method.
*/
protected void setReplyTo(Mail newMail, MailAddress replyTo, Mail originalMail)
throws MessagingException {
if(replyTo != null) {
- if (replyTo == SpecialAddress.SENDER) {
- replyTo = getSafeApparentSender(originalMail);
-
- // if still null give up.
- if (replyTo == null) {
- return;
- }
- }
-
- // do the job
InternetAddress[] iart = null;
if (replyTo != SpecialAddress.NULL) {
iart = new InternetAddress[1];
@@ -769,7 +766,7 @@
try {
return new MailAddress(addressString);
} catch(Exception e) {
- log("Parse error in getReturnPath: " + addressString);
+ throw new MessagingException("Exception thrown in getReturnPath()
parsing: " + addressString, e);
}
}
@@ -783,13 +780,15 @@
*
* @return [EMAIL PROTECTED] #getReturnPath()},
* replacing <CODE>SpecialAddress.SENDER</CODE> if applicable with the original
sender,
- * replacing <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null,
+ * replacing <CODE>SpecialAddress.UNALTERED</CODE>
+ * and <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null,
* but not replacing <CODE>SpecialAddress.NULL</CODE>
+ * that will be handled by [EMAIL PROTECTED] #setReturnPath}
*/
protected MailAddress getReturnPath(Mail originalMail) throws
MessagingException {
MailAddress returnPath = (isStatic()) ? this.returnPath : getReturnPath();
if (returnPath != null) {
- if (returnPath == SpecialAddress.UNALTERED) {
+ if (returnPath == SpecialAddress.UNALTERED || returnPath ==
SpecialAddress.RETURN_PATH) {
returnPath = null;
}
else if (returnPath == SpecialAddress.SENDER) {
@@ -844,7 +843,7 @@
try {
return new MailAddress(addressString);
} catch(Exception e) {
- log("Parse error in getSender: " + addressString);
+ throw new MessagingException("Exception thrown in getSender()
parsing: " + addressString, e);
}
}
@@ -857,12 +856,13 @@
* Is a "getX(Mail)" method.
*
* @return [EMAIL PROTECTED] #getSender()}
- * replacing <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null
+ * replacing <CODE>SpecialAddress.UNALTERED</CODE>
+ * and <CODE>SpecialAddress.SENDER</CODE> if applicable with null
*/
protected MailAddress getSender(Mail originalMail) throws MessagingException {
MailAddress sender = (isStatic()) ? this.sender : getSender();
if (sender != null) {
- if (sender == SpecialAddress.UNALTERED) {
+ if (sender == SpecialAddress.UNALTERED || sender ==
SpecialAddress.SENDER) {
sender = null;
}
}
@@ -870,35 +870,14 @@
}
/**
- * <P>Sets the sender and the "From:" header of <I>newMail</I> to
<I>sender</I>.</P>
- * <P>If the requested value is <CODE>SpecialAddress.SENDER</CODE> will use the
original "From:" header;
- * if this header is empty will use the original "Sender:" header;
- * if this header is empty will use the original sender.
- * If the requested value is null does nothing.</P>
+ * Sets the sender and the "From:" header of <I>newMail</I> to <I>sender</I>.
+ * If the requested value is null does nothing.
* Is a "setX(Mail, Tx, Mail)" method.
*/
protected void setSender(Mail newMail, MailAddress sender, Mail originalMail)
throws MessagingException {
if (sender != null) {
- if (sender == SpecialAddress.SENDER) {
- MailAddress newSender = getSafeApparentSender(originalMail);
- String newFromHeader = getSafeFromHeader(originalMail);
-
- if (!newFromHeader.trim().equals("")) {
- newMail.getMessage().setHeader(RFC2822Headers.FROM,
newFromHeader);
- }
-
- if (newSender != null) {
- ((MailImpl) newMail).setSender(newSender);
- }
-
- // The new code should be compatible with and extend the previous
code:
-// MailAddress originalSender = new MailAddress(((InternetAddress)
originalMail.getMessage().getFrom()[0]).getAddress());
-// newMail.getMessage().setHeader(RFC2822Headers.FROM,
originalMail.getMessage().getHeader(RFC2822Headers.FROM, ","));
-// ((MailImpl) newMail).setSender(originalSender);
- } else {
- newMail.getMessage().setFrom(sender.toInternetAddress());
- ((MailImpl) newMail).setSender(sender);
- }
+ newMail.getMessage().setFrom(sender.toInternetAddress());
+ ((MailImpl) newMail).setSender(sender);
if (isDebug) {
log("sender set to: " + sender);
@@ -907,44 +886,6 @@
}
/**
- * <P>Gets a safe "apparent" sender using the original "From:" header if
possible.</P>
- * <P>Will use the original "From:" header;
- * if this header is empty will use the original "Sender:" header;
- * if this header is empty will use the original sender.</P>
- */
- private MailAddress getSafeApparentSender(Mail originalMail) throws
MessagingException {
- MailAddress sender = null;
- InternetAddress from = (InternetAddress)
originalMail.getMessage().getFrom()[0];
-
- if (from == null) {
- // perhaps this is redundant, but just in case ...
- from = originalMail.getSender().toInternetAddress();
- }
- if (from != null) {
- sender = new MailAddress(from.getAddress());
- }
-
- return sender;
- }
-
- /**
- * <P>Gets a safe "From:" header using the original if possible.</P>
- * <P>Will use the original "From:" header;
- * if this header is empty will use the original "Sender:" header;
- * if this header is empty will use the original sender.</P>
- */
- private String getSafeFromHeader(Mail originalMail) throws MessagingException {
- MailAddress sender = getSafeApparentSender(originalMail);
- String fromHeader =
originalMail.getMessage().getHeader(RFC2822Headers.FROM, ",");
-
- if (fromHeader.trim().equals("") && sender != null) {
- fromHeader = sender.toInternetAddress().toString();
- }
-
- return fromHeader;
- }
-
- /**
* Gets the <CODE>subject</CODE> property.
* Returns a string for the new message subject.
* Is a "getX()" method.
@@ -980,7 +921,7 @@
*/
protected String getSubjectPrefix() throws MessagingException {
if(getInitParameter("prefix") == null) {
- return "";
+ return null;
} else {
return getInitParameter("prefix");
}
@@ -1001,18 +942,33 @@
/**
* Builds the subject of <I>newMail</I> appending the subject
* of <I>originalMail</I> to <I>subjectPrefix</I>.
+ * Is a "setX(Mail, Tx, Mail)" method.
*/
protected void setSubjectPrefix(Mail newMail, String subjectPrefix, Mail
originalMail) throws MessagingException {
String subject = getSubject(originalMail);
- if (subject == null) {
- subject = originalMail.getMessage().getSubject();
- }
- if (subject == null) {
- subject = "";
- }
- newMail.getMessage().setSubject(subjectPrefix + subject);
- if (isDebug) {
- log("subjectPrefix set to: " + subjectPrefix);
+ if ((subjectPrefix != null && subjectPrefix.length() > 0) || subject !=
null) {
+ if (subject == null) {
+ subject = originalMail.getMessage().getSubject();
+ } else {
+ // replacing the subject
+ if (isDebug) {
+ log("subject set to: " + subject);
+ }
+ }
+ // Was null in original?
+ if (subject == null) {
+ subject = "";
+ }
+
+ if (subjectPrefix != null) {
+ subject = subjectPrefix + subject;
+ // adding a prefix
+ if (isDebug) {
+ log("subjectPrefix set to: " + subjectPrefix);
+ }
+ }
+// newMail.getMessage().setSubject(subject);
+ changeSubject(newMail.getMessage(), subject);
}
}
@@ -1194,8 +1150,6 @@
// handle the new message if altered
buildAlteredMessage(newMail, originalMail);
- setTo(newMail, getTo(originalMail), originalMail);
-
} else {
// if we need the original, create a copy of this message to redirect
if (getPassThrough(originalMail)) {
@@ -1218,6 +1172,8 @@
setRecipients(newMail, getRecipients(originalMail), originalMail);
+ setTo(newMail, getTo(originalMail), originalMail);
+
setSubjectPrefix(newMail, getSubjectPrefix(originalMail), originalMail);
if(newMail.getMessage().getHeader(RFC2822Headers.DATE) == null) {
@@ -1248,9 +1204,9 @@
.append(((MailImpl) originalMail).getName())
.append(". Invalid sender domain for ")
.append(newMail.getSender())
- .append(". Consider using the Redirect mailet ")
+ .append(". Consider using the Resend mailet ")
.append("using a different sender.");
- log(logBuffer.toString());
+ throw new MessagingException(logBuffer.toString());
}
if(!getPassThrough(originalMail)) {
@@ -1330,7 +1286,7 @@
* Gets the MailAddress corresponding to the existing "Return-Path" header of
* <I>mail</I>.
* If empty returns <CODE>SpecialAddress.NULL</CODE>,
- * if missing return <CODE>SpecialAddress.SENDER</CODE>.
+ * if missing return <CODE>null</CODE>.
*/
protected MailAddress getExistingReturnPath(Mail mail) throws
MessagingException {
MailAddress mailAddress = null;
@@ -1467,11 +1423,25 @@
*/
protected void buildAlteredMessage(Mail newMail, Mail originalMail) throws
MessagingException {
- MimeMessage message = originalMail.getMessage();
+ MimeMessage originalMessage = originalMail.getMessage();
+ MimeMessage newMessage = newMail.getMessage();
+
+ // Copy the relevant headers
+ String[] relevantHeaderNames =
+ {RFC2822Headers.DATE,
+ RFC2822Headers.FROM,
+ RFC2822Headers.REPLY_TO,
+ RFC2822Headers.TO,
+ RFC2822Headers.SUBJECT,
+ RFC2822Headers.RETURN_PATH};
+ Enumeration headerEnum =
originalMessage.getMatchingHeaderLines(relevantHeaderNames);
+ while (headerEnum.hasMoreElements()) {
+ newMessage.addHeaderLine((String) headerEnum.nextElement());
+ }
StringWriter sout = new StringWriter();
PrintWriter out = new PrintWriter(sout, true);
- String head = getMessageHeaders(message);
+ String head = getMessageHeaders(originalMessage);
boolean all = false;
String messageText = getMessage(originalMail);
@@ -1494,7 +1464,7 @@
case BODY: //BODY:
out.println("Message:");
try {
- out.println(getMessageBody(message));
+ out.println(getMessageBody(originalMessage));
} catch(Exception e) {
out.println("body unavailable");
}
@@ -1530,7 +1500,7 @@
break;
case BODY: //BODY:
try {
- part.setText(getMessageBody(message));
+ part.setText(getMessageBody(originalMessage));
} catch(Exception e) {
part.setText("body unavailable");
}
@@ -1540,15 +1510,15 @@
new StringBuffer(1024)
.append(head)
.append("\r\nMessage:\r\n")
- .append(getMessageBody(message));
+ .append(getMessageBody(originalMessage));
part.setText(textBuffer.toString());
break;
case MESSAGE: //MESSAGE:
- part.setContent(message, "message/rfc822");
+ part.setContent(originalMessage, "message/rfc822");
break;
}
- if ((message.getSubject() != null) &&
(message.getSubject().trim().length() > 0)) {
- part.setFileName(message.getSubject().trim());
+ if ((originalMessage.getSubject() != null) &&
(originalMessage.getSubject().trim().length() > 0)) {
+ part.setFileName(originalMessage.getSubject().trim());
} else {
part.setFileName("No Subject");
}
@@ -1703,6 +1673,91 @@
throw new MessagingException("Unexpected init parameters found: "
+ arrayToString(bad.toArray()));
}
+ }
+
+ /**
+ * It changes the subject of the supplied message to to supplied value
+ * but it also tries to preserve the original charset information.
+ *
+ * This method was needed to avoid sending the subject using a charset
+ * (usually the default charset on the server) which doesn't contain
+ * the characters in the subject, resulting in the loss of these characters.
+ * The most simple method would be to either send it in ASCII unencoded
+ * or in UTF-8 if non-ASCII characters are present but unfortunately UTF-8
+ * is not yet a MIME standard and not all email clients
+ * are supporting it. The optimal method would be to determine the best
+ * charset by analyzing the actual characters. That would require much
+ * more work (exept if an open source library already exists for this).
+ * However there is nothing to stop somebody to add a detection algorithm
+ * for a specific charset.
+ *
+ * The current algorithm works correctly if only ASCII characters are
+ * added to an existing subject.
+ *
+ * If the new value is ASCII only, then it doesn't apply any encoding to
+ * the subject header. (This is provided by MimeMessage.setSubject()).
+ *
+ * Possible enhancement: under java 1.4 java.nio the system can determine if
the
+ * suggested charset fits or not (if there is untranslatable
+ * characters). If the charset doesn't fit the new value, it
+ * can fall back to UTF-8.
+ *
+ * @param message the message of which subject is changed
+ * @param newValue the new (unencoded) value of the subject. It must
+ * not be null.
+ * @throws MessagingException - according to the JavaMail doc most likely
+ * this is never thrown
+ */
+ public static void changeSubject(MimeMessage message, String newValue)
+ throws MessagingException
+ {
+ String rawSubject = message.getHeader(RFC2822Headers.SUBJECT, null);
+ String mimeCharset = determineMailHeaderEncodingCharset(rawSubject);
+ if (mimeCharset == null) { // most likely ASCII
+ // it uses the system charset or the value of the
+ // mail.mime.charset property if set
+ message.setSubject(newValue);
+ return;
+ } else { // original charset determined
+ String javaCharset =
javax.mail.internet.MimeUtility.javaCharset(mimeCharset);
+ try {
+ message.setSubject(newValue, javaCharset);
+ } catch (MessagingException e) {
+ // known, but unsupported encoding
+ // this should be logged, the admin may setup a more i18n
+ // capable JRE, but the log API cannot be accessed from here
+ //if (charset != null) log(charset +
+ // " charset unsupported by the JRE, email subject may be
damaged");
+ message.setSubject(newValue); // recover
+ }
+ }
+ }
+
+ /**
+ * It attempts to determine the charset used to encode an "unstructured"
+ * RFC 822 header (like Subject). The encoding is specified in RFC 2047.
+ * If it cannot determine or the the text is not encoded then it returns null.
+ *
+ * Here is an example raw text:
+ * Subject: =?iso-8859-2?Q?leg=FAjabb_pr=F3ba_l=F5elemmel?=
+ *
+ * @param rawText the raw (not decoded) value of the header
+ * @return the MIME charset name or null if no encoding applied
+ */
+ static private String determineMailHeaderEncodingCharset(String rawText)
+ {
+ int iEncodingPrefix = rawText.indexOf("=?");
+ if (iEncodingPrefix == -1) return null;
+ int iCharsetBegin = iEncodingPrefix + 2;
+ int iSecondQuestionMark = rawText.indexOf('?', iCharsetBegin);
+ if (iSecondQuestionMark == -1) return null;
+ // safety checks
+ if (iSecondQuestionMark == iCharsetBegin) return null; // empty charset?
impossible
+ int iThirdQuestionMark = rawText.indexOf('?', iSecondQuestionMark + 1);
+ if (iThirdQuestionMark == -1) return null; // there must be one after
encoding
+ if (-1 == rawText.indexOf("?=", iThirdQuestionMark + 1)) return null; //
closing tag
+ String mimeCharset = rawText.substring(iCharsetBegin, iSecondQuestionMark);
+ return mimeCharset;
}
}
1.8 +8 -5
jakarta-james/src/java/org/apache/james/transport/mailets/Bounce.java
Index: Bounce.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/Bounce.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- Bounce.java 27 Jun 2003 14:25:47 -0000 1.7
+++ Bounce.java 30 Jun 2003 09:41:03 -0000 1.8
@@ -58,7 +58,6 @@
package org.apache.james.transport.mailets;
-import org.apache.mailet.RFC2822Headers;
import org.apache.mailet.GenericMailet;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
@@ -133,7 +132,7 @@
* <debug><I>true or false</I></debug>
* </mailet>
* </CODE></PRE>
- * <P><I>notice</I>, <I>senderAddress</I> and <I>attachStackTrace</I> can be used
instead of
+ * <P><I>notice</I>, <I>sendingAddress</I> and <I>attachStackTrace</I> can be used
instead of
* <I><I>message</I>, <I>sender</I> and <I>attachError</I>; such names are kept for
backward compatibility.</P>
*
* @version CVS $Revision$ $Date$
@@ -161,6 +160,7 @@
"attachment",
"message",
"notice",
+ "sender",
"sendingAddress",
"prefix",
"attachError",
@@ -194,7 +194,7 @@
/**
* @return <CODE>SpecialAddress.NULL</CODE> (the meaning of bounce)
*/
- protected MailAddress getReturnPath() {
+ protected MailAddress getReturnPath(Mail originalMail) {
return SpecialAddress.NULL;
}
@@ -215,8 +215,11 @@
if (returnAddress == SpecialAddress.NULL) {
if (isDebug)
log("Processing a bounce request for a message with an empty return
path. No bounce will be sent.");
+ if(!getPassThrough(originalMail)) {
+ originalMail.setState(Mail.GHOST);
+ }
return;
- } else if (returnAddress == SpecialAddress.SENDER) {
+ } else if (returnAddress == null) {
log("WARNING: Mail to be bounced does not contain a Return-Path
header.");
} else {
if (isDebug)
1.16 +2 -2
jakarta-james/src/java/org/apache/james/transport/mailets/Forward.java
Index: Forward.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/Forward.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- Forward.java 27 Jun 2003 14:25:47 -0000 1.15
+++ Forward.java 30 Jun 2003 09:41:03 -0000 1.16
@@ -204,7 +204,7 @@
* @return ""
*/
protected String getSubjectPrefix() throws MessagingException {
- return "";
+ return null;
}
/**
1.20 +1 -94
jakarta-james/src/java/org/apache/james/transport/mailets/GenericListserv.java
Index: GenericListserv.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/GenericListserv.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- GenericListserv.java 29 May 2003 20:39:01 -0000 1.19
+++ GenericListserv.java 30 Jun 2003 09:41:03 -0000 1.20
@@ -199,90 +199,6 @@
}
/**
- * It attempts to determine the charset used to encode an "unstructured"
- * RFC 822 header (like Subject). The encoding is specified in RFC 2047.
- * If it cannot determine or the the text is not encoded then it returns null.
- *
- * Under Java 1.4 it further checks if the encoding is supported under the
- * current runtime environment.
- *
- * In some cases it returns UTF-8 as a fallback charset. This is not
- * an official MIME standard yet, and most importantly not all email client
- * support it, but it is likely better then the server default.
- *
- * Here is an example raw text:
- * Subject: =?iso-8859-2?Q?leg=FAjabb_pr=F3ba_l=F5elemmel?=
- *
- * Possible enhancement: under java 1.4 java.nio the system can determine if
the
- * suggested charset fits or not (if there is untranslatable
- * characters). If the charset doesn't fit the new value, it
- * can fall back to UTF-8.
- *
- * @param rawText the raw (not decoded) value of the header
- * @return the java charset name or null if no encoding applied
- */
- static private String determineMailHeaderEncodingCharset(String rawText)
- {
- int iEncodingPrefix = rawText.indexOf("=?");
- if (iEncodingPrefix == -1) return null;
- int iCharsetBegin = iEncodingPrefix + 2;
- int iSecondQuestionMark = rawText.indexOf('?', iCharsetBegin);
- if (iSecondQuestionMark == -1) return null;
- // safety checks
- if (iSecondQuestionMark == iCharsetBegin) return null; // empty charset?
impossible
- int iThirdQuestionMark = rawText.indexOf('?', iSecondQuestionMark + 1);
- if (iThirdQuestionMark == -1) return null; // there must be one after
encoding
- if (-1 == rawText.indexOf("?=", iThirdQuestionMark + 1)) return null; //
closing tag
-
- String mimeCharset = rawText.substring(iCharsetBegin, iSecondQuestionMark);
- String javaCharset =
javax.mail.internet.MimeUtility.javaCharset(mimeCharset);
-
- // using reflection for a JRE 1.4 function
- if (charsetIsSupportedMethod == null) return javaCharset; // pre 1.4 runtime
-
- try {
- String[] arguments = { javaCharset };
- Boolean isSupported = (Boolean)charsetIsSupportedMethod.invoke(null,
arguments);
- if (isSupported.booleanValue())
- return javaCharset;
- else
- // UTF-8 must be supported by every JRE, and it is better then
server default,
- // even if a few clients don't support it yet.
- // I use UTF-8 instead of UTF8 because there is no java-MIME
mapping,
- // and official MIME code yet, so this will be directly used as a
MIME
- // code, and it is the quasi-standard MIME code (OE uses this).
- return "UTF-8";
- } catch (java.lang.reflect.InvocationTargetException e) {
- // it was thrown by Charset.isSupported, illegal charset name
- return "UTF-8";
- } catch (Exception e) {
- // impossible
- return javaCharset;
- }
- }
-
- /**
- * JRE 1.4 specific method, java.nio.charset.Charset.isSupported(String).
- * This field is initialized by the static initialization block and
- * is used by the determineMailHeaderEncodingCharset method.
- * James doesn't require JRE 1.4 so we must use reflection.
- */
- static private java.lang.reflect.Method charsetIsSupportedMethod;
-
- /**
- * class initialization, it initializes the charsetIsSupportedMethod member
- */
- static {
- try {
- Class charsetClass = Class.forName("java.nio.charset.Charset");
- Class[] parameterTypes = { String.class };
- charsetIsSupportedMethod = charsetClass.getMethod("isSupported",
parameterTypes);
- } catch (Exception e) {
- charsetIsSupportedMethod = null; // pre 1.4 runtime
- }
- }
-
- /**
* Processes the message. Assumes it is the only recipient of this forked
message.
*/
public final void service(Mail mail) throws MessagingException {
@@ -335,21 +251,12 @@
.append("] ");
prefix = prefixBuffer.toString();
}
- String rawSubject = message.getHeader(RFC2822Headers.SUBJECT, null);
- String charset = determineMailHeaderEncodingCharset(rawSubject);
String subj = message.getSubject();
if (subj == null) {
subj = "";
}
subj = normalizeSubject(subj, prefix);
- try {
- message.setSubject(subj, charset);
- } catch (MessagingException e) {
- // known, but unsupported encoding
- if (charset != null) log(charset +
- " charset unsupported by the JRE, email subject may be
damaged");
- message.setSubject(subj); // recover
- }
+ AbstractRedirect.changeSubject(message, subj);
}
//If replies should go to this list, we need to set the header
1.20 +3 -2
jakarta-james/src/java/org/apache/james/transport/mailets/NotifyPostmaster.java
Index: NotifyPostmaster.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/NotifyPostmaster.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- NotifyPostmaster.java 27 Jun 2003 14:25:47 -0000 1.19
+++ NotifyPostmaster.java 30 Jun 2003 09:41:03 -0000 1.20
@@ -129,7 +129,7 @@
* <debug><I>true or false</I></debug>
* </mailet>
* </CODE></PRE>
- * <P><I>notice</I>, <I>senderAddress</I> and <I>attachStackTrace</I> can be used
instead of
+ * <P><I>notice</I>, <I>sendingAddress</I> and <I>attachStackTrace</I> can be used
instead of
* <I><I>message</I>, <I>sender</I> and <I>attachError</I>; such names are kept for
backward compatibility.</P>
*
* @version CVS $Revision$ $Date$
@@ -156,6 +156,7 @@
"attachment",
"message",
"notice",
+ "sender",
"sendingAddress",
"prefix",
"attachError",
1.23 +3 -2
jakarta-james/src/java/org/apache/james/transport/mailets/NotifySender.java
Index: NotifySender.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/NotifySender.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- NotifySender.java 27 Jun 2003 14:25:47 -0000 1.22
+++ NotifySender.java 30 Jun 2003 09:41:03 -0000 1.23
@@ -128,7 +128,7 @@
* <debug><I>true or false</I></debug>
* </mailet>
* </CODE></PRE>
- * <P><I>notice</I>, <I>senderAddress</I> and <I>attachStackTrace</I> can be used
instead of
+ * <P><I>notice</I>, <I>sendingAddress</I> and <I>attachStackTrace</I> can be used
instead of
* <I><I>message</I>, <I>sender</I> and <I>attachError</I>; such names are kept for
backward compatibility.</P>
*
* @version CVS $Revision$ $Date$
@@ -155,6 +155,7 @@
"attachment",
"message",
"notice",
+ "sender",
"sendingAddress",
"prefix",
"attachError",
1.32 +58 -17
jakarta-james/src/java/org/apache/james/transport/mailets/Redirect.java
Index: Redirect.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/Redirect.java,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- Redirect.java 27 Jun 2003 14:25:47 -0000 1.31
+++ Redirect.java 30 Jun 2003 09:41:03 -0000 1.32
@@ -90,11 +90,13 @@
* <P>A mailet providing configurable redirection services.</P>
* <P>Can produce listserver, forward and notify behaviour, with the original
* message intact, attached, appended or left out altogether.</P>
- * <P>It is kept only for compatibility, use instead [EMAIL PROTECTED] Resend}.
- * It differs from <CODE>Resend</CODE> because (i) some defaults are different,
- * notably for the following parameters: <I><recipients></I>,
<I><to></I> and <I><inline></I>;
- * (ii) because it allows the use of the <I><static></I> parameter;
- * (iii) because it lacks the <I><subject></I> parameter.</P>
+ * <P>It differs from [EMAIL PROTECTED] Resend} because
+ * (i) some defaults are different,
+ * notably for the following parameters: <I><recipients></I>,
<I><to></I>,
+ * <I><returnPath></I> and <I><inline></I>;
+ * (ii) because it allows the use of the <I><static></I> parameter;.<BR>
+ * Use <CODE>Resend</CODE> if you need full control, <CODE>Redirect</CODE> if
+ * the more automatic behaviour of some parameters is appropriate.</P>
* <P>This built in functionality is controlled by the configuration as laid out
below.
* In the table please note that the parameters controlling message headers
* accept the <B>"unaltered"</B> value, whose meaning is to keep the
associated
@@ -127,10 +129,9 @@
* <TR valign=top>
* <TD width="20%"><sender></TD>
* <TD width="80%">
- * A single email address to appear in the From: header and become the sender.<BR>
+ * A single email address to appear in the From: and Return-Path: headers and
become the sender.<BR>
* It can include constants "sender", "postmaster" and
"unaltered";
- * if "sender" is specified then it will follow a safe procedure from the
- * original From: header (see [EMAIL PROTECTED] AbstractRedirect#setSender} and
[EMAIL PROTECTED] AbstractRedirect#getSender(Mail)}).<BR>
+ * "sender" is equivalent to "unaltered".<BR>
* Default: "unaltered".
* </TD>
* </TR>
@@ -209,26 +210,34 @@
* <TD width="80%">
* A single email address to appear in the Reply-To: header.<BR>
* It can include constants "sender", "postmaster"
"null" and "unaltered";
- * if "sender" is specified then it will follow a safe procedure from the
- * original From: header (see [EMAIL PROTECTED] AbstractRedirect#setReplyTo} and
[EMAIL PROTECTED] AbstractRedirect#getReplyTo(Mail)});
* if "null" is specified it will remove this header.<BR>
* Default: "unaltered".
* </TD>
* </TR>
+ * </TR>
* <TR valign=top>
* <TD width="20%"><returnPath></TD>
* <TD width="80%">
* A single email address to appear in the Return-Path: header.<BR>
- * It can include constants "sender", "postmaster"
"null"and "unaltered";
+ * It can include constants "sender", "postmaster" and
"null";
* if "null" is specified then it will set it to <>, meaning "null
return path".<BR>
- * Default: "unaltered".
+ * Notice: the "unaltered" value is <I>not allowed</I>.<BR>
+ * Default: the value of the <I><sender></I> parameter, if set, otherwise
remains unaltered.
+ * </TD>
+ * </TR>
+ * <TR valign=top>
+ * <TD width="20%"><subject></TD>
+ * <TD width="80%">
+ * An optional string to use as the subject.<BR>
+ * Default: keep the original message subject.
* </TD>
* </TR>
* <TR valign=top>
* <TD width="20%"><prefix></TD>
* <TD width="80%">
* An optional subject prefix prepended to the original message
- * subject, for example: <I>[Undeliverable mail]</I>.<BR>
+ * subject, or to a new subject specified with the <I><subject></I>
parameter.<BR>
+ * For example: <I>[Undeliverable mail]</I>.<BR>
* Default: "".
* </TD>
* </TR>
@@ -323,7 +332,7 @@
"replyto",
"returnPath",
"sender",
-// "subject",
+ "subject",
"prefix",
"attachError",
"isReply"
@@ -432,10 +441,42 @@
}
/**
- * @return null
+ * @return the <CODE>returnPath</CODE> init parameter
+ * or the postmaster address
+ * or <CODE>SpecialAddress.SENDER</CODE>
+ * or <CODE>SpecialAddress.NULL</CODE>
+ * or <CODE>null</CODE> if missing
*/
- protected String getSubject() {
+ protected MailAddress getReturnPath() throws MessagingException {
+ String addressString = getInitParameter("returnPath");
+ if(addressString != null) {
+ MailAddress specialAddress = getSpecialAddress(addressString,
+ new String[] {"postmaster", "sender",
"null"});
+ if (specialAddress != null) {
+ return specialAddress;
+ }
+
+ try {
+ return new MailAddress(addressString);
+ } catch(Exception e) {
+ throw new MessagingException("Exception thrown in getReturnPath()
parsing: " + addressString, e);
+ }
+ }
+
return null;
+ }
+
+ /**
+ * @return [EMAIL PROTECTED] AbstractRedirect#getReturnPath()};
+ * if null return [EMAIL PROTECTED] AbstractRedirect#getSender(Mail)},
+ * meaning the new requested sender if any
+ */
+ protected MailAddress getReturnPath(Mail originalMail) throws
MessagingException {
+ MailAddress returnPath = super.getReturnPath(originalMail);
+ if (returnPath == null) {
+ returnPath = getSender(originalMail);
+ }
+ return returnPath;
}
/* ******************************************************************** */
1.2 +7 -8
jakarta-james/src/java/org/apache/james/transport/mailets/Resend.java
Index: Resend.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/transport/mailets/Resend.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Resend.java 27 Jun 2003 14:15:13 -0000 1.1
+++ Resend.java 30 Jun 2003 09:41:04 -0000 1.2
@@ -90,8 +90,10 @@
* <P>A mailet providing configurable redirection services.</P>
* <P>Can produce listserver, forward and notify behaviour, with the original
* message intact, attached, appended or left out altogether.
- * Should be used as a replacement to [EMAIL PROTECTED] Redirect}, as defaults are
more consistent,
- * and has new options available.</P>
+ * Can be used as a replacement to [EMAIL PROTECTED] Redirect}, having more
consistent defaults,
+ * and new options available.<BR>
+ * Use <CODE>Resend</CODE> if you need full control, <CODE>Redirect</CODE> if
+ * the more automatic behaviour of some parameters is appropriate.</P>
* <P>This built in functionality is controlled by the configuration as laid out
below.
* In the table please note that the parameters controlling message headers
* accept the <B>"unaltered"</B> value, whose meaning is to keep the
associated
@@ -121,8 +123,7 @@
* <TD width="80%">
* A single email address to appear in the From: header and become the sender.<BR>
* It can include constants "sender", "postmaster" and
"unaltered";
- * if "sender" is specified then it will follow a safe procedure from the
- * original From: header (see [EMAIL PROTECTED] AbstractRedirect#setSender} and
[EMAIL PROTECTED] AbstractRedirect#getSender(Mail)}).<BR>
+ * "sender" is equivalent to "unaltered".<BR>
* Default: "unaltered".
* </TD>
* </TR>
@@ -201,8 +202,6 @@
* <TD width="80%">
* A single email address to appear in the Reply-To: header.<BR>
* It can include constants "sender", "postmaster"
"null" and "unaltered";
- * if "sender" is specified then it will follow a safe procedure from the
- * original From: header (see [EMAIL PROTECTED] AbstractRedirect#setReplyTo} and
[EMAIL PROTECTED] AbstractRedirect#getReplyTo(Mail)});
* if "null" is specified it will remove this header.<BR>
* Default: "unaltered".
* </TD>
@@ -211,7 +210,7 @@
* <TD width="20%"><returnPath></TD>
* <TD width="80%">
* A single email address to appear in the Return-Path: header.<BR>
- * It can include constants "sender", "postmaster"
"null"and "unaltered";
+ * It can include constants "sender", "postmaster"
"null" and "unaltered";
* if "null" is specified then it will set it to <>, meaning "null
return path".<BR>
* Default: "unaltered".
* </TD>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]