blob: 8daefa8106cbcd5c8f2ff89cb5328830dabe2f72 [file] [log] [blame]
adamdunkelsca9ddcb2003-03-19 14:13:31 +00001/*
2 * Copyright (c) 2002, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Adam Dunkels.
16 * 4. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior
18 * written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * This file is part of the uIP TCP/IP stack.
33 *
adamdunkelscd583a52003-08-11 22:23:54 +000034 * $Id: smtp.c,v 1.3 2003/08/11 22:23:54 adamdunkels Exp $
adamdunkelsca9ddcb2003-03-19 14:13:31 +000035 *
36 */
37
38#include "uip.h"
39#include "smtp.h"
40
41#include "smtp-strings.h"
42
43#include <string.h>
44
45#define STATE_SEND_NONE 0
46#define STATE_SEND_HELO 1
47#define STATE_SEND_MAIL_FROM 2
48#define STATE_SEND_RCPT_TO 3
49#define STATE_SEND_DATA 4
50#define STATE_SEND_DATA_HEADERS 5
51#define STATE_SEND_DATA_MESSAGE 6
52#define STATE_SEND_DATA_END 7
53#define STATE_SEND_QUIT 8
54#define STATE_SEND_DONE 9
55
56static char *localhostname;
57static u16_t smtpserver[2];
58
59
60
61#define ISO_nl 0x0a
62#define ISO_cr 0x0d
63
64#define ISO_period 0x2e
65
66#define ISO_2 0x32
67#define ISO_3 0x33
68#define ISO_4 0x34
69#define ISO_5 0x35
70
71
72struct smtp_state {
73 u8_t state;
74 char *to;
75 char *from;
76 char *subject;
77 char *msg;
78 u16_t msglen;
79
80 u16_t sentlen, textlen;
81 u16_t sendptr;
82
83};
84
85
86static struct smtp_state s;
87
88/*-----------------------------------------------------------------------------------*/
89static void
90senddata(void)
91{
92 char *textptr;
93
94 if(s.textlen != 0 &&
95 s.textlen == s.sendptr) {
96 return;
97 }
98
99 textptr = (char *)uip_appdata;
100 switch(s.state) {
101 case STATE_SEND_HELO:
102 /* Create HELO message. */
103 strcpy(textptr, smtp_helo);
104 textptr += sizeof(smtp_helo) - 1;
105 strcpy(textptr, localhostname);
106 textptr += strlen(localhostname);
107 *textptr = ISO_cr;
108 ++textptr;
109 *textptr = ISO_nl;
110 ++textptr;
111 /* printf("s.sendptr %d\n", s.sendptr);*/
112 if(s.sendptr == 0) {
113 s.textlen = textptr - (char *)uip_appdata;
114 /* printf("s.textlen %d\n", s.textlen);*/
115 }
116 textptr = (char *)uip_appdata;
117 break;
118 case STATE_SEND_MAIL_FROM:
119 /* Create MAIL FROM message. */
120 strcpy(textptr, smtp_mail_from);
121 textptr += sizeof(smtp_mail_from) - 1;
122 strcpy(textptr, s.from);
123 textptr += strlen(s.from);
124 *textptr = ISO_cr;
125 ++textptr;
126 *textptr = ISO_nl;
127 ++textptr;
128 if(s.sendptr == 0) {
129 s.textlen = textptr - (char *)uip_appdata;
130 }
131 textptr = (char *)uip_appdata;
132 break;
133 case STATE_SEND_RCPT_TO:
134 /* Create RCPT_TO message. */
135 strcpy(textptr, smtp_rcpt_to);
136 textptr += sizeof(smtp_rcpt_to) - 1;
137 strcpy(textptr, s.to);
138 textptr += strlen(s.to);
139 *textptr = ISO_cr;
140 ++textptr;
141 *textptr = ISO_nl;
142 ++textptr;
143 if(s.sendptr == 0) {
144 s.textlen = textptr - (char *)uip_appdata;
145 }
146 textptr = (char *)uip_appdata;
147 break;
148 case STATE_SEND_DATA:
149 strcpy(textptr, smtp_data);
150 textptr += sizeof(smtp_data) - 1;
151 *textptr = ISO_cr;
152 ++textptr;
153 *textptr = ISO_nl;
154 ++textptr;
155 if(s.sendptr == 0) {
156 s.textlen = textptr - (char *)uip_appdata;
157 }
158 textptr = (char *)uip_appdata;
159 break;
160 case STATE_SEND_DATA_HEADERS:
161 /* Create mail headers. */
162 strcpy(textptr, smtp_to);
163 textptr += sizeof(smtp_to) - 1;
164 strcpy(textptr, s.to);
165 textptr += strlen(s.to);
166 *textptr = ISO_cr;
167 ++textptr;
168 *textptr = ISO_nl;
169 ++textptr;
170
171 strcpy(textptr, smtp_from);
172 textptr += sizeof(smtp_from) - 1;
173 strcpy(textptr, s.from);
174 textptr += strlen(s.from);
175 *textptr = ISO_cr;
176 ++textptr;
177 *textptr = ISO_nl;
178 ++textptr;
179
180 strcpy(textptr, smtp_subject);
181 textptr += sizeof(smtp_subject) - 1;
182 strcpy(textptr, s.subject);
183 textptr += strlen(s.subject);
184 *textptr = ISO_cr;
185 ++textptr;
186 *textptr = ISO_nl;
187 ++textptr;
188
189 if(s.sendptr == 0) {
190 s.textlen = textptr - (char *)uip_appdata;
191 }
192 textptr = (char *)uip_appdata;
193 break;
194 case STATE_SEND_DATA_MESSAGE:
195 textptr = s.msg;
196 if(s.sendptr == 0) {
197 s.textlen = s.msglen;
198 }
199 break;
200 case STATE_SEND_DATA_END:
201 *textptr = ISO_cr;
202 ++textptr;
203 *textptr = ISO_nl;
204 ++textptr;
205 *textptr = ISO_period;
206 ++textptr;
207 *textptr = ISO_cr;
208 ++textptr;
209 *textptr = ISO_nl;
210 ++textptr;
211 if(s.sendptr == 0) {
212 s.textlen = 5;
213 }
214 textptr = (char *)uip_appdata;
215 break;
216 case STATE_SEND_QUIT:
217 strcpy(textptr, smtp_quit);
218 textptr += sizeof(smtp_quit) - 1;
219 *textptr = ISO_cr;
220 ++textptr;
221 *textptr = ISO_nl;
222 ++textptr;
223 if(s.sendptr == 0) {
224 s.textlen = textptr - (char *)uip_appdata;
225 }
226 textptr = (char *)uip_appdata;
227 break;
228 default:
229 return;
230 }
231
232 textptr += s.sendptr;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000233
234 if(s.textlen - s.sendptr > uip_mss()) {
235 s.sentlen = uip_mss();
236 } else {
237 s.sentlen = s.textlen - s.sendptr;
238 }
adamdunkelscd583a52003-08-11 22:23:54 +0000239
240 /* textptr[s.sentlen] = 0;
241 printf("Senidng '%s'\n", textptr);*/
242
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000243 uip_send(textptr, s.sentlen);
244}
245/*-----------------------------------------------------------------------------------*/
246static void
247acked(void)
adamdunkelscd583a52003-08-11 22:23:54 +0000248{
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000249 s.sendptr += s.sentlen;
250 s.sentlen = 0;
251
252 if(s.sendptr == s.textlen) {
253 switch(s.state) {
254 case STATE_SEND_DATA_HEADERS:
255 s.state = STATE_SEND_DATA_MESSAGE;
adamdunkelscd583a52003-08-11 22:23:54 +0000256 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000257 break;
258 case STATE_SEND_DATA_MESSAGE:
259 s.state = STATE_SEND_DATA_END;
adamdunkelscd583a52003-08-11 22:23:54 +0000260 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000261 break;
262 case STATE_SEND_DATA_END:
263 s.state = STATE_SEND_QUIT;
adamdunkelscd583a52003-08-11 22:23:54 +0000264 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000265 break;
266 case STATE_SEND_QUIT:
267 s.state = STATE_SEND_DONE;
268 smtp_done(SMTP_ERR_OK);
269 uip_close();
270 break;
271 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000272 }
273}
274/*-----------------------------------------------------------------------------------*/
275static void
276newdata(void)
277{
278 if(*(char *)uip_appdata == ISO_5) {
279 smtp_done(1);
280 uip_abort();
281 return;
282 }
283 /* printf("Got %d bytes: '%s'\n", uip_datalen(),
284 uip_appdata);*/
285 switch(s.state) {
286 case STATE_SEND_NONE:
287 if(strncmp((char *)uip_appdata, smtp_220, 3) == 0) {
adamdunkelscd583a52003-08-11 22:23:54 +0000288 /* printf("Newdata(): SEND_NONE, got 220, towards SEND_HELO\n");*/
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000289 s.state = STATE_SEND_HELO;
adamdunkelscd583a52003-08-11 22:23:54 +0000290 s.sendptr = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000291 }
292 break;
293 case STATE_SEND_HELO:
294 if(*(char *)uip_appdata == ISO_2) {
adamdunkelscd583a52003-08-11 22:23:54 +0000295 /* printf("Newdata(): SEND_HELO, got 2*, towards SEND_MAIL_FROM\n");*/
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000296 s.state = STATE_SEND_MAIL_FROM;
297 s.sendptr = 0;
298 }
299 break;
300 case STATE_SEND_MAIL_FROM:
301 if(*(char *)uip_appdata == ISO_2) {
adamdunkelscd583a52003-08-11 22:23:54 +0000302 /* printf("Newdata(): SEND_MAIL_FROM, got 2*, towards SEND_RCPT_TO\n"); */
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000303 /* printf("2\n");*/
304 s.state = STATE_SEND_RCPT_TO;
305 s.textlen = s.sendptr = 0;
306 }
307 break;
308 case STATE_SEND_RCPT_TO:
309 if(*(char *)uip_appdata == ISO_2) {
310 /* printf("2\n");*/
311 s.state = STATE_SEND_DATA;
312 s.textlen = s.sendptr = 0;
313 }
314 break;
315 case STATE_SEND_DATA:
316 if(*(char *)uip_appdata == ISO_3) {
317 /* printf("3\n");*/
318 s.state = STATE_SEND_DATA_HEADERS;
319 s.textlen = s.sendptr = 0;
320 }
321 break;
322 case STATE_SEND_DATA_HEADERS:
323 if(*(char *)uip_appdata == ISO_3) {
324 /* printf("3\n");*/
325 s.state = STATE_SEND_DATA_MESSAGE;
326 s.textlen = s.sendptr = 0;
327 }
328 break;
329 }
330
331}
332/*-----------------------------------------------------------------------------------*/
adamdunkels2e415422003-04-10 09:04:49 +0000333DISPATCHER_UIPCALL(smtp_appcall, state)
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000334{
335 if(uip_connected()) {
336 /* senddata();*/
337 return;
338 }
339 if(uip_acked()) {
340 acked();
341 }
adamdunkelscd583a52003-08-11 22:23:54 +0000342 if(uip_newdata()) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000343 newdata();
344 }
345 if(uip_rexmit() ||
346 uip_newdata() ||
347 uip_acked()) {
348 senddata();
349 } else if(uip_poll()) {
350 senddata();
351 }
352 /* if(uip_closed()) {
353 printf("Dnoe\n");
354 }*/
355
356
357}
358/*-----------------------------------------------------------------------------------*/
359unsigned char
360smtp_send(char *to, char *from, char *subject,
361 char *msg, u16_t msglen)
362{
363 struct uip_conn *conn;
364
365 conn = uip_connect(smtpserver, 25);
366 if(conn == NULL) {
367 return 0;
368 }
369 dispatcher_markconn(conn, NULL);
370
371 s.state = STATE_SEND_NONE;
372 s.sentlen = s.sendptr = s.textlen = 0;
373 s.to = to;
374 s.from = from;
375 s.subject = subject;
376 s.msg = msg;
377 s.msglen = msglen;
378
379 return 1;
380}
381/*-----------------------------------------------------------------------------------*/
382void
383smtp_configure(char *lhostname, u16_t *server)
384{
385 localhostname = lhostname;
386 smtpserver[0] = server[0];
387 smtpserver[1] = server[1];
388}
389/*-----------------------------------------------------------------------------------*/