Embedded system Fun Blog
























































Find out all the best information, libraries and circuit about the latest Embedded systems.
Showing posts with label smtp. Show all posts
Showing posts with label smtp. Show all posts

Sunday, 8 January 2012

MBED: Cool Tiny SMTP Client

.from: http://mbed.org/users/okini3939/programs/TinySMTP/lv1bdk

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "DNSRequest.h"
#include "TinySMTP.h"

#define STATUS_NONE 0
#define STATUS_READABLE 1
#define STATUS_CONNECTED 2
#define STATUS_ERROR 3
#define STATUS_DISCONNECTED 4

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)
int base64enc(const char *input, unsigned int length, char *output, int outputlen) {
  static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  unsigned int c, c1, c2, c3;

  if (outputlen < (((length-1)/3)+1)<<2) return -1;

  for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
    c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
    c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
    c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;

    c = ((c1 & 0xFC) >> 2);
    output[j+0] = base64[c];
    c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
    output[j+1] = base64[c];
    c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
    output[j+2] = (length>i+1)?base64[c]:'=';
    c = (c3 & 0x3F);
    output[j+3] = (length>i+2)?base64[c]:'=';
  }
  output[(((length-1)/3)+1)<<2] = '\0';
  return 0;
}


void isr_smtp (TCPSocketEvent e) {

#ifdef DEBUG
    printf("tcp(%d)\r\n", e);
#endif
    switch(e) {
    case TCPSOCKET_CONNECTED:
        tcp_ready = 1;
        break;

    case TCPSOCKET_READABLE: //Incoming data
        tcp_readable = 1;
        break;

    case TCPSOCKET_WRITEABLE: //We can send data
        tcp_writable = 1;
        break;

    case TCPSOCKET_CONTIMEOUT:
    case TCPSOCKET_CONRST:
    case TCPSOCKET_CONABRT:
    case TCPSOCKET_ERROR:
    case TCPSOCKET_DISCONNECTED:
        tcp_ready = 0;
        break;
    }
}

int wait_smtp (int code) {
    Timer timeout;
    int i;
    char buf[1500];

    // wait responce
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_readable) break;
        Net::poll();
    }
    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);
#endif

    // check return code
    if (atoi(buf) == code) return 0;

    return -1;
}

void isr_dns (DNSReply r) {

#ifdef DEBUG
    printf("dns(%d)\r\n", r);
#endif
    if (DNS_FOUND) {
        dns_status = 1;
    } else {
        dns_status = -1;
    }
}

int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd) {
    TCPSocketErr err;
    Timer timeout;
    int ret = -1;

    smtp = new TCPSocket;
    tcp_ready = 0;
    tcp_readable = 0;
    tcp_writable = 0;

    smtp->setOnEvent(isr_smtp);

    // connect
    if (host->getIp().isNull()) {
        DNSRequest dns;
        dns_status = 0;
        dns.setOnReply(isr_dns);
        if (dns.resolve(host) != DNS_OK) goto exit;
        timeout.reset();
        timeout.start();
        while (timeout.read_ms() < SMTP_TIMEOUT) {
            if (dns_status) break;
            Net::poll();
        }
        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
    timeout.reset();
    timeout.start();
    while (timeout.read_ms() < SMTP_TIMEOUT) {
        if (tcp_ready) break;
        Net::poll();
    }
    timeout.stop();
    if (! tcp_ready) goto exit;
    if (wait_smtp(220)) goto exit;

    // send request
    wait_ms(100);
    smtp->send("EHLO mbed\r\n", 11);
    if (wait_smtp(250)) goto exit;

    if (user && pwd) {
        // smtp auth
        char tmp[80], buf[100];
        int len;
        snprintf(tmp, sizeof(tmp), "%s%c%s%c%s", user, 0, user, 0, pwd);
        len = strlen(user) * 2 + strlen(pwd) + 2;
        base64enc(tmp, len, buf, sizeof(buf));
        smtp->send("AUTH PLAIN ", 11);
        smtp->send(buf, strlen(buf));
        smtp->send("\r\n", 2);
        if (wait_smtp(235)) goto quit;
    }

    smtp->send("MAIL FROM: ", 11);
    smtp->send(from, strlen(from));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("RCPT TO: ", 9);
    smtp->send(to, strlen(to));
    smtp->send("\r\n", 2);
    if (wait_smtp(250)) goto quit;

    smtp->send("DATA\r\n", 6);
    if (wait_smtp(354)) goto quit;

    // mail data
    smtp->send(data, strlen(data));
    smtp->send("\r\n.\r\n", 5);
    if (wait_smtp(250)) goto quit;
    ret = 0;

quit:
    smtp->send("QUIT\r\n", 6);
    if (wait_smtp(221)) goto exit;

exit:
    smtp->resetOnEvent();
    smtp->close();
    delete smtp;

    return ret;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx TinySMTP.h XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

/*
 * mbed Tiny SMTP Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny SMTP Client
 */

#ifndef TinySMTP_h
#define TinySMTP_h

#define DEBUG

#define SMTP_PORT 25
#define SMTP_TIMEOUT 15000 // ms

/** send mail
 * @param to mail address
 * @param from mail address
 * @param data mail body
 * @param host mail server
 * @param data mail body
 * @param user auth username (or NULL)
 * @param pwd auth password (or NULL)
 * @return 0:success, -1:failue
 */
int sendmail (char *to, char *from, char *data, Host *host, char *user, char *pwd);

#endif

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx main.cpp XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "TinySMTP.h"

#define SMTP "mail.domain.name"
#define PORT 587 // or 25
#define FROM "from@domain.name"
#define TO "to@domain.name"
#define USER "authuser"
#define PWD "password"
#define SUBJECT "mail test"
#define BODY "TEST TEST"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
EthernetNetIf eth;

int main () {
    EthernetErr ethErr;
    Host host;
    int r;
    char data[500];

    myled = 1;

    strcpy(data, "From: " FROM "\r\nTo: " TO "\r\n");
    strcat(data, "Subject: " SUBJECT "\r\n\r\n" BODY "\r\n");

    ethErr = eth.setup();
    if(ethErr) {
        return -1;
    }

    host.setName(SMTP);
    host.setPort(PORT);
    r = sendmail(FROM, TO, data, &host, USER, PWD);

    if (r) {
        printf("error\r\n");
    } else {
        printf("sent\r\n");
    }

    myled = 0;
    return 0;
}

XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx EOF XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx