1 /*****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20 package org.apache.james.smtpserver;
21
22 import org.apache.avalon.framework.configuration.Configurable;
23 import org.apache.avalon.framework.configuration.Configuration;
24 import org.apache.avalon.framework.configuration.ConfigurationException;
25 import org.apache.avalon.framework.logger.AbstractLogEnabled;
26 import org.apache.james.util.mail.dsn.DSNStatus;
27
28 import java.net.UnknownHostException;
29 import java.util.ArrayList;
30
31 /***
32 * Handles EHLO command
33 */
34 public class EhloCmdHandler extends AbstractLogEnabled implements CommandHandler,Configurable {
35
36 /***
37 * The name of the command handled by the command handler
38 */
39 private final static String COMMAND_NAME = "EHLO";
40
41 /***
42 * set checkResolvableEhlo to false as default value
43 */
44 private boolean checkResolvableEhlo = false;
45
46 private boolean checkAuthNetworks = false;
47
48 /***
49 * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
50 */
51 public void configure(Configuration handlerConfiguration) throws ConfigurationException {
52 Configuration configuration = handlerConfiguration.getChild("checkResolvableEhlo",false);
53 if(configuration != null) {
54 checkResolvableEhlo = configuration.getValueAsBoolean();
55 }
56
57 Configuration configRelay = handlerConfiguration.getChild("checkAuthNetworks",false);
58 if(configRelay != null) {
59 checkAuthNetworks = configRelay.getValueAsBoolean();
60 }
61 }
62
63
64
65
66
67
68 public void onCommand(SMTPSession session) {
69 doEHLO(session, session.getCommandArgument());
70 }
71
72 /***
73 * Handler method called upon receipt of a EHLO command.
74 * Responds with a greeting and informs the client whether
75 * client authentication is required.
76 *
77 * @param session SMTP session object
78 * @param argument the argument passed in with the command by the SMTP client
79 */
80 private void doEHLO(SMTPSession session, String argument) {
81 String responseString = null;
82 StringBuffer responseBuffer = session.getResponseBuffer();
83 boolean badEhlo = false;
84
85
86 if (checkResolvableEhlo) {
87
88 /***
89 * don't check if the ip address is allowed to relay. Only check if it is set in the config. ed.
90 */
91 if (!session.isRelayingAllowed() || checkAuthNetworks) {
92
93
94
95 try {
96 org.apache.james.dnsserver.DNSServer.getByName(argument);
97 } catch (UnknownHostException e) {
98 badEhlo = true;
99 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Provided EHLO " + argument + " can not resolved";
100 session.writeResponse(responseString);
101 getLogger().info(responseString);
102 }
103 }
104 }
105
106 if (argument == null) {
107 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Domain address required: " + COMMAND_NAME;
108 session.writeResponse(responseString);
109 } else if (!badEhlo){
110 session.resetState();
111 session.getState().put(SMTPSession.CURRENT_HELO_MODE, COMMAND_NAME);
112
113 ArrayList esmtpextensions = new ArrayList();
114
115 esmtpextensions.add(new StringBuffer(session.getConfigurationData().getHelloName())
116 .append(" Hello ")
117 .append(argument)
118 .append(" (")
119 .append(session.getRemoteHost())
120 .append(" [")
121 .append(session.getRemoteIPAddress())
122 .append("])").toString());
123
124
125 long maxMessageSize = session.getConfigurationData().getMaxMessageSize();
126 if (maxMessageSize > 0) {
127 esmtpextensions.add("SIZE " + maxMessageSize);
128 }
129
130 if (session.isAuthRequired()) {
131 esmtpextensions.add("AUTH LOGIN PLAIN");
132 esmtpextensions.add("AUTH=LOGIN PLAIN");
133 }
134
135 esmtpextensions.add("PIPELINING");
136 esmtpextensions.add("ENHANCEDSTATUSCODES");
137
138
139
140
141
142 for (int i = 0; i < esmtpextensions.size(); i++) {
143 if (i == esmtpextensions.size() - 1) {
144 responseBuffer.append("250 ");
145 responseBuffer.append((String) esmtpextensions.get(i));
146 session.writeResponse(session.clearResponseBuffer());
147 } else {
148 responseBuffer.append("250-");
149 responseBuffer.append((String) esmtpextensions.get(i));
150 session.writeResponse(session.clearResponseBuffer());
151 }
152 }
153 }
154 }
155
156 }