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 import java.util.Locale;
27 import java.util.StringTokenizer;
28
29 import org.apache.avalon.framework.logger.AbstractLogEnabled;
30 import org.apache.james.dsn.DSNStatus;
31 import org.apache.james.smtpserver.CommandHandler;
32 import org.apache.james.smtpserver.SMTPSession;
33 import org.apache.mailet.MailAddress;
34
35
36
37
38 public class MailFilterCmdHandler
39 extends AbstractLogEnabled
40 implements CommandHandler {
41
42 private final static String MAIL_OPTION_SIZE = "SIZE";
43
44 private final static String MESG_SIZE = "MESG_SIZE";
45
46
47
48
49
50
51 public void onCommand(SMTPSession session) {
52 doMAIL(session, session.getCommandArgument());
53 }
54
55
56
57
58
59
60 private void doMAIL(SMTPSession session, String argument) {
61 String responseString = null;
62 String sender = null;
63
64 if ((argument != null) && (argument.indexOf(":") > 0)) {
65 int colonIndex = argument.indexOf(":");
66 sender = argument.substring(colonIndex + 1);
67 argument = argument.substring(0, colonIndex);
68 }
69 if (session.getState().containsKey(SMTPSession.SENDER)) {
70 responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Sender already specified";
71 session.writeResponse(responseString);
72
73
74 session.setStopHandlerProcessing(true);
75
76 } else if (!session.getConnectionState().containsKey(SMTPSession.CURRENT_HELO_MODE) && session.useHeloEhloEnforcement()) {
77 responseString = "503 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need HELO or EHLO before MAIL";
78 session.writeResponse(responseString);
79
80
81 session.setStopHandlerProcessing(true);
82
83 } else if (argument == null || !argument.toUpperCase(Locale.US).equals("FROM")
84 || sender == null) {
85 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Usage: MAIL FROM:<sender>";
86 session.writeResponse(responseString);
87
88
89 session.setStopHandlerProcessing(true);
90
91 } else {
92 sender = sender.trim();
93
94 int lastChar = sender.indexOf('>', sender.indexOf('<'));
95
96
97 if ((lastChar > 0) && (sender.length() > lastChar + 2) && (sender.charAt(lastChar + 1) == ' ')) {
98 String mailOptionString = sender.substring(lastChar + 2);
99
100
101 sender = sender.substring(0, lastChar + 1);
102
103 StringTokenizer optionTokenizer = new StringTokenizer(mailOptionString, " ");
104 while (optionTokenizer.hasMoreElements()) {
105 String mailOption = optionTokenizer.nextToken();
106 int equalIndex = mailOption.indexOf('=');
107 String mailOptionName = mailOption;
108 String mailOptionValue = "";
109 if (equalIndex > 0) {
110 mailOptionName = mailOption.substring(0, equalIndex).toUpperCase(Locale.US);
111 mailOptionValue = mailOption.substring(equalIndex + 1);
112 }
113
114
115
116 if (mailOptionName.startsWith(MAIL_OPTION_SIZE)) {
117 if (!(doMailSize(session, mailOptionValue, sender))) {
118 return;
119 }
120 } else {
121
122 if (getLogger().isDebugEnabled()) {
123 StringBuffer debugBuffer =
124 new StringBuffer(128)
125 .append("MAIL command had unrecognized/unexpected option ")
126 .append(mailOptionName)
127 .append(" with value ")
128 .append(mailOptionValue);
129 getLogger().debug(debugBuffer.toString());
130 }
131 }
132 }
133 }
134 if ( session.getConfigurationData().useAddressBracketsEnforcement() && (!sender.startsWith("<") || !sender.endsWith(">"))) {
135 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX_SENDER)+" Syntax error in MAIL command";
136 session.writeResponse(responseString);
137 if (getLogger().isErrorEnabled()) {
138 StringBuffer errorBuffer =
139 new StringBuffer(128)
140 .append("Error parsing sender address: ")
141 .append(sender)
142 .append(": did not start and end with < >");
143 getLogger().error(errorBuffer.toString());
144 }
145
146 session.setStopHandlerProcessing(true);
147
148 return;
149 }
150 MailAddress senderAddress = null;
151
152 if (session.getConfigurationData().useAddressBracketsEnforcement() || (sender.startsWith("<") && sender.endsWith(">"))) {
153
154 sender = sender.substring(1, sender.length() - 1);
155 }
156
157 if (sender.length() == 0) {
158
159 } else {
160
161 if (sender.indexOf("@") < 0) {
162 sender = sender + "@" + session.getConfigurationData().getMailServer().getDefaultDomain();
163 }
164
165 try {
166 senderAddress = new MailAddress(sender);
167 } catch (Exception pe) {
168 responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX_SENDER)+" Syntax error in sender address";
169 session.writeResponse(responseString);
170 if (getLogger().isErrorEnabled()) {
171 StringBuffer errorBuffer =
172 new StringBuffer(256)
173 .append("Error parsing sender address: ")
174 .append(sender)
175 .append(": ")
176 .append(pe.getMessage());
177 getLogger().error(errorBuffer.toString());
178 }
179
180
181 session.setStopHandlerProcessing(true);
182
183 return;
184 }
185 }
186
187
188 session.getState().put(SMTPSession.SENDER, senderAddress);
189 }
190 }
191
192
193
194
195
196
197
198
199
200 private boolean doMailSize(SMTPSession session, String mailOptionValue, String tempSender) {
201 int size = 0;
202 try {
203 size = Integer.parseInt(mailOptionValue);
204 } catch (NumberFormatException pe) {
205
206 String responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Syntactically incorrect value for SIZE parameter";
207 session.writeResponse(responseString);
208 getLogger().error("Rejected syntactically incorrect value for SIZE parameter.");
209
210
211 session.setStopHandlerProcessing(true);
212
213 return false;
214 }
215 if (getLogger().isDebugEnabled()) {
216 StringBuffer debugBuffer =
217 new StringBuffer(128)
218 .append("MAIL command option SIZE received with value ")
219 .append(size)
220 .append(".");
221 getLogger().debug(debugBuffer.toString());
222 }
223 long maxMessageSize = session.getConfigurationData().getMaxMessageSize();
224 if ((maxMessageSize > 0) && (size > maxMessageSize)) {
225
226 String responseString = "552 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SYSTEM_MSG_TOO_BIG)+" Message size exceeds fixed maximum message size";
227 session.writeResponse(responseString);
228 StringBuffer errorBuffer =
229 new StringBuffer(256)
230 .append("Rejected message from ")
231 .append(tempSender != null ? tempSender : null)
232 .append(" from host ")
233 .append(session.getRemoteHost())
234 .append(" (")
235 .append(session.getRemoteIPAddress())
236 .append(") of size ")
237 .append(size)
238 .append(" exceeding system maximum message size of ")
239 .append(maxMessageSize)
240 .append("based on SIZE option.");
241 getLogger().error(errorBuffer.toString());
242
243
244 session.setStopHandlerProcessing(true);
245
246 return false;
247 } else {
248
249
250 session.getState().put(MESG_SIZE, new Integer(size));
251 }
252 return true;
253 }
254
255
256
257
258 public Collection getImplCommands() {
259 Collection implCommands = new ArrayList();
260 implCommands.add("MAIL");
261
262 return implCommands;
263 }
264
265 }