MailCmdHandlerpublic class MailCmdHandler extends org.apache.avalon.framework.logger.AbstractLogEnabled implements org.apache.avalon.framework.service.Serviceable, CommandHandler, org.apache.avalon.framework.configuration.Configurable
Fields Summary |
---|
private static final String | MAIL_OPTION_SIZE | private static final String | MESG_SIZE | private boolean | checkValidSenderDomain | private boolean | checkAuthClients | private org.apache.james.services.DNSServer | dnsServer |
Methods Summary |
---|
public void | configure(org.apache.avalon.framework.configuration.Configuration handlerConfiguration)
Configuration configuration = handlerConfiguration.getChild("checkValidSenderDomain",false);
if(configuration != null) {
checkValidSenderDomain = configuration.getValueAsBoolean();
if (checkValidSenderDomain && dnsServer == null) {
throw new ConfigurationException("checkValidSenderDomain enabled but no DNSServer service provided to SMTPServer");
}
}
Configuration configRelay = handlerConfiguration.getChild("checkAuthClients",false);
if(configRelay != null) {
checkAuthClients = configRelay.getValueAsBoolean();
}
| private void | doMAIL(SMTPSession session, java.lang.String argument)Handler method called upon receipt of a MAIL command.
Sets up handler to deliver mail as the stated sender.
String responseString = null;
StringBuffer responseBuffer = session.getResponseBuffer();
String sender = null;
boolean badSenderDomain = false;
if ((argument != null) && (argument.indexOf(":") > 0)) {
int colonIndex = argument.indexOf(":");
sender = argument.substring(colonIndex + 1);
argument = argument.substring(0, colonIndex);
}
if (session.getState().containsKey(SMTPSession.SENDER)) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Sender already specified";
session.writeResponse(responseString);
} else if (!session.getState().containsKey(SMTPSession.CURRENT_HELO_MODE) && session.useHeloEhloEnforcement()) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need HELO or EHLO before MAIL";
session.writeResponse(responseString);
} else if (argument == null || !argument.toUpperCase(Locale.US).equals("FROM")
|| sender == null) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Usage: MAIL FROM:<sender>";
session.writeResponse(responseString);
} else {
sender = sender.trim();
// the next gt after the first lt ... AUTH may add more <>
int lastChar = sender.indexOf('>", sender.indexOf('<"));
// Check to see if any options are present and, if so, whether they are correctly formatted
// (separated from the closing angle bracket by a ' ').
if ((lastChar > 0) && (sender.length() > lastChar + 2) && (sender.charAt(lastChar + 1) == ' ")) {
String mailOptionString = sender.substring(lastChar + 2);
// Remove the options from the sender
sender = sender.substring(0, lastChar + 1);
StringTokenizer optionTokenizer = new StringTokenizer(mailOptionString, " ");
while (optionTokenizer.hasMoreElements()) {
String mailOption = optionTokenizer.nextToken();
int equalIndex = mailOption.indexOf('=");
String mailOptionName = mailOption;
String mailOptionValue = "";
if (equalIndex > 0) {
mailOptionName = mailOption.substring(0, equalIndex).toUpperCase(Locale.US);
mailOptionValue = mailOption.substring(equalIndex + 1);
}
// Handle the SIZE extension keyword
if (mailOptionName.startsWith(MAIL_OPTION_SIZE)) {
if (!(doMailSize(session, mailOptionValue, sender))) {
return;
}
} else {
// Unexpected option attached to the Mail command
if (getLogger().isDebugEnabled()) {
StringBuffer debugBuffer =
new StringBuffer(128)
.append("MAIL command had unrecognized/unexpected option ")
.append(mailOptionName)
.append(" with value ")
.append(mailOptionValue);
getLogger().debug(debugBuffer.toString());
}
}
}
}
if (!sender.startsWith("<") || !sender.endsWith(">")) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX_SENDER)+" Syntax error in MAIL command";
session.writeResponse(responseString);
if (getLogger().isErrorEnabled()) {
StringBuffer errorBuffer =
new StringBuffer(128)
.append("Error parsing sender address: ")
.append(sender)
.append(": did not start and end with < >");
getLogger().error(errorBuffer.toString());
}
return;
}
MailAddress senderAddress = null;
//Remove < and >
sender = sender.substring(1, sender.length() - 1);
if (sender.length() == 0) {
//This is the <> case. Let senderAddress == null
} else {
if (sender.indexOf("@") < 0) {
sender = sender + "@localhost";
}
try {
senderAddress = new MailAddress(sender);
} catch (Exception pe) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX_SENDER)+" Syntax error in sender address";
session.writeResponse(responseString);
if (getLogger().isErrorEnabled()) {
StringBuffer errorBuffer =
new StringBuffer(256)
.append("Error parsing sender address: ")
.append(sender)
.append(": ")
.append(pe.getMessage());
getLogger().error(errorBuffer.toString());
}
return;
}
}
// check only if senderAddress is not null
if (checkValidSenderDomain == true && senderAddress != null) {
/**
* don't check if the ip address is allowed to relay. Only check if it is set in the config.
*/
if (checkAuthClients || !session.isRelayingAllowed()) {
// Maybe we should build a static method in org.apache.james.dnsserver.DNSServer ?
Collection records;
records = dnsServer.findMXRecords(senderAddress.getHost());
if (records == null || records.size() == 0) {
badSenderDomain = true;
}
// try to resolv the provided domain in the senderaddress. If it can not resolved do not accept it.
if (badSenderDomain) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX_SENDER)+ " sender " + senderAddress + " contains a domain with no valid MX records";
session.writeResponse(responseString);
getLogger().info(responseString);
}
}
}
if (!badSenderDomain) {
session.getState().put(SMTPSession.SENDER, senderAddress);
responseBuffer.append("250 "+DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.ADDRESS_OTHER)+" Sender <")
.append(sender)
.append("> OK");
responseString = session.clearResponseBuffer();
session.writeResponse(responseString);
}
}
| private boolean | doMailSize(SMTPSession session, java.lang.String mailOptionValue, java.lang.String tempSender)Handles the SIZE MAIL option.
int size = 0;
try {
size = Integer.parseInt(mailOptionValue);
} catch (NumberFormatException pe) {
// This is a malformed option value. We return an error
String responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Syntactically incorrect value for SIZE parameter";
session.writeResponse(responseString);
getLogger().error("Rejected syntactically incorrect value for SIZE parameter.");
return false;
}
if (getLogger().isDebugEnabled()) {
StringBuffer debugBuffer =
new StringBuffer(128)
.append("MAIL command option SIZE received with value ")
.append(size)
.append(".");
getLogger().debug(debugBuffer.toString());
}
long maxMessageSize = session.getConfigurationData().getMaxMessageSize();
if ((maxMessageSize > 0) && (size > maxMessageSize)) {
// Let the client know that the size limit has been hit.
String responseString = "552 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SYSTEM_MSG_TOO_BIG)+" Message size exceeds fixed maximum message size";
session.writeResponse(responseString);
StringBuffer errorBuffer =
new StringBuffer(256)
.append("Rejected message from ")
.append(tempSender != null ? tempSender : null)
.append(" from host ")
.append(session.getRemoteHost())
.append(" (")
.append(session.getRemoteIPAddress())
.append(") of size ")
.append(size)
.append(" exceeding system maximum message size of ")
.append(maxMessageSize)
.append("based on SIZE option.");
getLogger().error(errorBuffer.toString());
return false;
} else {
// put the message size in the message state so it can be used
// later to restrict messages for user quotas, etc.
session.getState().put(MESG_SIZE, new Integer(size));
}
return true;
| public void | onCommand(SMTPSession session)handles MAIL command
doMAIL(session, session.getCommandArgument());
| public void | service(org.apache.avalon.framework.service.ServiceManager serviceMan)
dnsServer = (DNSServer) serviceMan.lookup(DNSServer.ROLE);
|
|