> I hope this time both attachements make the way to you, but
> I'll doublecheck
again the mailet got lost .. I'll resend it as .java.txt
Andreas
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache", "Jakarta", "JAMES" and "Apache Software Foundation"
* must not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
package org.apache.james.transport.mailets;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.james.core.MailImpl;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.apache.mailet.RFC2822Headers;
import org.apache.mailet.dates.RFC822DateFormat;
/**
*
* <P>Generates a Delivery Status Notification (DSN)
* Note that this is different than a mail-client's
* reply, which would use the Reply-To or From header.</P>
* <P>Bounced messages are attached in their entirety (headers and
* content) and the resulting MIME part type is "message/rfc822".<BR>
* The reverse-path and the Return-Path header of the response is set to "null" ("<>"),
* meaning that no reply should be sent.</P>
* <P>A sender of the notification message can optionally be specified.
* If one is not specified, the postmaster's address will be used.<BR>
* <P>Supports the <CODE>passThrough</CODE> init parameter (true if missing).</P>
*
* <P>Sample configuration:</P>
* <PRE><CODE>
* <mailet match="All" class="DSNBounce">
* <sender><I>an address or postmaster or sender or unaltered,
default=postmaster</I></sender>
* <prefix><I>optional subject prefix prepended to the original
message</I></prefix>
* <attachment><I>message or none, default=message</I></attachment>
* <passThrough><I>true or false, default=true</I></passThrough>
* <debug><I>true or false, default=false</I></debug>
* </mailet>
* </CODE></PRE>
*
*
* @author Andreas Göggerle <[EMAIL PROTECTED]>
*
* @see org.apache.james.transport.mailets.AbstractNotify
*/
public class DSNBounce extends AbstractNotify {
// /**
// *
// * @author Andreas Göggerle <[EMAIL PROTECTED]>
// */
//
// public class DSNMessage extends MimeMessage {
//
// private String type = "";
//
// public DSNMessage() {
// super(Session.getDefaultInstance(System.getProperties(), null));
// }
//
// public void setContent(Object o, String type) throws MessagingException {
// this.type = type;
// super.content = (byte[])o;
// }
//
// public void writeContentTo(OutputStream outs)
// throws java.io.IOException, MessagingException {
// outs.write(super.content);
// outs.flush();
// }
//
// public void writeTo(OutputStream outs, String as[])
// throws IOException, MessagingException
// {
// outs.write(super.content);
// outs.flush();
// }
//
// }
/**
* Constants and getters for RFC 3463 Enhanced Mail System Status Codes
*
* I suggest do extract this inner class for future use in the smtp-handler
*
* @author Andreas Göggerle <[EMAIL PROTECTED]>
*/
public static class DSNStatus {
// status code classes
/**
* Success
*/
public static final int SUCCESS = 2;
/**
* Persistent Transient Failure
*/
public static final int TRANSIENT = 4;
/**
* Permanent Failure
*/
public static final int PERMANENT = 5;
// subjects and details
/**
* Other or Undefined Status
*/
public static final int UNDEFINED = 0;
/**
* Other undefined status
*/
public static final String UNDEFINED_STATUS = "0.0";
/**
* Addressing Status
*/
public static final int ADDRESS = 1;
/**
* Other address status
*/
public static final String ADDRESS_OTHER = "1.0";
/**
* Bad destination mailbox address
*/
public static final String ADDRESS_MAILBOX = "1.1";
/**
* Bad destination system address
*/
public static final String ADDRESS_SYSTEM = "1.2";
/**
* Bad destination mailbox address syntax
*/
public static final String ADDRESS_SYNTAX = "1.3";
/**
* Destination mailbox address ambiguous
*/
public static final String ADDRESS_AMBIGUOUS = "1.4";
/**
* Destination Address valid
*/
public static final String ADDRESS_VALID = "1.5";
/**
* Destimation mailbox has moved, no forwarding address
*/
public static final String ADDRESS_MOVED = "1.6";
/**
* Bad sender's mailbox address syntax
*/
public static final String ADDRESS_SYNTAX_SENDER = "1.7";
/**
* Bad sender's system address
*/
public static final String ADDRESS_SYSTEM_SENDER = "1.8";
/**
* Mailbox Status
*/
public static final int MAILBOX = 2;
/**
* Other or Undefined Mailbox Status
*/
public static final String MAILBOX_OTHER = "2.0";
/**
* Mailbox disabled, not accepting messages
*/
public static final String MAILBOX_DISABLED = "2.1";
/**
* Mailbox full
*/
public static final String MAILBOX_FULL = "2.2";
/**
* Message length exceeds administrative limit
*/
public static final String MAILBOX_MSG_TOO_BIG = "2.3";
/**
* Mailing list expansion problem
*/
public static final String MAILBOX_LIST_EXPANSION = "2.4";
/**
* Mail System Status
*/
public static final int SYSTEM = 3;
/**
* Other or undefined mail system status
*/
public static final String SYSTEM_OTHER = "3.0";
/**
* Mail system full
*/
public static final String SYSTEM_FULL = "3.1";
/**
* System not accepting messages
*/
public static final String SYSTEM_NOT_ACCEPTING = "3.2";
/**
* System not capable of selected features
*/
public static final String SYSTEM_NOT_CAPABLE = "3.3";
/**
* Message too big for system
*/
public static final String SYSTEM_MSG_TOO_BIG = "3.4";
/**
* System incorrectly configured
*/
public static final String SYSTEM_CFG_ERROR = "3.5";
/**
* Network and Routing Status
*/
public static final int NETWORK = 4;
/**
* Other or undefined network or routing status
*/
public static final String NETWORK_OTHER = "4.0";
/**
* No answer form host
*/
public static final String NETWORK_NO_ANSWER = "4.1";
/**
* Bad Connection
*/
public static final String NETWORK_CONNECTION = "4.2";
/**
* Directory server failure
*/
public static final String NETWORK_DIR_SERVER = "4.3";
/**
* Unable to route
*/
public static final String NETWORK_ROUTE = "4.4";
/**
* Mail system congestion
*/
public static final String NETWORK_CONGESTION = "4.5";
/**
* Routing loop detected
*/
public static final String NETWORK_LOOP = "4.6";
/**
* Delivery time expired
*/
public static final String NETWORK_EXPIRED = "4.7";
/**
* Mail Delivery Protocol Status
*/
public static final int DELIVERY = 5;
/**
* Other or undefined (SMTP) protocol status
*/
public static final String DELIVERY_OTHER = "5.0";
/**
* Invalid command
*/
public static final String DELIVERY_INVALID_CMD = "5.1";
/**
* Syntax error
*/
public static final String DELIVERY_SYNTAX = "5.2";
/**
* Too many recipients
*/
public static final String DELIVERY_TOO_MANY_REC = "5.3";
/**
* Invalid command arguments
*/
public static final String DELIVERY_INVALID_ARG = "5.4";
/**
* Wrong protocol version
*/
public static final String DELIVERY_VERSION = "5.5";
/**
* Message Content or Media Status
*/
public static final int CONTENT = 6;
/**
* Other or undefined media error
*/
public static final String CONTENT_OTHER = "6.0";
/**
* Media not supported
*/
public static final String CONTENT_UNSUPPORTED = "6.1";
/**
* Conversion required and prohibited
*/
public static final String CONTENT_CONVERSION_NOT_ALLOWED = "6.2";
/**
* Conversion required, but not supported
*/
public static final String CONTENT_CONVERSION_NOT_SUPPORTED = "6.3";
/**
* Conversion with loss performed
*/
public static final String CONTENT_CONVERSION_LOSS = "6.4";
/**
* Conversion failed
*/
public static final String CONTENT_CONVERSION_FAILED = "6.5";
/**
* Security or Policy Status
*/
public static final int SECURITY = 7;
/**
* Other or undefined security status
*/
public static final String SECURITY_OTHER = "7.0";
/**
* Delivery not authorized, message refused
*/
public static final String SECURITY_AUTH = "7.1";
/**
* Mailing list expansion prohibited
*/
public static final String SECURITY_LIST_EXP = "7.2";
/**
* Security conversion required, but not possible
*/
public static final String SECURITY_CONVERSION = "7.3";
/**
* Security features not supported
*/
public static final String SECURITY_UNSUPPORTED = "7.4";
/**
* Cryptographic failure
*/
public static final String SECURITY_CRYPT_FAIL = "7.5";
/**
* Cryptographic algorithm not supported
*/
public static final String SECURITY_CRYPT_ALGO = "7.6";
/**
* Message integrity failure
*/
public static final String SECURITY_INTEGRITY = "7.7";
// get methods
public static String getStatus(int type, String detail) {
return type + "." + detail;
}
public static String getStatus(int type, int subject, int detail) {
return type + "." + subject + "." + detail;
}
}
private static final RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
// Used to generate new mail names
private static final java.util.Random random = new java.util.Random();
// regexp pattern for scaning status code from exception message
private static final Pattern statusPattern =
Pattern.compile(".*\\s*([245]\\.\\d{1,3}\\.\\d{1,3}).*\\s*");
/**
* Service does the hard work and bounces the originalMail in the format specified
by RFC3464.
*
* @param originalMail the mail to bounce
* @throws MessagingException if a problem arises formulating the redirected mail
*
* @see org.apache.mailet.Mailet#service(org.apache.mailet.Mail)
*/
public void service(Mail originalMail) throws MessagingException {
// duplicates the Mail object, to be able to modify the new mail keeping the
original untouched
Mail newMail = ((MailImpl) originalMail).duplicate(newName((MailImpl)
originalMail));
// We don't need to use the original Remote Address and Host,
// and doing so would likely cause a loop with spam detecting
// matchers.
try {
((MailImpl)
newMail).setRemoteAddr(java.net.InetAddress.getLocalHost().getHostAddress());
((MailImpl)
newMail).setRemoteHost(java.net.InetAddress.getLocalHost().getHostName());
} catch (java.net.UnknownHostException _) {
((MailImpl) newMail).setRemoteAddr("127.0.0.1");
((MailImpl) newMail).setRemoteHost("localhost");
}
MailAddress returnAddress = getExistingReturnPath(originalMail);
Collection newRecipients = new HashSet();
if (returnAddress == SpecialAddress.NULL) {
if (isDebug)
log("Processing a bounce request for a message with an empty
reverse-path. No bounce will be sent.");
if(!getPassThrough(originalMail)) {
originalMail.setState(Mail.GHOST);
}
return;
} else if (returnAddress == null) {
log("WARNING: Mail to be bounced does not contain a reverse-path.");
} else {
if (isDebug)
log("Processing a bounce request for a message with a return path
header. The bounce will be sent to " + returnAddress);
}
newRecipients.add(returnAddress);
newMail.setRecipients(newRecipients);
if (isDebug) {
MailImpl newMailImpl = (MailImpl) newMail;
log("New mail - sender: " + newMailImpl.getSender()
+ ", recipients: " +
arrayToString(newMailImpl.getRecipients().toArray())
+ ", name: " + newMailImpl.getName()
+ ", remoteHost: " + newMailImpl.getRemoteHost()
+ ", remoteAddr: " + newMailImpl.getRemoteAddr()
+ ", state: " + newMailImpl.getState()
+ ", lastUpdated: " + newMailImpl.getLastUpdated()
+ ", errorMessage: " + newMailImpl.getErrorMessage());
}
// create the bounce message
MimeMessage newMessage = new
MimeMessage(Session.getDefaultInstance(System.getProperties(), null));
MimeMultipart multipart = new MimeMultipart("report;
report-type=delivery-status");
// part 1: descripive text message
MimeBodyPart part1 = createTextMsg(originalMail);
multipart.addBodyPart(part1);
// part 2: DSN
MimeBodyPart part2 = createDSN(originalMail);
multipart.addBodyPart(part2);
// part 3: original mail (optional)
if (getAttachmentType() != NONE) {
MimeBodyPart part3 = createAttachedOriginal(originalMail);
multipart.addBodyPart(part3);
}
// stuffing all together
newMessage.setContent(multipart);
newMessage.setHeader(RFC2822Headers.CONTENT_TYPE, multipart.getContentType());
newMail.setMessage(newMessage);
//Set additional headers
setRecipients(newMail, getRecipients(originalMail), originalMail);
setTo(newMail, getTo(originalMail), originalMail);
setSubjectPrefix(newMail, getSubjectPrefix(originalMail), originalMail);
if(newMail.getMessage().getHeader(RFC2822Headers.DATE) == null) {
newMail.getMessage().setHeader(RFC2822Headers.DATE,
rfc822DateFormat.format(new Date()));
}
setReplyTo(newMail, getReplyTo(originalMail), originalMail);
setReversePath(newMail, getReversePath(originalMail), originalMail);
setSender(newMail, getSender(originalMail), originalMail);
setIsReply(newMail, isReply(originalMail), originalMail);
newMail.getMessage().saveChanges();
getMailetContext().sendMail(newMail);
// ghosting the original mail
if(!getPassThrough(originalMail)) {
originalMail.setState(Mail.GHOST);
}
}
/**
* Create a MimeBodyPart with a textual description for human readers.
*
* @param originalMail
* @return MimeBodyPart
* @throws MessagingException
*/
private MimeBodyPart createTextMsg(Mail originalMail)
throws MessagingException {
MimeBodyPart part1 = new MimeBodyPart();
StringWriter sout = new StringWriter();
PrintWriter out = new PrintWriter(sout, true);
String machine = "[unknown]";
try {
InetAddress me = InetAddress.getLocalHost();
machine = me.getHostName();
} catch(Exception e){
machine = "[address unknown]";
}
StringBuffer bounceBuffer =
new StringBuffer(128)
.append("Hi. This is the James mail server at ")
.append(machine)
.append(".");
out.println(bounceBuffer.toString());
out.println("I'm afraid I wasn't able to deliver your message to the following
addresses.");
out.println("This is a permanent error; I've given up. Sorry it didn't work
out. Below");
out.println("I include the list of recipients and the reason why I was unable
to deliver");
out.println("your message.");
out.println();
out.println("Failed recipient(s):");
for (Iterator i = originalMail.getRecipients().iterator(); i.hasNext(); ) {
out.println(i.next());
}
MessagingException ex = (MessagingException)
originalMail.getAttribute("delivery-error");
out.println();
out.println("Error message:");
out.println(getErrorMsg(ex));
out.println();
part1.setText(sout.toString());
return part1;
}
/**
* creates the DSN-bodypart for automated processing
*
* @param originalMail
* @return MimeBodyPart dsn-bodypart
* @throws MessagingException
*/
private MimeBodyPart createDSN(Mail originalMail) throws MessagingException {
MimeBodyPart dsn = new MimeBodyPart();
MimeMessage dsnMessage = new
MimeMessage(Session.getDefaultInstance(System.getProperties(), null));
StringWriter sout = new StringWriter();
PrintWriter out = new PrintWriter(sout, true);
String errorMsg = null;
String nameType = null;
////////////////////////
// per message fields //
////////////////////////
//optional: envelope-id
// TODO: Envelope-Id
// The Original-Envelope-Id is NOT the same as the Message-Id from the header.
// The Message-Id identifies the content of the message, while the
Original-Envelope-ID
// identifies the transaction in which the message is sent. (see RFC3461)
// so do NOT out.println("Original-Envelope-Id:
"+originalMail.getMessage().getMessageID());
//required: reporting MTA
// this is always us, since we do not translate non-internet-mail
// failure reports into DSNs
nameType = "dns";
try {
String myAddress = InetAddress.getLocalHost().getCanonicalHostName();
out.println("Reporting-MTA: "+nameType+"; "+myAddress);
} catch(Exception e){
// we should always know our address, so we shouldn't get here
log("WARNING: sending DSN without required Reporting-MTA Address");
}
//only for gateways to non-internet mail systems: dsn-gateway
//optional: received from
out.println("Received-From-MTA: "+nameType+"; "+originalMail.getRemoteHost());
//optional: Arrival-Date
//////////////////////////
// per recipient fields //
//////////////////////////
Iterator recipients = originalMail.getRecipients().iterator();
while (recipients.hasNext())
{
MailAddress rec = (MailAddress)recipients.next();
String addressType = "rfc822";
//required: blank line
out.println();
//optional: original recipient (see RFC3461)
//out.println("Original-Recipient: "+addressType+"; "+ ??? );
//required: final recipient
out.println("Final-Recipient: "+addressType+"; "+rec.toString());
//required: action
// alowed values: failed, delayed, delivered, relayed, expanded
// TODO: until now, we do error-bounces only
out.println("Action: failed");
//required: status
// get Exception for getting status information
// TODO: it would be nice if the SMTP-handler would set a status attribute
we can use here
MessagingException ex = (MessagingException)
originalMail.getAttribute("delivery-error");
out.println("Status: "+getStatus(ex));
//optional: remote MTA
//to which MTA were we talking while the Error occured?
//optional: diagnostic-code
String diagnosticType = null;
// this typically is the return value received during smtp
// (or other transport) communication
// and should be stored as attribute by the smtp handler
// but until now we only have error-messages.
String diagnosticCode = getErrorMsg(ex);
// Sometimes this is the smtp diagnostic code,
// but James often gives us other messages
Pattern diagPattern = Pattern.compile("^\\d{3}\\s.*$");
Matcher diagMatcher = diagPattern.matcher(diagnosticCode);
boolean smtpDiagCodeAvailable = diagMatcher.matches();
if (smtpDiagCodeAvailable){
diagnosticType = "smtp";
} else {
diagnosticType = "X-James";
}
out.println("Diagnostic-Code: "+diagnosticType+";
"+diagnosticCode);
//optional: last attempt
out.println("Last-Attempt-Date:
"+rfc822DateFormat.format(originalMail.getLastUpdated()));
//optional: retry until
//only for 'delayed' reports .. but we don't report this (at least until
now)
//optional: extension fields
}
// setting content
dsnMessage.setText(sout.toString());
dsnMessage.saveChanges();
// TODO: activation doesn't know how to handle the "message/delivery-status"
MIME-Type
//DataHandler dh = new DataHandler(dsnMessage, "message/delivery-status");
//dsn.setDataHandler(dh);
//dsn.setContent(dsnMessage, "message/delivery-status");
dsn.setContent(sout.toString(), "text/plain");
dsn.setDescription("Delivery Status Notification");
dsn.setFileName("status.dat");
return dsn;
}
/**
* Create a MimeBodyPart with the original Mail as Attachment
*
* @param originalMail
* @return MimeBodyPart
* @throws MessagingException
*/
private MimeBodyPart createAttachedOriginal(Mail originalMail)
throws MessagingException {
MimeBodyPart part = new MimeBodyPart();
MimeMessage originalMessage = originalMail.getMessage();
part.setContent(originalMessage, "message/rfc822");
if ((originalMessage.getSubject() != null) &&
(originalMessage.getSubject().trim().length() > 0)) {
part.setFileName(originalMessage.getSubject().trim());
} else {
part.setFileName("No Subject");
}
part.setDisposition("Attachment");
return part;
}
/**
* Guessing status code by the exception provided.
* This method should use the status attribute when the
* SMTP-handler somewhen provides it
*
* @param MessagingException
* @return status code
*/
private String getStatus(MessagingException me) {
if (me.getNextException() == null) {
String mess = me.getMessage();
Matcher m = statusPattern.matcher(mess);
StringBuffer sb = new StringBuffer();
if (m.matches()) {
sb.append(m.group(1));
return sb.toString();
}
// bad destination system adress
if (mess.startsWith("There are no DNS entries for the hostname"))
return DSNStatus.getStatus(DSNStatus.PERMANENT,
DSNStatus.ADDRESS_SYSTEM);
// no answer from host (4.4.1) or
// system not accepting network messages (4.3.2), lets guess ...
if (mess.equals("No mail server(s) available at this time."))
return DSNStatus.getStatus(DSNStatus.TRANSIENT,
DSNStatus.NETWORK_NO_ANSWER);
// other/unknown error
return DSNStatus.getStatus(DSNStatus.PERMANENT,
DSNStatus.UNDEFINED_STATUS);
} else {
String retVal = null;
Exception ex1 = me.getNextException();
Matcher m = statusPattern.matcher(ex1.getMessage());
StringBuffer sb = new StringBuffer();
if (m.matches()) {
sb.append(m.group(1));
return sb.toString();
} else if (ex1 instanceof SendFailedException) {
// other/undefined protocol status
// if we get an smtp returncode starting with 4
// it is an persistent transient error, else permanent
if (ex1.getMessage().startsWith("4")) {
return DSNStatus.getStatus(DSNStatus.TRANSIENT,
DSNStatus.DELIVERY_OTHER);
} else return DSNStatus.getStatus(DSNStatus.PERMANENT,
DSNStatus.DELIVERY_OTHER);
} else if (ex1 instanceof UnknownHostException) {
// bad destination system address
return DSNStatus.getStatus(DSNStatus.PERMANENT,
DSNStatus.ADDRESS_SYSTEM);
} else if (ex1 instanceof ConnectException) {
// bad connection
return DSNStatus.getStatus(DSNStatus.TRANSIENT,
DSNStatus.NETWORK_CONNECTION);
} else if (ex1 instanceof SocketException) {
// bad connection
return DSNStatus.getStatus(DSNStatus.TRANSIENT,
DSNStatus.NETWORK_CONNECTION);
} else {
// other/undefined/unknown error
return DSNStatus.getStatus(DSNStatus.PERMANENT,
DSNStatus.UNDEFINED_STATUS);
}
}
}
/**
* Utility method for getting the error message from the (nested) exception.
* @param MessagingException
* @return error message
*/
private String getErrorMsg(MessagingException me) {
if (me.getNextException() == null) {
return me.getMessage().trim();
} else {
Exception ex1 = me.getNextException();
return ex1.getMessage().trim();
}
}
/**
* Utility method for obtaining a string representation of an array of Objects.
*/
private String arrayToString(Object[] array) {
if (array == null) {
return "null";
}
StringBuffer sb = new StringBuffer(1024);
sb.append("[");
for (int i = 0; i < array.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(array[i]);
}
sb.append("]");
return sb.toString();
}
/**
* Create a unique new primary key name.
*
* @param mail the mail to use as the basis for the new mail name
* @return a new name
*/
private String newName(MailImpl mail) throws MessagingException {
String oldName = mail.getName();
// Checking if the original mail name is too long, perhaps because of a
// loop caused by a configuration error.
// it could cause a "null pointer exception" in AvalonMailRepository much
// harder to understand.
if (oldName.length() > 76) {
int count = 0;
int index = 0;
while ((index = oldName.indexOf('!', index + 1)) >= 0) {
count++;
}
// It looks like a configuration loop. It's better to stop.
if (count > 7) {
throw new MessagingException("Unable to create a new message name: too
long."
+ " Possible loop in config.xml.");
}
else {
oldName = oldName.substring(0, 76);
}
}
StringBuffer nameBuffer =
new StringBuffer(64)
.append(oldName)
.append("-!")
.append(random.nextInt(1048576));
return nameBuffer.toString();
}
public String getMailetInfo() {
return "DSNBounce Mailet";
}
/* ******************************************************************** */
/* ****************** Begin of getX and setX methods ****************** */
/* ******************************************************************** */
/** Gets the expected init parameters. */
protected String[] getAllowedInitParameters() {
String[] allowedArray = {
"debug",
"passThrough",
"attachment",
"sender",
"prefix"
};
return allowedArray;
}
/**
* @return the <CODE>attachment</CODE> init parameter, or <CODE>MESSAGE</CODE> if
missing
*/
protected int getAttachmentType() throws MessagingException {
if(getInitParameter("attachment") == null) {
return MESSAGE;
} else {
return getTypeCode(getInitParameter("attachment"));
}
}
/**
* @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
*/
protected Collection getRecipients() {
Collection newRecipients = new HashSet();
newRecipients.add(SpecialAddress.REVERSE_PATH);
return newRecipients;
}
/**
* @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
*/
protected InternetAddress[] getTo() {
InternetAddress[] apparentlyTo = new InternetAddress[1];
apparentlyTo[0] = SpecialAddress.REVERSE_PATH.toInternetAddress();
return apparentlyTo;
}
/**
* @return <CODE>SpecialAddress.NULL</CODE> (the meaning of bounce)
*/
protected MailAddress getReversePath(Mail originalMail) {
return SpecialAddress.NULL;
}
/* ******************************************************************** */
/* ******************* End of getX and setX methods ******************* */
/* ******************************************************************** */
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]