uIP 1.0
smtp.c
/**
 * \addtogroup apps
 * @{
 */

/**
 * \defgroup smtp Отправитель E-mail через SMTP
 * @{
 *
 * Simple Mail Transfer Protocol (SMTP) определен в RFC821 как
 * стандартный способ отправки и передачи e-mail через Интернет.
 * Это простой пример реализации, показывающий, как создавать
 * работу протоколов в uIP. Пример может посылать e-mail,
 * но он не был тщатель но протестирован.
 */

/**
 * \file
 * Пример реализации SMTP
 * \author Adam Dunkels <adam@dunkels.com>
 */

/*
 * Copyright (c) 2004, Adam Dunkels.
 * Все права зарезервированы. *
 * Повторное распространение, использование в исходном и двоичном виде,
 * с модификацией или без - разрешается, если выполняются следующие
 * условия:
 * 1. Распространение исходного кода должно сохранить вышеуказанную пометку
 *    копирайта, этот список условий и следующую правовую оговорку.
 * 2. Распространение исходного кода должно сохранить вышеуказанную пометку
 *    копирайта, этот список условий и следующую правовую оговорку в
 *    документации и/или других материалах, которые будут предоставлены
 *    вместе с распространяемыми материалами.
 * 3. Имя автора не может использоваться, чтобы подтвердить или продвинуть
 *    продукты, написанные с использованием этого программного обеспечения
 *    без специального на то разрешения.
 *
 * ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ АВТОРОМ ``КАК ЕСТЬ'', БЕЗ
 * КАКОЙ-ЛИБО ЛЮБОЙ РАСШИРЕННОЙ ИЛИ ПОДРАЗУМЕВАЕМОЙ ГАРАНТИИ, ВКЛЮЧАЯ,
 * НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ГАРАНТИИ ВЫСОКОГО СПРОСА И ПРИГОДНОСТИ
 * ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. АВТОР НИ ПРИ КАКИХ УСЛОВИЯХ НЕ ОТВЕТСТВЕНЕН
 * ЗА ЛЮБЫЕ УБЫТКИ - ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ОБРАЗЦОВЫЕ
 * ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМ, ТРЕБОВАНИЯ
 * ЗАМЕНЫ ТОВАРА ИЛИ СЕРВИСА; ПОТЕРИ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ВЫГОДЫ;
 * ИЛИ ПРЕКРАЩЕНИЕ БИЗНЕСА), ОДНАКО ВЫЗВАННЫЕ ПО ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ,
 * ЛИБО В КОНТРАКТЕ, ПРЯМОЙ ОТВЕТСТВЕННОСТИ, ЛИБО В НАРУШЕНИИ ЗАКОННЫХ ПРАВ
 * (ВКЛЮЧАЯ ТАК ИЛИ ИНАЧЕ НЕБРЕЖНОСТЬ), ВОЗНИКАЮЩИЕ ВСЕГДА ИЗ ИСПОЛЬЗОВАНИЯ
 * ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, ДАЖЕ ЕСЛИ БЫЛО ПРЕДУПРЕЖДЕНИЕ О ВОЗМОЖНОСТИ
 * ТАКОГО ПОВРЕЖДЕНИЯ.
 *
 * Этот файл является частью стека uIP TCP/IP..
 *
 * Author: Adam Dunkels <adam@sics.se>
 *
 * $Id: smtp.c,v 1.4 2006/06/11 21:46:37 adam Exp $
 */
#include "smtp.h"

#include "smtp-strings.h"
#include "psock.h"
#include "uip.h"

#include <string.h>

static struct smtp_state s;

static char *localhostname;
static uip_ipaddr_t smtpserver;

#define ISO_nl 0x0a
#define ISO_cr 0x0d

#define ISO_period 0x2e

#define ISO_2  0x32
#define ISO_3  0x33
#define ISO_4  0x34
#define ISO_5  0x35


