DataCmdHandlerpublic class DataCmdHandler extends org.apache.avalon.framework.logger.AbstractLogEnabled implements CommandHandler
Fields Summary |
---|
private static final String | SOFTWARE_TYPE | private static final org.apache.mailet.dates.RFC822DateFormat | rfc822DateFormatStatic RFC822DateFormat used to generate date headers | private static final String | SMTP_AUTH_USER_ATTRIBUTE_NAMEThe mail attribute holding the SMTP AUTH user name, if any. | private static final char[] | SMTPTerminatorThe character array that indicates termination of an SMTP connection |
Methods Summary |
---|
private void | doDATA(SMTPSession session, java.lang.String argument)Handler method called upon receipt of a DATA command.
Reads in message data, creates header, and delivers to
mail server service for delivery.
String responseString = null;
if ((argument != null) && (argument.length() > 0)) {
responseString = "500 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Unexpected argument provided with DATA command";
session.writeResponse(responseString);
}
if (!session.getState().containsKey(SMTPSession.SENDER)) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" No sender specified";
session.writeResponse(responseString);
} else if (!session.getState().containsKey(SMTPSession.RCPT_LIST)) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" No recipients specified";
session.writeResponse(responseString);
} else {
responseString = "354 Ok Send data ending with <CRLF>.<CRLF>";
session.writeResponse(responseString);
InputStream msgIn = new CharTerminatedInputStream(session.getInputStream(), SMTPTerminator);
try {
msgIn = new BytesReadResetInputStream(msgIn,
session.getWatchdog(),
session.getConfigurationData().getResetLength());
// if the message size limit has been set, we'll
// wrap msgIn with a SizeLimitedInputStream
long maxMessageSize = session.getConfigurationData().getMaxMessageSize();
if (maxMessageSize > 0) {
if (getLogger().isDebugEnabled()) {
StringBuffer logBuffer =
new StringBuffer(128)
.append("Using SizeLimitedInputStream ")
.append(" with max message size: ")
.append(maxMessageSize);
getLogger().debug(logBuffer.toString());
}
msgIn = new SizeLimitedInputStream(msgIn, maxMessageSize);
}
// Removes the dot stuffing
msgIn = new DotStuffingInputStream(msgIn);
// Parse out the message headers
MailHeaders headers = new MailHeaders(msgIn);
headers = processMailHeaders(session, headers);
processMail(session, headers, msgIn);
headers = null;
} catch (MessagingException me) {
// Grab any exception attached to this one.
Exception e = me.getNextException();
// If there was an attached exception, and it's a
// MessageSizeException
if (e != null && e instanceof MessageSizeException) {
// Add an item to the state to suppress
// logging of extra lines of data
// that are sent after the size limit has
// been hit.
session.getState().put(SMTPSession.MESG_FAILED, Boolean.TRUE);
// then let the client know that the size
// limit has been hit.
responseString = "552 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SYSTEM_MSG_TOO_BIG)+" Error processing message: "
+ e.getMessage();
StringBuffer errorBuffer =
new StringBuffer(256)
.append("Rejected message from ")
.append(session.getState().get(SMTPSession.SENDER).toString())
.append(" from host ")
.append(session.getRemoteHost())
.append(" (")
.append(session.getRemoteIPAddress())
.append(") exceeding system maximum message size of ")
.append(session.getConfigurationData().getMaxMessageSize());
getLogger().error(errorBuffer.toString());
} else {
responseString = "451 "+DSNStatus.getStatus(DSNStatus.TRANSIENT,DSNStatus.UNDEFINED_STATUS)+" Error processing message: "
+ me.getMessage();
getLogger().error("Unknown error occurred while processing DATA.", me);
}
session.writeResponse(responseString);
return;
} finally {
if (msgIn != null) {
try {
msgIn.close();
} catch (Exception e) {
// Ignore close exception
}
msgIn = null;
}
}
}
| public void | onCommand(SMTPSession session)process DATA command
doDATA(session, session.getCommandArgument());
| private void | processMail(SMTPSession session, org.apache.james.core.MailHeaders headers, java.io.InputStream msgIn)Processes the mail message coming in off the wire. Reads the
content and delivers to the spool.
ByteArrayInputStream headersIn = null;
MailImpl mail = null;
List recipientCollection = null;
try {
headersIn = new ByteArrayInputStream(headers.toByteArray());
recipientCollection = (List) session.getState().get(SMTPSession.RCPT_LIST);
mail =
new MailImpl(session.getConfigurationData().getMailServer().getId(),
(MailAddress) session.getState().get(SMTPSession.SENDER),
recipientCollection,
new SequenceInputStream(new SequenceInputStream(headersIn, msgIn),
new ReaderInputStream(new StringReader("\r\n"))));
// Call mail.getSize() to force the message to be
// loaded. Need to do this to enforce the size limit
if (session.getConfigurationData().getMaxMessageSize() > 0) {
mail.getMessageSize();
}
mail.setRemoteHost(session.getRemoteHost());
mail.setRemoteAddr(session.getRemoteIPAddress());
if (session.getUser() != null) {
mail.setAttribute(SMTP_AUTH_USER_ATTRIBUTE_NAME, session.getUser());
}
session.setMail(mail);
} catch (MessagingException me) {
// if we get here, it means that we received a
// MessagingException, which would happen BEFORE we call
// session.setMail, so the mail object is still strictly
// local to us, and we really should clean it up before
// re-throwing the MessagingException for our call chain
// to process.
//
// So why has this worked at all so far? Initial
// conjecture is that it has depended upon finalize to
// call dispose. Not in the MailImpl, which doesn't have
// one, but even further down in the MimeMessageInputStreamSource.
if (mail != null) {
mail.dispose();
}
throw me;
} finally {
if (recipientCollection != null) {
recipientCollection.clear();
}
recipientCollection = null;
if (headersIn != null) {
try {
headersIn.close();
} catch (IOException ioe) {
// Ignore exception on close.
}
}
headersIn = null;
}
| private org.apache.james.core.MailHeaders | processMailHeaders(SMTPSession session, org.apache.james.core.MailHeaders headers)
// If headers do not contains minimum REQUIRED headers fields,
// add them
if (!headers.isSet(RFC2822Headers.DATE)) {
headers.setHeader(RFC2822Headers.DATE, rfc822DateFormat.format(new Date()));
}
if (!headers.isSet(RFC2822Headers.FROM) && session.getState().get(SMTPSession.SENDER) != null) {
headers.setHeader(RFC2822Headers.FROM, session.getState().get(SMTPSession.SENDER).toString());
}
// RFC 2821 says that we cannot examine the message to see if
// Return-Path headers are present. If there is one, our
// Received: header may precede it, but the Return-Path header
// should be removed when making final delivery.
// headers.removeHeader(RFC2822Headers.RETURN_PATH);
StringBuffer headerLineBuffer = new StringBuffer(512);
// We will rebuild the header object to put our Received header at the top
Enumeration headerLines = headers.getAllHeaderLines();
MailHeaders newHeaders = new MailHeaders();
// Put our Received header first
headerLineBuffer.append(RFC2822Headers.RECEIVED + ": from ")
.append(session.getRemoteHost())
.append(" ([")
.append(session.getRemoteIPAddress())
.append("])");
newHeaders.addHeaderLine(headerLineBuffer.toString());
headerLineBuffer.delete(0, headerLineBuffer.length());
headerLineBuffer.append(" by ")
.append(session.getConfigurationData().getHelloName())
.append(" (")
.append(SOFTWARE_TYPE)
.append(") with SMTP ID ")
.append(session.getSessionID());
if (((Collection) session.getState().get(SMTPSession.RCPT_LIST)).size() == 1) {
// Only indicate a recipient if they're the only recipient
// (prevents email address harvesting and large headers in
// bulk email)
newHeaders.addHeaderLine(headerLineBuffer.toString());
headerLineBuffer.delete(0, headerLineBuffer.length());
headerLineBuffer.append(" for <")
.append(((List) session.getState().get(SMTPSession.RCPT_LIST)).get(0).toString())
.append(">;");
newHeaders.addHeaderLine(headerLineBuffer.toString());
headerLineBuffer.delete(0, headerLineBuffer.length());
} else {
// Put the ; on the end of the 'by' line
headerLineBuffer.append(";");
newHeaders.addHeaderLine(headerLineBuffer.toString());
headerLineBuffer.delete(0, headerLineBuffer.length());
}
headerLineBuffer = null;
newHeaders.addHeaderLine(" " + rfc822DateFormat.format(new Date()));
// Add all the original message headers back in next
while (headerLines.hasMoreElements()) {
newHeaders.addHeaderLine((String) headerLines.nextElement());
}
return newHeaders;
|
|