1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.smtpserver.core.filter;
23
24 import java.util.ArrayList;
25 import java.util.Collection;
26
27 import java.util.Locale;
28 import java.util.StringTokenizer;
29
30 import org.apache.avalon.framework.logger.AbstractLogEnabled;
31 import org.apache.james.dsn.DSNStatus;
32 import org.apache.james.smtpserver.CommandHandler;
33 import org.apache.james.smtpserver.SMTPSession;
34 import org.apache.mailet.MailAddress;
35
36
37
38
39 public class RcptFilterCmdHandler extends AbstractLogEnabled implements
40 CommandHandler {
41
42
43
44
45
46
47
48 public void onCommand(SMTPSession session) {
49 doRCPT(session, session.getCommandArgument());
50 }
51
52
53
54
55
56
57 private void doRCPT(SMTPSession session, String argument) {
58 String responseString = null;
59
60 String recipient = null;
61 if ((argument != null) && (argument.indexOf(":") > 0)) {
62 int colonIndex = argument.indexOf(":");
63 recipient = argument.substring(colonIndex + 1);
64 argument = argument.substring(0, colonIndex);
65 }
66 if (!session.getState().containsKey(SMTPSession.SENDER)) {
67 responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need MAIL before RCPT";
68 session.writeResponse(responseString);
69
70
71 session.setStopHandlerProcessing(true);
72
73 } else if (argument == null || !argument.toUpperCase(Locale.US).equals("TO")
74 || recipient == null) {
75 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Usage: RCPT TO:<recipient>";
76 session.writeResponse(responseString);
77
78
79 session.setStopHandlerProcessing(true);
80
81 } else {
82 Collection rcptColl = (Collection) session.getState().get(SMTPSession.RCPT_LIST);
83 if (rcptColl == null) {
84 rcptColl = new ArrayList();
85 }
86 recipient = recipient.trim();
87 int lastChar = recipient.lastIndexOf('>');
88
89
90 String rcptOptionString = null;
91 if ((lastChar > 0) && (recipient.length() > lastChar + 2) && (recipient.charAt(lastChar + 1) == ' ')) {
92 rcptOptionString = recipient.substring(lastChar + 2);
93
94
95 recipient = recipient.substring(0, lastChar + 1);
96 }
97 if (session.getConfigurationData().useAddressBracketsEnforcement() && (!recipient.startsWith("<") || !recipient.endsWith(">"))) {
98 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Syntax error in parameters or arguments";
99 session.writeResponse(responseString);
100 if (getLogger().isErrorEnabled()) {
101 StringBuffer errorBuffer =
102 new StringBuffer(192)
103 .append("Error parsing recipient address: ")
104 .append("Address did not start and end with < >")
105 .append(getContext(session,null,recipient));
106 getLogger().error(errorBuffer.toString());
107 }
108
109
110 session.setStopHandlerProcessing(true);
111
112 return;
113 }
114 MailAddress recipientAddress = null;
115
116 if (session.getConfigurationData().useAddressBracketsEnforcement() || (recipient.startsWith("<") && recipient.endsWith(">"))) {
117 recipient = recipient.substring(1, recipient.length() - 1);
118 }
119
120 if (recipient.indexOf("@") < 0) {
121
122 recipient = recipient + "@" + session.getConfigurationData().getMailServer().getDefaultDomain();
123 }
124
125 try {
126 recipientAddress = new MailAddress(recipient);
127 } catch (Exception pe) {
128
129
130
131
132
133 responseString = "553 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX)+" Syntax error in recipient address";
134 session.writeResponse(responseString);
135
136 if (getLogger().isErrorEnabled()) {
137 StringBuffer errorBuffer =
138 new StringBuffer(192)
139 .append("Error parsing recipient address: ")
140 .append(getContext(session,recipientAddress,recipient))
141 .append(pe.getMessage());
142 getLogger().error(errorBuffer.toString());
143 }
144
145
146 session.setStopHandlerProcessing(true);
147
148 return;
149 }
150
151
152
153 if (session.isAuthRequired() && !session.isRelayingAllowed()) {
154
155
156 if (session.getUser() == null) {
157 String toDomain = recipientAddress.getHost();
158 if (!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
159 responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Authentication Required";
160 session.writeResponse(responseString);
161 StringBuffer sb = new StringBuffer(128);
162 sb.append("Rejected message - authentication is required for mail request");
163 sb.append(getContext(session,recipientAddress,recipient));
164 getLogger().error(sb.toString());
165
166
167 session.setStopHandlerProcessing(true);
168
169 return;
170 }
171 } else {
172
173 if (session.getConfigurationData().isVerifyIdentity()) {
174 String authUser = (session.getUser()).toLowerCase(Locale.US);
175 MailAddress senderAddress = (MailAddress) session.getState().get(SMTPSession.SENDER);
176
177 if ((senderAddress == null) || (!authUser.equals(senderAddress.getUser())) ||
178 (!session.getConfigurationData().getMailServer().isLocalServer(senderAddress.getHost()))) {
179 responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Incorrect Authentication for Specified Email Address";
180 session.writeResponse(responseString);
181 if (getLogger().isErrorEnabled()) {
182 StringBuffer errorBuffer =
183 new StringBuffer(128)
184 .append("User ")
185 .append(authUser)
186 .append(" authenticated, however tried sending email as ")
187 .append(senderAddress)
188 .append(getContext(session,recipientAddress,recipient));
189 getLogger().error(errorBuffer.toString());
190 }
191
192
193 session.setStopHandlerProcessing(true);
194
195 return;
196 }
197 }
198 }
199 } else if (!session.isRelayingAllowed()) {
200 String toDomain = recipientAddress.getHost();
201 if (!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
202 responseString = "550 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Requested action not taken: relaying denied";
203 session.writeResponse(responseString);
204 StringBuffer errorBuffer = new StringBuffer(128)
205 .append("Rejected message - ")
206 .append(session.getRemoteIPAddress())
207 .append(" not authorized to relay to ")
208 .append(toDomain)
209 .append(getContext(session,recipientAddress,recipient));
210 getLogger().error(errorBuffer.toString());
211
212
213 session.setStopHandlerProcessing(true);
214
215 return;
216 }
217 }
218 if (rcptOptionString != null) {
219
220 StringTokenizer optionTokenizer = new StringTokenizer(rcptOptionString, " ");
221 while (optionTokenizer.hasMoreElements()) {
222 String rcptOption = optionTokenizer.nextToken();
223 int equalIndex = rcptOption.indexOf('=');
224 String rcptOptionName = rcptOption;
225 String rcptOptionValue = "";
226 if (equalIndex > 0) {
227 rcptOptionName = rcptOption.substring(0, equalIndex).toUpperCase(Locale.US);
228 rcptOptionValue = rcptOption.substring(equalIndex + 1);
229 }
230
231 if (getLogger().isDebugEnabled()) {
232 StringBuffer debugBuffer =
233 new StringBuffer(128)
234 .append("RCPT command had unrecognized/unexpected option ")
235 .append(rcptOptionName)
236 .append(" with value ")
237 .append(rcptOptionValue)
238 .append(getContext(session,recipientAddress,recipient));
239 getLogger().debug(debugBuffer.toString());
240 }
241
242
243 session.setStopHandlerProcessing(true);
244
245 }
246 optionTokenizer = null;
247 }
248
249 session.getState().put(SMTPSession.CURRENT_RECIPIENT,recipientAddress);
250 }
251 }
252
253
254 private String getContext(SMTPSession session, MailAddress recipientAddress, String recipient){
255 StringBuffer sb = new StringBuffer(128);
256 if(null!=recipientAddress) {
257 sb.append(" [to:" + (recipientAddress).toInternetAddress().getAddress() + "]");
258 } else if(null!=recipient) {
259 sb.append(" [to:" + recipient + "]");
260 }
261 if (null!=session.getState().get(SMTPSession.SENDER)) {
262 sb.append(" [from:" + ((MailAddress)session.getState().get(SMTPSession.SENDER)).toInternetAddress().getAddress() + "]");
263 }
264 return sb.toString();
265 }
266
267
268
269
270 public Collection getImplCommands() {
271 Collection implCommands = new ArrayList();
272 implCommands.add("RCPT");
273
274 return implCommands;
275 }
276
277 }