1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.dumbster.smtp;
21
22 /***
23 * Contains an SMTP client request.
24 */
25 public class SmtpRequest {
26
27 /*** SMTP action received from client. */
28 private SmtpActionType action;
29
30 /*** Current state of the SMTP state table. */
31 private SmtpState state;
32
33 /*** Additional information passed from the client with the SMTP action. */
34 private String params;
35
36 /***
37 * Create a new SMTP client request.
38 * @param actionType type of action/command
39 * @param params remainder of command line once command is removed
40 * @param state current SMTP server state
41 */
42 public SmtpRequest(SmtpActionType actionType, String params, SmtpState state) {
43 this.action = actionType;
44 this.state = state;
45 this.params = params;
46 }
47
48 /***
49 * Execute the SMTP request returning a response. This method models the state transition table for the SMTP server.
50 * @return reponse to the request
51 */
52 public SmtpResponse execute() {
53 SmtpResponse response = null;
54 if (action.isStateless()) {
55 if (SmtpActionType.EXPN == action || SmtpActionType.VRFY == action) {
56 response = new SmtpResponse(252, "Not supported", this.state);
57 } else if (SmtpActionType.HELP == action) {
58 response = new SmtpResponse(211, "No help available", this.state);
59 } else if (SmtpActionType.NOOP == action) {
60 response = new SmtpResponse(250, "OK", this.state);
61 } else if (SmtpActionType.VRFY == action) {
62 response = new SmtpResponse(252, "Not supported", this.state);
63 } else if (SmtpActionType.RSET == action) {
64 response = new SmtpResponse(250, "OK", SmtpState.GREET);
65 } else {
66 response = new SmtpResponse(500, "Command not recognized", this.state);
67 }
68 } else {
69 if (SmtpActionType.CONNECT == action) {
70 if (SmtpState.CONNECT == state) {
71 response = new SmtpResponse(220, "localhost Dumbster SMTP service ready",
72 SmtpState.GREET);
73 } else {
74 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
75 this.state);
76 }
77 } else if (SmtpActionType.EHLO == action) {
78 if (SmtpState.GREET == state) {
79 response = new SmtpResponse(250, "OK", SmtpState.MAIL);
80 } else {
81 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
82 this.state);
83 }
84 } else if (SmtpActionType.MAIL == action) {
85 if (SmtpState.MAIL == state) {
86 response = new SmtpResponse(250, "OK", SmtpState.RCPT);
87 } else {
88 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
89 this.state);
90 }
91 } else if (SmtpActionType.RCPT == action) {
92 if (SmtpState.RCPT == state) {
93 response = new SmtpResponse(250, "OK", this.state);
94 } else {
95 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
96 this.state);
97 }
98 } else if (SmtpActionType.DATA == action) {
99 if (SmtpState.RCPT == state) {
100 response = new SmtpResponse(354, "Start mail input; end with <CRLF>.<CRLF>",
101 SmtpState.DATA_HDR);
102 } else {
103 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
104 this.state);
105 }
106 } else if (SmtpActionType.UNRECOG == action) {
107 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
108 response = new SmtpResponse(-1, "", this.state);
109 } else {
110 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
111 this.state);
112 }
113 } else if (SmtpActionType.DATA_END == action) {
114 if (SmtpState.DATA_HDR == state || SmtpState.DATA_BODY == state) {
115 response = new SmtpResponse(250, "OK", SmtpState.QUIT);
116 } else {
117 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
118 this.state);
119 }
120 } else if (SmtpActionType.BLANK_LINE == action) {
121 if (SmtpState.DATA_HDR == state) {
122 response = new SmtpResponse(-1, "", SmtpState.DATA_BODY);
123 } else if (SmtpState.DATA_BODY == state) {
124 response = new SmtpResponse(-1, "", this.state);
125 } else {
126 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
127 this.state);
128 }
129 } else if (SmtpActionType.QUIT == action) {
130 if (SmtpState.QUIT == state) {
131 response = new SmtpResponse(250, "OK", SmtpState.CONNECT);
132 } else {
133 response = new SmtpResponse(503, "Bad sequence of commands: " + action,
134 this.state);
135 }
136 } else {
137 response = new SmtpResponse(500, "Command not recognized", this.state);
138 }
139 }
140 return response;
141 }
142
143 /***
144 * Create an SMTP request object given a line of the input stream from the client and the current internal state.
145 * @param s line of input
146 * @param state current state
147 * @return a populated SmtpRequest object
148 */
149 public static SmtpRequest createRequest(String s, SmtpState state) {
150 SmtpActionType action = null;
151 String params = null;
152
153 if (state == SmtpState.DATA_HDR) {
154 if (s.equals(".")) {
155 action = SmtpActionType.DATA_END;
156 } else if (s.length() < 1) {
157 action = SmtpActionType.BLANK_LINE;
158 } else {
159 action = SmtpActionType.UNRECOG;
160 params = s;
161 }
162 } else if (state == SmtpState.DATA_BODY) {
163 if (s.equals(".")) {
164 action = SmtpActionType.DATA_END;
165 } else {
166 action = SmtpActionType.UNRECOG;
167 if (s.length() < 1) {
168 params = "\n";
169 } else {
170 params = s;
171 }
172 }
173 } else {
174 String su = s.toUpperCase();
175 if (su.startsWith("EHLO ") || su.startsWith("HELO")) {
176 action = SmtpActionType.EHLO;
177 params = s.substring(5);
178 } else if (su.startsWith("MAIL FROM:")) {
179 action = SmtpActionType.MAIL;
180 params = s.substring(10);
181 } else if (su.startsWith("RCPT TO:")) {
182 action = SmtpActionType.RCPT;
183 params = s.substring(8);
184 } else if (su.startsWith("DATA")) {
185 action = SmtpActionType.DATA;
186 } else if (su.startsWith("QUIT")) {
187 action = SmtpActionType.QUIT;
188 } else if (su.startsWith("RSET")) {
189 action = SmtpActionType.RSET;
190 } else if (su.startsWith("NOOP")) {
191 action = SmtpActionType.NOOP;
192 } else if (su.startsWith("EXPN")) {
193 action = SmtpActionType.EXPN;
194 } else if (su.startsWith("VRFY")) {
195 action = SmtpActionType.VRFY;
196 } else if (su.startsWith("HELP")) {
197 action = SmtpActionType.HELP;
198 }
199 }
200
201 SmtpRequest req = new SmtpRequest(action, params, state);
202 return req;
203 }
204
205 /***
206 * Get the parameters of this request (remainder of command line once the command is removed.
207 * @return parameters
208 */
209 public String getParams() {
210 return params;
211 }
212 }