/*---------------------------------------------------------------------------*/
static
PT_THREAD(smtp_thread(void))
{
  PSOCK_BEGIN(&s.psock);

  PSOCK_READTO(&s.psock, ISO_nl);
   
  if(strncmp(s.inputbuffer, smtp_220, 3) != 0) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(2);
    PSOCK_EXIT(&s.psock);
  }
  
  PSOCK_SEND_STR(&s.psock, (char *)smtp_helo);
  PSOCK_SEND_STR(&s.psock, localhostname);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);

  PSOCK_READTO(&s.psock, ISO_nl);
  
  if(s.inputbuffer[0] != ISO_2) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(3);
    PSOCK_EXIT(&s.psock);
  }

  PSOCK_SEND_STR(&s.psock, (char *)smtp_mail_from);
  PSOCK_SEND_STR(&s.psock, s.from);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);

  PSOCK_READTO(&s.psock, ISO_nl);
  
  if(s.inputbuffer[0] != ISO_2) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(4);
    PSOCK_EXIT(&s.psock);
  }

  PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
  PSOCK_SEND_STR(&s.psock, s.to);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);

  PSOCK_READTO(&s.psock, ISO_nl);
  
  if(s.inputbuffer[0] != ISO_2) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(5);
    PSOCK_EXIT(&s.psock);
  }
  
  if(s.cc != 0) {
    PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
    PSOCK_SEND_STR(&s.psock, s.cc);
    PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);

    PSOCK_READTO(&s.psock, ISO_nl);
  
    if(s.inputbuffer[0] != ISO_2) {
      PSOCK_CLOSE(&s.psock);
      smtp_done(6);
      PSOCK_EXIT(&s.psock);
    }
  }
  
  PSOCK_SEND_STR(&s.psock, (char *)smtp_data);
  
  PSOCK_READTO(&s.psock, ISO_nl);
  
  if(s.inputbuffer[0] != ISO_3) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(7);
    PSOCK_EXIT(&s.psock);
  }

  PSOCK_SEND_STR(&s.psock, (char *)smtp_to);
  PSOCK_SEND_STR(&s.psock, s.to);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
  
  if(s.cc != 0) {
    PSOCK_SEND_STR(&s.psock, (char *)smtp_cc);
    PSOCK_SEND_STR(&s.psock, s.cc);
    PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
  }
  
  PSOCK_SEND_STR(&s.psock, (char *)smtp_from);
  PSOCK_SEND_STR(&s.psock, s.from);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
  
  PSOCK_SEND_STR(&s.psock, (char *)smtp_subject);
  PSOCK_SEND_STR(&s.psock, s.subject);
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);

  PSOCK_SEND(&s.psock, s.msg, s.msglen);
  
  PSOCK_SEND_STR(&s.psock, (char *)smtp_crnlperiodcrnl);

  PSOCK_READTO(&s.psock, ISO_nl);
  if(s.inputbuffer[0] != ISO_2) {
    PSOCK_CLOSE(&s.psock);
    smtp_done(8);
    PSOCK_EXIT(&s.psock);
  }

  PSOCK_SEND_STR(&s.psock, (char *)smtp_quit);
  smtp_done(SMTP_ERR_OK);
  PSOCK_END(&s.psock);
}
/*---------------------------------------------------------------------------*/
void
smtp_appcall(void)
{
  if(uip_closed()) {
    s.connected = 0;
    return;
  }
  if(uip_aborted() || uip_timedout()) {
    s.connected = 0;
    smtp_done(1);
    return;
  }
  smtp_thread();
}
/*---------------------------------------------------------------------------*/
/**
 * Указывает сервер SMTP и имя хоста.
 *
 * Эта функция используется для конфигурирования модуля SMTP, при этом
 * задается сервер SMTP и имя хоста.
 *
 * \param lhostname Имя для хоста uIP.
 *
 * \param server Указатель на 4-байтный массив, представляющий адрес IP
 * конфигурируемого сервера SMTP.
 */
void
smtp_configure(char *lhostname, void *server)
{
  localhostname = lhostname;
  uip_ipaddr_copy(smtpserver, server);
}
/*---------------------------------------------------------------------------*/
/**
 * Отправляет e-mail.
 *
 * \param to Адрес получателя e-mail.
 * \param cc Адрес CC (отправка копии): получателей e-mail.
 * \param from Адрес e-mail отправителя.
 * \param subject Тема e-mail.
 * \param msg Само сообщение e-mail.
 * \param msglen The Длина сообщения e-mail.
 */
unsigned char
smtp_send(char *to, char *cc, char *from,
          char *subject, char *msg, u16_t msglen)
{
  struct uip_conn *conn;

  conn = uip_connect(smtpserver, HTONS(25));
  if(conn == NULL) {
    return 0;
  }
  s.connected = 1;
  s.to = to;
  s.cc = cc;
  s.from = from;
  s.subject = subject;
  s.msg = msg;
  s.msglen = msglen;

  PSOCK_INIT(&s.psock, s.inputbuffer, sizeof(s.inputbuffer));
  
  return 1;
}
/*---------------------------------------------------------------------------*/
void
smtp_init(void)
{
  s.connected = 0;
}
/*---------------------------------------------------------------------------*/
/** @} */
/** @} */