RcptCmdHandlerpublic class RcptCmdHandler extends org.apache.avalon.framework.logger.AbstractLogEnabled implements CommandHandler, org.apache.avalon.framework.configuration.Configurable
Fields Summary |
---|
private static final String | RCPTCOUNTThe keys used to store sender and recepients in the SMTPSession state | private int | maxRcpt | private int | tarpitRcptCount | private long | tarpitSleepTime |
Methods Summary |
---|
public void | configure(org.apache.avalon.framework.configuration.Configuration handlerConfiguration)
Configuration configuration = handlerConfiguration.getChild("maxRcpt",false);
if(configuration != null) {
maxRcpt = configuration.getValueAsInteger();
}
Configuration configTarpitRcptCount = handlerConfiguration.getChild("tarpitRcptCount",false);
if(configTarpitRcptCount != null) {
tarpitRcptCount = configTarpitRcptCount.getValueAsInteger();
}
Configuration configTarpitSleepTime = handlerConfiguration.getChild("tarpitSleepTime",false);
if(configTarpitSleepTime != null) {
tarpitSleepTime = configTarpitSleepTime.getValueAsLong();
}
| private void | doRCPT(SMTPSession session, java.lang.String argument)Handler method called upon receipt of a RCPT command.
Reads recipient. Does some connection validation.
String responseString = null;
StringBuffer responseBuffer = session.getResponseBuffer();
boolean maxRcptReached = false;
boolean useTarpit = false;
String recipient = null;
if ((argument != null) && (argument.indexOf(":") > 0)) {
int colonIndex = argument.indexOf(":");
recipient = argument.substring(colonIndex + 1);
argument = argument.substring(0, colonIndex);
}
if (!session.getState().containsKey(SMTPSession.SENDER)) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need MAIL before RCPT";
session.writeResponse(responseString);
} else if (argument == null || !argument.toUpperCase(Locale.US).equals("TO")
|| recipient == null) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Usage: RCPT TO:<recipient>";
session.writeResponse(responseString);
} else {
Collection rcptColl = (Collection) session.getState().get(SMTPSession.RCPT_LIST);
if (rcptColl == null) {
rcptColl = new ArrayList();
}
recipient = recipient.trim();
int lastChar = recipient.lastIndexOf('>");
// Check to see if any options are present and, if so, whether they are correctly formatted
// (separated from the closing angle bracket by a ' ').
String rcptOptionString = null;
if ((lastChar > 0) && (recipient.length() > lastChar + 2) && (recipient.charAt(lastChar + 1) == ' ")) {
rcptOptionString = recipient.substring(lastChar + 2);
// Remove the options from the recipient
recipient = recipient.substring(0, lastChar + 1);
}
if (!recipient.startsWith("<") || !recipient.endsWith(">")) {
responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Syntax error in parameters or arguments";
session.writeResponse(responseString);
if (getLogger().isErrorEnabled()) {
StringBuffer errorBuffer =
new StringBuffer(192)
.append("Error parsing recipient address: ")
.append("Address did not start and end with < >")
.append(getContext(session,null,recipient));
getLogger().error(errorBuffer.toString());
}
return;
}
MailAddress recipientAddress = null;
//Remove < and >
recipient = recipient.substring(1, recipient.length() - 1);
if (recipient.indexOf("@") < 0) {
recipient = recipient + "@localhost";
}
try {
recipientAddress = new MailAddress(recipient);
} catch (Exception pe) {
/*
* from RFC2822;
* 553 Requested action not taken: mailbox name not allowed
* (e.g., mailbox syntax incorrect)
*/
responseString = "553 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX)+" Syntax error in recipient address";
session.writeResponse(responseString);
if (getLogger().isErrorEnabled()) {
StringBuffer errorBuffer =
new StringBuffer(192)
.append("Error parsing recipient address: ")
.append(getContext(session,recipientAddress,recipient))
.append(pe.getMessage());
getLogger().error(errorBuffer.toString());
}
return;
}
if (session.isBlockListed() && // was found in the RBL
!(session.isRelayingAllowed() || (session.isAuthRequired() && session.getUser() != null)) && // Not (either an authorized IP or (SMTP AUTH is enabled and not authenticated))
!(recipientAddress.getUser().equalsIgnoreCase("postmaster") || recipientAddress.getUser().equalsIgnoreCase("abuse"))) {
// trying to send e-mail to other than postmaster or abuse
responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Rejected: unauthenticated e-mail from " + session.getRemoteIPAddress() + " is restricted. Contact the postmaster for details.";
session.writeResponse(responseString);
return;
}
if (session.isAuthRequired() && !session.isRelayingAllowed()) {
// Make sure the mail is being sent locally if not
// authenticated else reject.
if (session.getUser() == null) {
String toDomain = recipientAddress.getHost();
if (!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Authentication Required";
session.writeResponse(responseString);
StringBuffer sb = new StringBuffer(128);
sb.append("Rejected message - authentication is required for mail request");
sb.append(getContext(session,recipientAddress,recipient));
getLogger().error(sb.toString());
return;
}
} else {
// Identity verification checking
if (session.getConfigurationData().isVerifyIdentity()) {
String authUser = (session.getUser()).toLowerCase(Locale.US);
MailAddress senderAddress = (MailAddress) session.getState().get(SMTPSession.SENDER);
if ((senderAddress == null) || (!authUser.equals(senderAddress.getUser())) ||
(!session.getConfigurationData().getMailServer().isLocalServer(senderAddress.getHost()))) {
responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Incorrect Authentication for Specified Email Address";
session.writeResponse(responseString);
if (getLogger().isErrorEnabled()) {
StringBuffer errorBuffer =
new StringBuffer(128)
.append("User ")
.append(authUser)
.append(" authenticated, however tried sending email as ")
.append(senderAddress)
.append(getContext(session,recipientAddress,recipient));
getLogger().error(errorBuffer.toString());
}
return;
}
}
}
} else if (!session.isRelayingAllowed()) {
String toDomain = recipientAddress.getHost();
if (!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
responseString = "550 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Requested action not taken: relaying denied";
session.writeResponse(responseString);
StringBuffer errorBuffer = new StringBuffer(128)
.append("Rejected message - ")
.append(session.getRemoteIPAddress())
.append(" not authorized to relay to ")
.append(toDomain)
.append(getContext(session,recipientAddress,recipient));
getLogger().error(errorBuffer.toString());
return;
}
}
if (rcptOptionString != null) {
StringTokenizer optionTokenizer = new StringTokenizer(rcptOptionString, " ");
while (optionTokenizer.hasMoreElements()) {
String rcptOption = optionTokenizer.nextToken();
int equalIndex = rcptOption.indexOf('=");
String rcptOptionName = rcptOption;
String rcptOptionValue = "";
if (equalIndex > 0) {
rcptOptionName = rcptOption.substring(0, equalIndex).toUpperCase(Locale.US);
rcptOptionValue = rcptOption.substring(equalIndex + 1);
}
// Unexpected option attached to the RCPT command
if (getLogger().isDebugEnabled()) {
StringBuffer debugBuffer =
new StringBuffer(128)
.append("RCPT command had unrecognized/unexpected option ")
.append(rcptOptionName)
.append(" with value ")
.append(rcptOptionValue)
.append(getContext(session,recipientAddress,recipient));
getLogger().debug(debugBuffer.toString());
}
}
optionTokenizer = null;
}
// check if we should check for max recipients
if (maxRcpt > 0) {
int rcptCount = 0;
// check if the key exists
rcptCount = getRcptCount(session);
rcptCount++;
// check if the max recipients has reached
if (rcptCount > maxRcpt) {
maxRcptReached = true;
responseString = "452 "+DSNStatus.getStatus(DSNStatus.NETWORK,DSNStatus.DELIVERY_TOO_MANY_REC)+" Requested action not taken: max recipients reached";
session.writeResponse(responseString);
getLogger().error(responseString);
}
// put the recipient cound in session hashtable
session.getState().put(RCPTCOUNT,Integer.toString(rcptCount));
}
// check if we should use tarpit
if (tarpitRcptCount > 0) {
int rcptCount = 0;
rcptCount = getRcptCount(session);
rcptCount++;
if (rcptCount > tarpitRcptCount) {
useTarpit = true;
}
// put the recipient cound in session hashtable
session.getState().put(RCPTCOUNT,Integer.toString(rcptCount));
}
if (maxRcptReached == false) {
rcptColl.add(recipientAddress);
session.getState().put(SMTPSession.RCPT_LIST, rcptColl);
responseBuffer.append("250 "+DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.ADDRESS_VALID)+" Recipient <")
.append(recipient)
.append("> OK");
responseString = session.clearResponseBuffer();
if (useTarpit == true) {
try {
sleep(tarpitSleepTime);
} catch (InterruptedException e) { }
}
session.writeResponse(responseString);
}
}
| private java.lang.String | getContext(SMTPSession session, org.apache.mailet.MailAddress recipientAddress, java.lang.String recipient)
StringBuffer sb = new StringBuffer(128);
if(null!=recipientAddress) {
sb.append(" [to:" + (recipientAddress).toInternetAddress().getAddress() + "]");
} else if(null!=recipient) {
sb.append(" [to:" + recipient + "]");
}
if (null!=session.getState().get(SMTPSession.SENDER)) {
sb.append(" [from:" + ((MailAddress)session.getState().get(SMTPSession.SENDER)).toInternetAddress().getAddress() + "]");
}
return sb.toString();
| private int | getRcptCount(SMTPSession session)
int startCount = 0;
// check if the key exists
if (session.getState().get(RCPTCOUNT) != null) {
Integer rcptCountInteger = Integer.valueOf(session.getState().get(RCPTCOUNT).toString());
return rcptCountInteger.intValue();
} else {
return startCount;
}
| public void | onCommand(SMTPSession session)
doRCPT(session, session.getCommandArgument());
| public void | sleep(float timeInMillis)
Thread.sleep( (long) timeInMillis );
|
|