Tiny SMTP Client

Dependencies:   EthernetNetIf mbed

Revision:
1:05064fe7ea1e
Parent:
0:7440c9b170aa
--- a/TinySMTP.cpp	Wed Jul 27 15:09:04 2011 +0000
+++ b/TinySMTP.cpp	Thu Jul 28 17:39:31 2011 +0000
@@ -20,8 +20,9 @@
 #define STATUS_ERROR 3
 #define STATUS_DISCONNECTED 4
 
-TCPSocket *smtp;
-volatile int tcp_status = 0, dns_status = 0;
+static TCPSocket *smtp;
+static volatile int tcp_ready, tcp_readable, tcp_writable;
+static volatile int dns_status;
 
 
 // Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
@@ -56,42 +57,45 @@
     printf("tcp(%d)\r\n", e);
 #endif
     switch(e) {
-    case TCPSOCKET_READABLE: //Incoming data
-        tcp_status = STATUS_READABLE;
+    case TCPSOCKET_CONNECTED:
+        tcp_ready = 1;
         break;
 
-    case TCPSOCKET_CONNECTED:
+    case TCPSOCKET_READABLE: //Incoming data
+        tcp_readable = 1;
+        break;
+
     case TCPSOCKET_WRITEABLE: //We can send data
-        tcp_status = STATUS_CONNECTED;
+        tcp_writable = 1;
         break;
 
     case TCPSOCKET_CONTIMEOUT:
     case TCPSOCKET_CONRST:
     case TCPSOCKET_CONABRT:
     case TCPSOCKET_ERROR:
-        tcp_status = STATUS_ERROR;
-        break;
-
     case TCPSOCKET_DISCONNECTED:
-        tcp_status = STATUS_DISCONNECTED;
+        tcp_ready = 0;
         break;
     }
 }
 
 int wait_smtp (int code) {
+    Timer timeout;
     int i;
-    char buf[700];
+    char buf[1500];
 
     // wait responce
-    for (i = 0; i < SMTP_TIMEOUT / 10; i ++) {
-        if (tcp_status != STATUS_CONNECTED) break;
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < SMTP_TIMEOUT) {
+        if (tcp_readable) break;
         Net::poll();
-        wait_ms(10);
     }
-    if (tcp_status != STATUS_READABLE) return -1;
-    tcp_status = STATUS_CONNECTED;
+    timeout.stop();
+    if (! tcp_readable) return -1;
     // recv
     i = smtp->recv(buf, sizeof(buf));
+    if (i < sizeof(buf) - 1) tcp_readable = 0;
     buf[i] = 0;
 #ifdef DEBUG
     printf(buf);
@@ -105,6 +109,9 @@
 
 void isr_dns (DNSReply r) {
 
+#ifdef DEBUG
+    printf("dns(%d)\r\n", r);
+#endif
     if (DNS_FOUND) {
         dns_status = 1;
     } else {
@@ -114,10 +121,13 @@
 
 int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd) {
     TCPSocketErr err;
-    int i, ret = -1;
+    Timer timeout;
+    int ret = -1;
 
     smtp = new TCPSocket;
-    tcp_status = STATUS_NONE;
+    tcp_ready = 0;
+    tcp_readable = 0;
+    tcp_writable = 0;
 
     smtp->setOnEvent(isr_smtp);
 
@@ -127,22 +137,34 @@
         dns_status = 0;
         dns.setOnReply(isr_dns);
         if (dns.resolve(host) != DNS_OK) goto exit;
-        for (i = 0; i < SMTP_TIMEOUT / 10; i ++) {
+        timeout.reset();
+        timeout.start();
+        while (timeout.read_ms() < SMTP_TIMEOUT) {
             if (dns_status) break;
             Net::poll();
-            wait_ms(10);
         }
-        while (dns_status < 0) goto exit;
+        timeout.stop();
+        if (dns_status <= 0) goto exit;
+#ifdef DEBUG
+        printf("%s [%d.%d.%d.%d]\r\n", host->getName(), (unsigned char)host->getIp()[0], (unsigned char)host->getIp()[1], (unsigned char)host->getIp()[2], (unsigned char)host->getIp()[3]);
+#endif
     }
+    if (! host->getPort()) {
+        host->setPort(SMTP_PORT);
+    }
+
     err = smtp->connect(*host);
     if (err != TCPSOCKET_OK) goto exit;
 
     // wait connect
-    for (i = 0; i < 1500; i ++) {
-        if (tcp_status != STATUS_NONE) break;
+    timeout.reset();
+    timeout.start();
+    while (timeout.read_ms() < SMTP_TIMEOUT) {
+        if (tcp_ready) break;
         Net::poll();
-        wait_ms(10);
     }
+    timeout.stop();
+    if (! tcp_ready) goto exit;
     if (wait_smtp(220)) goto exit;
 
     // send request