001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.smtpserver;
019:
020: import org.apache.avalon.framework.configuration.Configurable;
021: import org.apache.avalon.framework.configuration.Configuration;
022: import org.apache.avalon.framework.configuration.ConfigurationException;
023: import org.apache.avalon.framework.logger.AbstractLogEnabled;
024: import org.apache.james.util.mail.dsn.DSNStatus;
025:
026: import java.net.UnknownHostException;
027: import java.util.ArrayList;
028:
029: /**
030: * Handles EHLO command
031: */
032: public class EhloCmdHandler extends AbstractLogEnabled implements
033: CommandHandler, Configurable {
034:
035: /**
036: * The name of the command handled by the command handler
037: */
038: private final static String COMMAND_NAME = "EHLO";
039:
040: /**
041: * set checkResolvableEhlo to false as default value
042: */
043: private boolean checkResolvableEhlo = false;
044:
045: private boolean checkAuthNetworks = false;
046:
047: /**
048: * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
049: */
050: public void configure(Configuration handlerConfiguration)
051: throws ConfigurationException {
052: Configuration configuration = handlerConfiguration.getChild(
053: "checkResolvableEhlo", false);
054: if (configuration != null) {
055: checkResolvableEhlo = configuration.getValueAsBoolean();
056: }
057:
058: Configuration configRelay = handlerConfiguration.getChild(
059: "checkAuthNetworks", false);
060: if (configRelay != null) {
061: checkAuthNetworks = configRelay.getValueAsBoolean();
062: }
063: }
064:
065: /*
066: * processes EHLO command
067: *
068: * @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
069: **/
070: public void onCommand(SMTPSession session) {
071: doEHLO(session, session.getCommandArgument());
072: }
073:
074: /**
075: * Handler method called upon receipt of a EHLO command.
076: * Responds with a greeting and informs the client whether
077: * client authentication is required.
078: *
079: * @param session SMTP session object
080: * @param argument the argument passed in with the command by the SMTP client
081: */
082: private void doEHLO(SMTPSession session, String argument) {
083: String responseString = null;
084: StringBuffer responseBuffer = session.getResponseBuffer();
085: boolean badEhlo = false;
086:
087: // check for resolvabe helo if its set in config
088: if (checkResolvableEhlo) {
089:
090: /**
091: * don't check if the ip address is allowed to relay. Only check if it is set in the config. ed.
092: */
093: if (!session.isRelayingAllowed() || checkAuthNetworks) {
094:
095: // try to resolv the provided helo. If it can not resolved do not accept it.
096: try {
097: org.apache.james.dnsserver.DNSServer
098: .getByName(argument);
099: } catch (UnknownHostException e) {
100: badEhlo = true;
101: responseString = "501 "
102: + DSNStatus.getStatus(DSNStatus.PERMANENT,
103: DSNStatus.DELIVERY_INVALID_ARG)
104: + " Provided EHLO " + argument
105: + " can not resolved";
106: session.writeResponse(responseString);
107: getLogger().info(responseString);
108: }
109: }
110: }
111:
112: if (argument == null) {
113: responseString = "501 "
114: + DSNStatus.getStatus(DSNStatus.PERMANENT,
115: DSNStatus.DELIVERY_INVALID_ARG)
116: + " Domain address required: " + COMMAND_NAME;
117: session.writeResponse(responseString);
118: } else if (!badEhlo) {
119: session.resetState();
120: session.getState().put(SMTPSession.CURRENT_HELO_MODE,
121: COMMAND_NAME);
122:
123: ArrayList esmtpextensions = new ArrayList();
124:
125: esmtpextensions.add(new StringBuffer(session
126: .getConfigurationData().getHelloName()).append(
127: " Hello ").append(argument).append(" (").append(
128: session.getRemoteHost()).append(" [").append(
129: session.getRemoteIPAddress()).append("])")
130: .toString());
131:
132: // Extension defined in RFC 1870
133: long maxMessageSize = session.getConfigurationData()
134: .getMaxMessageSize();
135: if (maxMessageSize > 0) {
136: esmtpextensions.add("SIZE " + maxMessageSize);
137: }
138:
139: if (session.isAuthRequired()) {
140: esmtpextensions.add("AUTH LOGIN PLAIN");
141: esmtpextensions.add("AUTH=LOGIN PLAIN");
142: }
143:
144: esmtpextensions.add("PIPELINING");
145: esmtpextensions.add("ENHANCEDSTATUSCODES");
146: // see http://issues.apache.org/jira/browse/JAMES-419
147: //esmtpextensions.add("8BITMIME");
148:
149: // Iterator i = esmtpextensions.iterator();
150: for (int i = 0; i < esmtpextensions.size(); i++) {
151: if (i == esmtpextensions.size() - 1) {
152: responseBuffer.append("250 ");
153: responseBuffer.append((String) esmtpextensions
154: .get(i));
155: session
156: .writeResponse(session
157: .clearResponseBuffer());
158: } else {
159: responseBuffer.append("250-");
160: responseBuffer.append((String) esmtpextensions
161: .get(i));
162: session
163: .writeResponse(session
164: .clearResponseBuffer());
165: }
166: }
167: }
168: }
169:
170: }
|