Hi,
James doesn't allow missing bracket into the "mailto" and "rcpt to",
which is conforme to the RFC.
However, most of the smtp server allow that. When some simple client
does not follow the RFC. It is the case of the Oracle UTL_MAIL (pl-sql
pkg) which is quite buggy.
Anyway, I got the problem, so I added an allowMissingBracket parameter
to MailCmdHandler and RcptCmdHandler.
I'll be happy to send you a patch if you would like include it into the
James distribution. In that case do you prefere that I add the parameter
(like I did) or do you prefere that I create a new class like
NotStrictMailCmdHandler...?
Anyway, I send were the code that I did.
Let me know if you would like anything more in order to make it part of
your distribution.
Regards,
Laurent Rouvet
/***********************************************************************
* Copyright (c) 1999-2006 The Apache Software Foundation. *
* All rights reserved. *
* ------------------------------------------------------------------- *
* Licensed under the Apache License, Version 2.0 (the "License"); you *
* may not use this file except in compliance with the License. You *
* may obtain a copy of the License at: *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
* implied. See the License for the specific language governing *
* permissions and limitations under the License. *
***********************************************************************/
package org.apache.james.smtpserver;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.james.services.DNSServer;
import org.apache.james.util.mail.dsn.DSNStatus;
import org.apache.mailet.MailAddress;
import java.util.Collection;
import java.util.Locale;
import java.util.StringTokenizer;
/**
* Handles MAIL command
*/
public class MailCmdHandler
extends AbstractLogEnabled
implements CommandHandler,Configurable, Serviceable {
private final static String MAIL_OPTION_SIZE = "SIZE";
private final static String MESG_SIZE = "MESG_SIZE"; // The size of the
message
private boolean checkValidSenderDomain = false;
private boolean checkAuthClients = false;
private boolean allowMissingBracket = false;
private DNSServer dnsServer = null;
/**
* @see
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration handlerConfiguration) throws
ConfigurationException {
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();
}
configRelay =
handlerConfiguration.getChild("allowMissingBracket",false);
if(configRelay != null) {
allowMissingBracket = configRelay.getValueAsBoolean();
}
}
/**
* @see
org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
*/
public void service(ServiceManager serviceMan) throws ServiceException {
dnsServer = (DNSServer) serviceMan.lookup(DNSServer.ROLE);
}
/**
* handles MAIL command
*
* @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
*/
public void onCommand(SMTPSession session) {
doMAIL(session, session.getCommandArgument());
}
/**
* Handler method called upon receipt of a MAIL command.
* Sets up handler to deliver mail as the stated sender.
*
* @param session SMTP session object
* @param argument the argument passed in with the command by the SMTP
client
*/
private void doMAIL(SMTPSession session, String argument) {
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());
}
}
}
}
{
int start = 0;
int end = sender.length();
if (allowMissingBracket) {
if (sender.startsWith("<")) start++;
if (sender.endsWith(">")) end--;
}
else {
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;
}
start++;
end--;
}
//Remove < and >
sender = sender.substring(start, end);
}
MailAddress senderAddress = null;
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);
}
}
}
/**
* Handles the SIZE MAIL option.
*
* @param session SMTP session object
* @param mailOptionValue the option string passed in with the SIZE option
* @param tempSender the sender specified in this mail command (for logging
purpose)
* @return true if further options should be processed, false otherwise
*/
private boolean doMailSize(SMTPSession session, String mailOptionValue,
String tempSender) {
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;
}
}
/***********************************************************************
* Copyright (c) 1999-2006 The Apache Software Foundation. *
* All rights reserved. *
* ------------------------------------------------------------------- *
* Licensed under the Apache License, Version 2.0 (the "License"); you *
* may not use this file except in compliance with the License. You *
* may obtain a copy of the License at: *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
* implied. See the License for the specific language governing *
* permissions and limitations under the License. *
***********************************************************************/
package org.apache.james.smtpserver;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.james.util.mail.dsn.DSNStatus;
import org.apache.mailet.MailAddress;
import java.util.Collection;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Locale;
/**
* Handles RCPT command
*/
public class RcptCmdHandler
extends AbstractLogEnabled
implements CommandHandler,Configurable {
/**
* The keys used to store sender and recepients in the SMTPSession state
*/
private final static String RCPTCOUNT = "RCPT_COUNT";
private int maxRcpt = 0;
private int tarpitRcptCount = 0;
private long tarpitSleepTime = 5000;
private boolean allowMissingBracket = false;
/**
* @see
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration handlerConfiguration) throws
ConfigurationException {
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();
}
Configuration configRelay =
handlerConfiguration.getChild("allowMissingBracket",false);
if(configRelay != null) {
allowMissingBracket = configRelay.getValueAsBoolean();
}
}
/*
* handles RCPT command
*
* @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
**/
public void onCommand(SMTPSession session) {
doRCPT(session, session.getCommandArgument());
}
/**
* Handler method called upon receipt of a RCPT command.
* Reads recipient. Does some connection validation.
*
*
* @param session SMTP session object
* @param argument the argument passed in with the command by the SMTP
client
*/
private void doRCPT(SMTPSession session, String argument) {
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);
}
{
int start = 0;
int end = recipient.length();
if (allowMissingBracket) {
if (recipient.startsWith("<")) start++;
if (recipient.endsWith(">")) end--;
}
else {
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;
}
start++;
end--;
}
//Remove < and >
recipient = recipient.substring(start, end);
}
MailAddress recipientAddress = null;
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 String getContext(SMTPSession session, MailAddress
recipientAddress, 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 sleep(float timeInMillis) throws InterruptedException {
Thread.sleep( (long) timeInMillis );
}
}
<!-- The configuration handler chain -->
<!-- Please note that this is EXPERIMENTAL and will be changed in future -->
<!-- releases -->
<handlerchain>
<!-- The connect handler configuration -->
<!-- STOP - before you uncomment out the DNS RBL handler,
please take a moment to review each block list. We
have included some that various JAMES committers use,
but you must decide which, if any, are appropriate
for your environment. The mail servers hosting
@apache.org mailing lists, for example, use a
slightly different list than we have included below.
And it is likely that most JAMES committes also have
slightly different sets of lists. The SpamAssassin
user's list would be one good place to discuss the
measured quality of various block lists.
NOTA BENE: the domain names, below, are terminated
with '.' to ensure that they are absolute names in
DNS lookups. Under some circumstances, names that
are not explicitly absolute could be treated as
relative names, leading to incorrect results. This
has been observed on *nix and MS-Windows platforms
by users of multiple mail servers, and is not JAMES
specific. If you are unsure what this means for you,
please speak with your local system/network admins.
-->
<!--
<handler class="org.apache.james.smtpserver.DNSRBLHandler">
<rblservers>
<whitelist> query.bondedsender.org. </whitelist>
<blacklist> sbl-xbl.spamhaus.org. </blacklist>
<blacklist> dul.dnsbl.sorbs.net. </blacklist>
<blacklist> list.dsbl.org. </blacklist>
<blacklist> relays.ordb.org. </blacklist>
</rblservers>
</handler>
-->
<!-- The command handler configuration -->
<handler command="HELO" class="org.apache.james.smtpserver.HeloCmdHandler">
<!-- If is set to true helo is only accepted if it can be resolved -->
<!-- WARNING: This check will reject on invalid HELO even if the user is authenticated-->
<!--
<checkResolvableHelo> false </checkResolvableHelo>
-->
<!-- If is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
<checkAuthNetworks> false </checkAuthNetworks>
-->
</handler>
<handler command="EHLO" class="org.apache.james.smtpserver.EhloCmdHandler">
<!-- If is set to true EHLO is only accepted if it can be resolved -->
<!-- WARNING: This check will reject on invalid EHLO even if the user is authenticated-->
<!--
<checkResolvableEhlo> false </checkResolvableEhlo>
-->
<!-- If is set to true sender domain will be checked also for clients that -->
<!-- are allowed to relay. Default is false. -->
<!--
<checkAuthNetworks> false </checkAuthNetworks>
-->
</handler>
<handler command="AUTH" class="org.apache.james.smtpserver.AuthCmdHandler"></handler>
<handler command="VRFY" class="org.apache.james.smtpserver.VrfyCmdHandler"></handler>
<handler command="EXPN" class="org.apache.james.smtpserver.ExpnCmdHandler"></handler>
<handler command="MAIL" class="org.apache.james.smtpserver.MailCmdHandler">
<!-- If is set to true mail is only accepted if the sender contains -->
<!-- a resolvable domain having a valid MX Record or A Record associated! -->
<!--
<checkValidSenderDomain> false </checkValidSenderDomain>
-->
<!-- If is set to true sender domain from clients that are allowed to -->
<!-- relay will be checked, too. Default is false. -->
<!--
<checkAuthClients> false </checkAuthClients>
-->
<!-- If is set to true the address without bracket "<" ">" is allow instead of answering an error 501. -->
<!-- The SMTP RFC says that the addresses MUST be enclosed in "<" and ">". -->
<!-- So the sending client is not SMTP compliant without bracket. -->
<!-- However, that error is quite common and a lot of SMTP server tolerate it. -->
<!-- Default is false (force to be SMTP RFC compliant) -->
<!--
<allowMissingBracket> true </allowMissingBracket>
-->
</handler>
<handler command="RCPT" class="org.apache.james.smtpserver.RcptCmdHandler">
<!-- If is set to a bigger value as 0 you can limit the maximal recipients -->
<!-- per email. Default is set to 0. -->
<!--
<maxRcpt> 0 </maxRcpt>
-->
<!-- If is set to a bigger value as 0 you can set the recipients after which -->
<!-- tarpitting get activated. -->
<!-- Tarpitting is a method to insert a small sleep after each rcpt. For more -->
<!-- infos read this: http://www.palomine.net/qmail/tarpit.html . -->
<!-- Default is set to 0 (disabled). -->
<!--
<tarpitRcptCount> 0 </tarpitRcptCount>
-->
<!-- See timeout in milliseconds to insert after the rcpt. Only is used if -->
<!-- tarpitting is activated. -->
<!--
<tarpitSleepTime> 5000 </tarpitSleepTime>
-->
<!-- If is set to true the address without bracket "<" ">" is allow instead of answering an error 501. -->
<!-- The SMTP RFC says that the addresses MUST be enclosed in "<" and ">". -->
<!-- So the sending client is not SMTP compliant without bracket. -->
<!-- However, that error is quite common and a lot of SMTP server tolerate it. -->
<!-- Default is false (force to be SMTP RFC compliant) -->
<!--
<allowMissingBracket> true </allowMissingBracket>
-->
</handler>
<handler command="DATA" class="org.apache.james.smtpserver.DataCmdHandler"></handler>
<handler command="RSET" class="org.apache.james.smtpserver.RsetCmdHandler"></handler>
<handler command="HELP" class="org.apache.james.smtpserver.HelpCmdHandler"></handler>
<handler command="QUIT" class="org.apache.james.smtpserver.QuitCmdHandler"></handler>
<!-- The message handler configuration -->
<!--
<handler class="org.apache.james.smtpserver.SetMimeHeaderHandler">
<headername>SPF-test</headername>
<headervalue>passed</headervalue>
</handler>
-->
<!-- The default message receiving handler -->
<!-- The default behaviour is to put the message in the root processor of -->
<!-- the spooler -->
<handler class="org.apache.james.smtpserver.SendMailHandler">
</handler>
</handlerchain>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]