blob: 9efacdf9d6aaa6926fa3eebded37a3cab3b5dcd2 [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.
adamdunkels06f897e2004-06-06 05:59:20 +000013 * 3. The name of the author may not be used to endorse or promote
adamdunkelsca9ddcb2003-03-19 14:13:31 +000014 * products derived from this software without specific prior
15 * written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * This file is part of the uIP TCP/IP stack.
30 *
adamdunkelsf2f8cb22004-07-04 11:35:07 +000031 * $Id: smtp.c,v 1.6 2004/07/04 11:35:08 adamdunkels Exp $
adamdunkelsca9ddcb2003-03-19 14:13:31 +000032 *
33 */
34
35#include "uip.h"
36#include "smtp.h"
37
38#include "smtp-strings.h"
39
adamdunkelsf2f8cb22004-07-04 11:35:07 +000040#include "tcpip.h"
41
adamdunkelsca9ddcb2003-03-19 14:13:31 +000042#include <string.h>
43
44#define STATE_SEND_NONE 0
45#define STATE_SEND_HELO 1
46#define STATE_SEND_MAIL_FROM 2
47#define STATE_SEND_RCPT_TO 3
48#define STATE_SEND_DATA 4
49#define STATE_SEND_DATA_HEADERS 5
50#define STATE_SEND_DATA_MESSAGE 6
51#define STATE_SEND_DATA_END 7
52#define STATE_SEND_QUIT 8
53#define STATE_SEND_DONE 9
54
55static char *localhostname;
56static u16_t smtpserver[2];
57
58
59
60#define ISO_nl 0x0a
61#define ISO_cr 0x0d
62
63#define ISO_period 0x2e
64
65#define ISO_2 0x32
66#define ISO_3 0x33
67#define ISO_4 0x34
68#define ISO_5 0x35
69
70
71struct smtp_state {
72 u8_t state;
73 char *to;
74 char *from;
75 char *subject;
76 char *msg;
77 u16_t msglen;
78
79 u16_t sentlen, textlen;
80 u16_t sendptr;
81
82};
83
84
85static struct smtp_state s;
86
87/*-----------------------------------------------------------------------------------*/
88static void
89senddata(void)
90{
91 char *textptr;
92
93 if(s.textlen != 0 &&
94 s.textlen == s.sendptr) {
95 return;
96 }
97
98 textptr = (char *)uip_appdata;
99 switch(s.state) {
100 case STATE_SEND_HELO:
101 /* Create HELO message. */
102 strcpy(textptr, smtp_helo);
103 textptr += sizeof(smtp_helo) - 1;
104 strcpy(textptr, localhostname);
105 textptr += strlen(localhostname);
106 *textptr = ISO_cr;
107 ++textptr;
108 *textptr = ISO_nl;
109 ++textptr;
110 /* printf("s.sendptr %d\n", s.sendptr);*/
111 if(s.sendptr == 0) {
112 s.textlen = textptr - (char *)uip_appdata;
113 /* printf("s.textlen %d\n", s.textlen);*/
114 }
115 textptr = (char *)uip_appdata;
116 break;
117 case STATE_SEND_MAIL_FROM:
118 /* Create MAIL FROM message. */
119 strcpy(textptr, smtp_mail_from);
120 textptr += sizeof(smtp_mail_from) - 1;
121 strcpy(textptr, s.from);
122 textptr += strlen(s.from);
123 *textptr = ISO_cr;
124 ++textptr;
125 *textptr = ISO_nl;
126 ++textptr;
127 if(s.sendptr == 0) {
128 s.textlen = textptr - (char *)uip_appdata;
129 }
130 textptr = (char *)uip_appdata;
131 break;
132 case STATE_SEND_RCPT_TO:
133 /* Create RCPT_TO message. */
134 strcpy(textptr, smtp_rcpt_to);
135 textptr += sizeof(smtp_rcpt_to) - 1;
136 strcpy(textptr, s.to);
137 textptr += strlen(s.to);
138 *textptr = ISO_cr;
139 ++textptr;
140 *textptr = ISO_nl;
141 ++textptr;
142 if(s.sendptr == 0) {
143 s.textlen = textptr - (char *)uip_appdata;
144 }
145 textptr = (char *)uip_appdata;
146 break;
147 case STATE_SEND_DATA:
148 strcpy(textptr, smtp_data);
149 textptr += sizeof(smtp_data) - 1;
150 *textptr = ISO_cr;
151 ++textptr;
152 *textptr = ISO_nl;
153 ++textptr;
154 if(s.sendptr == 0) {
155 s.textlen = textptr - (char *)uip_appdata;
156 }
157 textptr = (char *)uip_appdata;
158 break;
159 case STATE_SEND_DATA_HEADERS:
160 /* Create mail headers. */
161 strcpy(textptr, smtp_to);
162 textptr += sizeof(smtp_to) - 1;
163 strcpy(textptr, s.to);
164 textptr += strlen(s.to);
165 *textptr = ISO_cr;
166 ++textptr;
167 *textptr = ISO_nl;
168 ++textptr;
169
170 strcpy(textptr, smtp_from);
171 textptr += sizeof(smtp_from) - 1;
172 strcpy(textptr, s.from);
173 textptr += strlen(s.from);
174 *textptr = ISO_cr;
175 ++textptr;
176 *textptr = ISO_nl;
177 ++textptr;
178
179 strcpy(textptr, smtp_subject);
180 textptr += sizeof(smtp_subject) - 1;
181 strcpy(textptr, s.subject);
182 textptr += strlen(s.subject);
183 *textptr = ISO_cr;
184 ++textptr;
185 *textptr = ISO_nl;
186 ++textptr;
187
188 if(s.sendptr == 0) {
189 s.textlen = textptr - (char *)uip_appdata;
190 }
191 textptr = (char *)uip_appdata;
192 break;
193 case STATE_SEND_DATA_MESSAGE:
194 textptr = s.msg;
195 if(s.sendptr == 0) {
196 s.textlen = s.msglen;
197 }
198 break;
199 case STATE_SEND_DATA_END:
200 *textptr = ISO_cr;
201 ++textptr;
202 *textptr = ISO_nl;
203 ++textptr;
204 *textptr = ISO_period;
205 ++textptr;
206 *textptr = ISO_cr;
207 ++textptr;
208 *textptr = ISO_nl;
209 ++textptr;
210 if(s.sendptr == 0) {
211 s.textlen = 5;
212 }
213 textptr = (char *)uip_appdata;
214 break;
215 case STATE_SEND_QUIT:
216 strcpy(textptr, smtp_quit);
217 textptr += sizeof(smtp_quit) - 1;
218 *textptr = ISO_cr;
219 ++textptr;
220 *textptr = ISO_nl;
221 ++textptr;
222 if(s.sendptr == 0) {
223 s.textlen = textptr - (char *)uip_appdata;
224 }
225 textptr = (char *)uip_appdata;
226 break;
227 default:
228 return;
229 }
230
231 textptr += s.sendptr;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000232
233 if(s.textlen - s.sendptr > uip_mss()) {
234 s.sentlen = uip_mss();
235 } else {
236 s.sentlen = s.textlen - s.sendptr;
237 }
adamdunkelscd583a52003-08-11 22:23:54 +0000238
239 /* textptr[s.sentlen] = 0;
240 printf("Senidng '%s'\n", textptr);*/
241
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000242 uip_send(textptr, s.sentlen);
243}
244/*-----------------------------------------------------------------------------------*/
245static void
246acked(void)
adamdunkelscd583a52003-08-11 22:23:54 +0000247{
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000248 s.sendptr += s.sentlen;
249 s.sentlen = 0;
250
251 if(s.sendptr == s.textlen) {
252 switch(s.state) {
253 case STATE_SEND_DATA_HEADERS:
254 s.state = STATE_SEND_DATA_MESSAGE;
adamdunkelscd583a52003-08-11 22:23:54 +0000255 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000256 break;
257 case STATE_SEND_DATA_MESSAGE:
258 s.state = STATE_SEND_DATA_END;
adamdunkelscd583a52003-08-11 22:23:54 +0000259 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000260 break;
261 case STATE_SEND_DATA_END:
262 s.state = STATE_SEND_QUIT;
adamdunkelscd583a52003-08-11 22:23:54 +0000263 s.sendptr = s.textlen = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000264 break;
265 case STATE_SEND_QUIT:
266 s.state = STATE_SEND_DONE;
267 smtp_done(SMTP_ERR_OK);
268 uip_close();
269 break;
270 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000271 }
272}
273/*-----------------------------------------------------------------------------------*/
274static void
275newdata(void)
276{
277 if(*(char *)uip_appdata == ISO_5) {
278 smtp_done(1);
279 uip_abort();
280 return;
281 }
282 /* printf("Got %d bytes: '%s'\n", uip_datalen(),
283 uip_appdata);*/
284 switch(s.state) {
285 case STATE_SEND_NONE:
286 if(strncmp((char *)uip_appdata, smtp_220, 3) == 0) {
adamdunkelscd583a52003-08-11 22:23:54 +0000287 /* printf("Newdata(): SEND_NONE, got 220, towards SEND_HELO\n");*/
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000288 s.state = STATE_SEND_HELO;
adamdunkelscd583a52003-08-11 22:23:54 +0000289 s.sendptr = 0;
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000290 }
291 break;
292 case STATE_SEND_HELO:
293 if(*(char *)uip_appdata == ISO_2) {
adamdunkelscd583a52003-08-11 22:23:54 +0000294 /* printf("Newdata(): SEND_HELO, got 2*, towards SEND_MAIL_FROM\n");*/
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000295 s.state = STATE_SEND_MAIL_FROM;
296 s.sendptr = 0;
297 }
298 break;
299 case STATE_SEND_MAIL_FROM:
300 if(*(char *)uip_appdata == ISO_2) {
adamdunkelscd583a52003-08-11 22:23:54 +0000301 /* printf("Newdata(): SEND_MAIL_FROM, got 2*, towards SEND_RCPT_TO\n"); */
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000302 /* printf("2\n");*/
303 s.state = STATE_SEND_RCPT_TO;
304 s.textlen = s.sendptr = 0;
305 }
306 break;
307 case STATE_SEND_RCPT_TO:
308 if(*(char *)uip_appdata == ISO_2) {
309 /* printf("2\n");*/
310 s.state = STATE_SEND_DATA;
311 s.textlen = s.sendptr = 0;
312 }
313 break;
314 case STATE_SEND_DATA:
315 if(*(char *)uip_appdata == ISO_3) {
316 /* printf("3\n");*/
317 s.state = STATE_SEND_DATA_HEADERS;
318 s.textlen = s.sendptr = 0;
319 }
320 break;
321 case STATE_SEND_DATA_HEADERS:
322 if(*(char *)uip_appdata == ISO_3) {
323 /* printf("3\n");*/
324 s.state = STATE_SEND_DATA_MESSAGE;
325 s.textlen = s.sendptr = 0;
326 }
327 break;
328 }
329
330}
331/*-----------------------------------------------------------------------------------*/
adamdunkelsf2f8cb22004-07-04 11:35:07 +0000332/*DISPATCHER_UIPCALL(smtp_appcall, state)*/
333void
334smtp_appcall(void *state)
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000335{
336 if(uip_connected()) {
337 /* senddata();*/
338 return;
339 }
340 if(uip_acked()) {
341 acked();
342 }
adamdunkelscd583a52003-08-11 22:23:54 +0000343 if(uip_newdata()) {
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000344 newdata();
345 }
346 if(uip_rexmit() ||
347 uip_newdata() ||
348 uip_acked()) {
349 senddata();
350 } else if(uip_poll()) {
351 senddata();
352 }
353 /* if(uip_closed()) {
354 printf("Dnoe\n");
355 }*/
356
357
358}
359/*-----------------------------------------------------------------------------------*/
360unsigned char
361smtp_send(char *to, char *from, char *subject,
362 char *msg, u16_t msglen)
363{
364 struct uip_conn *conn;
365
adamdunkelsf2f8cb22004-07-04 11:35:07 +0000366 conn = tcp_connect(smtpserver, HTONS(25), NULL);
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000367 if(conn == NULL) {
368 return 0;
369 }
adamdunkelsca9ddcb2003-03-19 14:13:31 +0000370
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/*-----------------------------------------------------------------------------------*/