Отправка почты с помощью ARDUINO.

В этом посте я представлю вашему вниманию две библиотеки для отправки почты с ардуино. Все началось с того, что мне понадобилось отправлять некоторые данные с ардуино при наступлении определенного события. Рассматривался вариант отправки СМС с SIM900, но СМСки платные, а интернет все равно оплачен и к тому-же, на любом смартфоне есть возможность принимать почту. Таким образом я остановился на почте. Отправка почты с ардуино оказалась делом не сложным. Однако выяснилось что все крупные монополисты в области почты (Яндекс, Гуголь и Мэйл) перешли на защищенные TLS соединения (в целях обеспечения вашей безопасности…:). К сожалению простая ардуинка не может устанавливать такие соединения в виду малого количества памяти. В связи с этим, для отправки почты с ардуино я решил поискать хостеров предоставляющих за разумные деньги почтовый хостинг с возможностью отправки почты по открытому каналу. Таких нашлось не мало. 10 ящиков + 1ГБ места + домен от одного из таких хостеров на год мне обошлись в 600 руб, что я думаю не очень большие деньги. Проверив возможность отправки почты через telnet я приступил к написанию библиотеки. Сразу оговорюсь что я не очень люблю беспроводные технологии, а больше уважаю провода. Поэтому библиотеки написаны под шилд Ethernet Shield W5100 и ему подобные использующие в своей работе библиотеку Ethernet. Обе библиотеки написаны без Delay() и не замедляют работу контроллера.


Итак, первая библиотека для отправки почты с помощью arduino – SimpleMail. Она требует от пользователя минимум знаний в области программирования, логин и пароль указываются стандартным способом. Далее, используя стороннюю библиотеку rBase64, логин и пароль кодируются по алгоритму Base64 для обеспечения авторизации. В PROGMEM упрятаны только только команды серверу. Исходя из вышесказанного данная библиотека отъедает прилично оперативки, но для тех кому это не принципиально – пойдет. Отправка письма осуществляется передачей в метод sendMail строк с указанными параметрами.


Вторая библиотека AdvancedMail в настройке сложнее. Все что можно: команды серверу, настройки сервера, логины, пароли, темы, сообщения и адреса хранятся в PROGMEM. Пароли и логины необходимо сначала закодировать по алгоритму Base64 сторонними способами. Сейчас в сети много онлайн-сервисов позволяющих это сделать. Например base64.ru. После этого закодированные строки необходимо вставить в файл .cpp библиотеки. Таким образом мы сильно экономим драгоценную оперативку. В библиотеке AdvancedMail для отправки почты с ардуино есть заготовки под 3 ящика, 3х адресатов, 5ти тем и 10 сообщений. Если вам необходимо больше – дописывайте. Отправка письма осуществляется передачей в метод sendMail интов с номером ящика, адреса, темы и сообщения.


Для проверки я создал (временно!) почтовый ящик который позволит вам отправлять тестовые сообщения в целях проверки. Все настройки, кроме адреса получателя уже сделаны. Не забудьте указать свой адрес получателя!!! Так же предусмотрен лог сообщений сервера для возможности отслеживания ошибок.

Чуть позднее запишу видео с демонстрацией работы библиотек.
Если есть вопросы – пишите в комментариях.
Пожалуйста не поленитесь и оцените пост!

Библиотека SimpleMail для отправки почты с ARDUINO

Страница библиотеки

Текущая версия: 0.0.1 / 2018.12.12
Предыдущие версии:

Size: 8 KB
Version: 0.0.1

Библиотека AdvancedMail для отправки почты с ARDUINO

Страница библиотеки

Текущая версия: 0.0.1 / 2018.12.12
Предыдущие версии:

Size: 6 KB
Version: 0.0.1



SimpleMail.h

  1. #ifndef SimpleMail_h
  2. #define SimpleMail_h
  3.  
  4. #include "Arduino.h"
  5. #include "Ethernet.h"
  6. #include "rBase64.h"
  7. #include <avr\pgmspace.h>
  8.  
  9. class SimpleSmtpClient {
  10. public:
  11.     SimpleSmtpClient();
  12.     bool sendMail(  char * smtpServer, uint16_t port, char * username, char * password, char * mailfrom, char * mailto, char * subject, char * message);
  13.     /* sendMail(  char * smtpServer, uint16_t port, char * username, char * password, char * mailfrom, char * mailto, char * subject, char * message);
  14.        Соединяется с сервером, пытатеся отправить письмо
  15.  
  16.        Принимаемые параметы:
  17.         char * smtpServer - адрес сервера,
  18.         uint16_t port - порт сервера,
  19.         char * username - логин,
  20.         char * password - пароль,
  21.         char * mailfrom - адрес отправителя,
  22.         char * mailto - адрес получателя,
  23.         char * subject - тема письма,
  24.         char * message - текст сообщения
  25.  
  26.         Возвращаемые значения:
  27.         false - идет отправка письма
  28.         true - попытка отправки завершена. Статус отправки проверяется методом getStatus()
  29.     */
  30.     bool getStatus();
  31.     /* getStatus() статус завершенного сеанса отправки письма
  32.         Возвращаемые значения:
  33.         false - сеанс завершен с ошибкой, письмо не отправлено
  34.         true - сеанс завершен успешно, письмо отправлено
  35.     */
  36. private:
  37.    /*Команды передаваемые серверу сохранены в PROGMEM для экономии оперативной памяти*/
  38.     static const char COMMAND_EHLO[]        PROGMEM;
  39.     static const char COMMAND_AUTHLOGIN[]   PROGMEM;
  40.     static const char COMMAND_MAILFROM[]    PROGMEM;
  41.     static const char COMMAND_MAILTO[]      PROGMEM;
  42.     static const char COMMAND_DATA[]        PROGMEM;
  43.     static const char COMMAND_SUBJECT[]     PROGMEM;
  44.     static const char COMMAND_TO[]          PROGMEM;
  45.     static const char COMMAND_QUIT[]        PROGMEM;
  46.  
  47.  
  48.  
  49.     EthernetClient  _client;
  50.     char _responseCode[3];
  51.     bool _status;
  52.     bool readResponse ();
  53.     void closeConnection(uint8_t * p_processStatus, bool status);
  54. };
  55.  
  56. #endif

SimpleMail.cpp


  1. #include "SimpleMail.h"
  2. //#define NDBG // если лог не нужен - раскомментировать стоку
  3. SimpleSmtpClient::SimpleSmtpClient(){}
  4.  
  5. bool SimpleSmtpClient::sendMail(
  6.                           char * smtpServer,
  7.                           uint16_t port,
  8.                           char * username,
  9.                           char * password,
  10.                           char * mailfrom,
  11.                           char * mailto,
  12.                           char * subject,
  13.                           char * message)
  14.                           {
  15.     static uint8_t processStatus = 0;
  16.    if (!_client.connected()){
  17.         if (_client.connect(smtpServer, port)){
  18.             #ifndef NDBG
  19.             Serial.println(F("SimpleMail >> SMTP client connected"));
  20.             #endif // NDBG
  21.         }
  22.         else {
  23.             #ifndef NDBG
  24.             Serial.println(F("SimpleMail >> SMTP client connection failed"));
  25.             #endif // NDBG
  26.         }
  27.     }
  28.     else{
  29.         switch (processStatus){
  30.             case 0:
  31.                 if (readResponse ()){
  32.                 if(atoi(_responseCode) == 220 || atoi(_responseCode) == 221 ){
  33.                     char buff[14];
  34.                     strcpy_P(buff, COMMAND_EHLO);
  35.                     _client.println(buff);
  36.                     processStatus = 1;
  37.                 }
  38.                 else{
  39.                     closeConnection(&processStatus, false);
  40.                     return true;
  41.                 }
  42.             }
  43.             break;
  44.             case 1:
  45.                 if (readResponse ()){
  46.                 if(atoi(_responseCode) == 250){
  47.                     char buff[10];
  48.                     strcpy_P(buff, COMMAND_AUTHLOGIN);
  49.                     _client.println(buff);
  50.                     processStatus = 2;
  51.                 }
  52.                 else{
  53.                     closeConnection(&processStatus, false);
  54.                     return true;
  55.                 }
  56.             }
  57.             break;
  58.             case 2:
  59.                 if (readResponse ()){
  60.                 if(atoi(_responseCode) == 334){
  61.                     rbase64.encode(username);
  62.                     _client.println(rbase64.result());
  63.                     processStatus = 3;
  64.                 }
  65.                 else{
  66.                     /*closeConnection(&processStatus, false);
  67.                     return true;*/
  68.                 }
  69.             }
  70.             case 3:
  71.                 if (readResponse ()){
  72.                 if(atoi(_responseCode) == 334){
  73.                     rbase64.encode(password);
  74.                     _client.println(rbase64.result());
  75.                     processStatus = 4;
  76.                 }
  77.                 else{
  78.                     closeConnection(&processStatus, false);
  79.                     return true;
  80.                 }
  81.             }
  82.             break;
  83.             case 4:
  84.                 if (readResponse ()){
  85.                 if(atoi(_responseCode) == 235){
  86.                     char buff[10];
  87.                     strcpy_P(buff, COMMAND_MAILFROM);
  88.                     _client.print(buff);
  89.                     _client.println(mailfrom);
  90.                     processStatus = 5;
  91.                 }
  92.                 else{
  93.                     closeConnection(&processStatus, false);
  94.                     return true;
  95.                 }
  96.             }
  97.             break;
  98.             case 5:
  99.                 if (readResponse ()){
  100.                 if(atoi(_responseCode) == 250){
  101.                     char buff[8];
  102.                     strcpy_P(buff, COMMAND_MAILTO);
  103.                     _client.print(buff);
  104.                     _client.println(mailto);
  105.                     processStatus = 6;
  106.                 }
  107.                 else{
  108.                     closeConnection(&processStatus, false);
  109.                     return true;
  110.                 }
  111.             }
  112.             break;
  113.             case 6:
  114.                 if (readResponse ()){
  115.                 if(atoi(_responseCode) == 250){
  116.                     char buff[8];
  117.                     strcpy_P(buff, COMMAND_DATA);
  118.                     _client.println(buff);
  119.                     processStatus = 7;
  120.                 }
  121.                 else{
  122.                     closeConnection(&processStatus, false);
  123.                     return true;
  124.                 }
  125.             }
  126.             break;
  127.             case 7:
  128.                 if (readResponse ()){
  129.                 if(atoi(_responseCode) == 354){
  130.                     {   char buff[3];
  131.                         strcpy_P(buff, COMMAND_TO);
  132.                         _client.print(buff);
  133.                     }
  134.                     _client.println(mailto);
  135.                     {   char buff[8];
  136.                         strcpy_P(buff, COMMAND_SUBJECT);
  137.                         _client.print(buff);
  138.                     }
  139.                     _client.println(subject);
  140.                     _client.println();
  141.                     _client.println(message);
  142.                     _client.println(F("."));
  143.                     processStatus = 8;
  144.                 }
  145.                 else{
  146.                     closeConnection(&processStatus, false);
  147.                     return true;
  148.                 }
  149.             }
  150.             break;
  151.             case 8:
  152.                 if (readResponse ()){
  153.                 if(atoi(_responseCode) == 250){
  154.                     char buff[4];
  155.                     strcpy_P(buff, COMMAND_QUIT);
  156.                     _client.println(buff);
  157.                     processStatus = 9;
  158.  
  159.                 }
  160.                 else{
  161.                     closeConnection(&processStatus, false);
  162.                     return true;
  163.                 }
  164.             }
  165.             break;
  166.             case 9:
  167.                 if (readResponse ()){
  168.                     if(atoi(_responseCode) == 221){
  169.                     closeConnection(&processStatus, true);
  170.                     return true;
  171.                     }
  172.                 }
  173.             break;
  174.             default:
  175.                 Serial.println(F("Zombies rising!"));
  176.         }
  177.     }
  178.     return false;
  179. };
  180.  
  181. bool SimpleSmtpClient::readResponse (){
  182.     if (_client.available()) {
  183.         static uint8_t n = 0;
  184.         #ifndef NDBG
  185.         if (!n) Serial.print(F("SMTP SERVER >>"));
  186.         #endif // NDBG
  187.         if (n < 3){
  188.             char sym = _client.read();
  189.             _responseCode[n] = sym;
  190.             #ifndef NDBG
  191.             Serial.print(sym);
  192.             #endif // NDBG
  193.             n++;
  194.             return false;
  195.         }
  196.         else {
  197.             char sym = _client.read();
  198.             #ifndef NDBG
  199.             Serial.print(sym);
  200.             #endif // NDBG
  201.             if (sym == 0x0A){
  202.                 n = 0;
  203.                 return true;
  204.             }
  205.             return false;
  206.         }
  207.     }
  208.     else {
  209.         return false;
  210.     }
  211. };
  212. void SimpleSmtpClient::closeConnection(uint8_t * p_processStatus, bool status){
  213.     * p_processStatus = 0;
  214.     _client.flush();
  215.     _client.stop();
  216.     #ifndef NDBG
  217.     if(!_client.connected()) {
  218.         Serial.println();
  219.         if (status) Serial.println(F("SimpleMail >> NO error detected"));
  220.         else Serial.println(F("SimpleMail >> Error detected"));
  221.         Serial.println(F("SimpleMail >> SMTP client disconnected"));
  222.     }
  223.     #endif // NDBG
  224.     _status = status;
  225. };
  226. bool SimpleSmtpClient::getStatus(){return _status;};
  227. /**-----------------Команды серверу-----------------*/
  228. const char SimpleSmtpClient::COMMAND_EHLO[] = "EHLO 127.0.0.1";
  229. const char SimpleSmtpClient::COMMAND_AUTHLOGIN[] = "AUTH LOGIN";
  230. const char SimpleSmtpClient::COMMAND_MAILFROM[] = "MAIL From:";
  231. const char SimpleSmtpClient::COMMAND_MAILTO[] = "RCPT To:";
  232. const char SimpleSmtpClient::COMMAND_DATA[] = "DATA";
  233. const char SimpleSmtpClient::COMMAND_SUBJECT[] = "Subject:";
  234. const char SimpleSmtpClient::COMMAND_TO[] = "To:";
  235. const char SimpleSmtpClient::COMMAND_QUIT[] = "QUIT";

Пример использования

  1. #include <SPI.h>// подключаем библиотеку SPI
  2. #include <Ethernet.h>// подключаем библиотеку Ethernet
  3. #include <SimpleMail.h>// подключаем библиотеку SimpleMail
  4.  
  5. uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };// задаем MAKадрес
  6. IPAddress ip(192, 168, 0, 77);// задаем айпи адрес (проверьте чтобы была корректная подсеть и не было конфликта айпи адресов)
  7. SimpleSmtpClient client; //создаем экземпляр класса SimpleSmtpClient (клиента SMTP)
  8.  
  9. char smtpServer[] = "smtp.spaceweb.ru"; // указываем адрес сервера
  10. uint16_t port = 25; // указываем порт сервера
  11. char user[] = "sendmail@avrguard.ru"; // указываем логин
  12. char pass[] = "t7N6254Y5*y4WCV"; // указываем пароль
  13. char mailto[] = "Укажите ваш адрес получателя"; // указываем адрес получателя
  14. char mailfrom[] = "sendmail@avrguard.ru"; // указываем адрес отправителя
  15. char subject[] = "Test subject"; // указываем тему
  16. char message[] = "Test\nmessage"; // указываем текст сообщения
  17. bool flag = false;// создаем флаг для отправки письма
  18. void setup() {
  19.   Serial.begin(9600);// инициализируем Serial
  20.   Ethernet.begin(mac, ip);// инициализируем Ethernet соединение
  21.   delay(1000);
  22. }
  23. void loop() {
  24.   // put your main code here, to run repeatedly:
  25. test();
  26.  if (flag) {// если флаг есть - пытаемся отправить письмо
  27.   if (client.sendMail(smtpServer,port,user,pass,mailfrom,mailto,subject,message)) {// если сеанс закончен
  28.       flag = false;//сбрасываем флаг
  29.       if (client.getStatus()) Serial.println(F("Message sent!"));
  30.       else Serial.println(F("Message not sent!"));
  31.     }
  32.   }
  33. }
  34. void test() {
  35.   if (Serial.available()) {// при приеме из Serial знака 0 переводит flag в true для инициализации отправки письма
  36.     byte symbol = Serial.read();
  37.     if (symbol == '0') {
  38.       Serial.println(F("Try to send mail..."));
  39.       flag = true;
  40.     }
  41.   }
  42. }

AdvancedMail.h

  1. #ifndef AdvancedMail_h
  2. #define AdvancedMail_h
  3.  
  4. #include "Arduino.h"
  5. #include "Ethernet.h"
  6. #include <avr\pgmspace.h>
  7.  
  8. class AdvancedSmtpClient {
  9. public:
  10.     AdvancedSmtpClient();
  11.     bool sendMail(uint8_t boxNum, uint8_t recipientNum, uint8_t subjectNum, uint8_t messageNum);
  12.     /* sendMail(uint8_t boxNum, uint8_t recipientNum, uint8_t subjectNum, uint8_t messageNum)
  13.        Соединяется с сервером, пытатеся отправить письмо
  14.  
  15.        Принимаемые параметы:
  16.        uint8_t boxNum - номер с настройками сервера, куда входят:
  17.             SMTP_SERVER_N
  18.             PORT_N
  19.             USER_N
  20.             PASS_N
  21.             FROM_N
  22.         uint8_t recipientNum - номер адреса получателя, куда входит:
  23.             TO_N
  24.         uint8_t subjectNum - номер темы, куда входит:
  25.             SUBJECT_N
  26.         uint8_t messageNum - номер сообщения, куда входит:
  27.             MESSAGE_N
  28.  
  29.  
  30.         Возвращаемые значения:
  31.         false - идет отправка письма
  32.         true - попытка отправки завершена. Статус отправки проверяется методом getStatus()
  33.     */
  34.     bool getStatus();
  35.     /* getStatus() статус завершенного сеанса отправки письма
  36.         Возвращаемые значения:
  37.         false - сеанс завершен с ошибкой, письмо не отправлено
  38.         true - сеанс завершен успешно, письмо отправлено
  39.     */
  40. private:
  41.  
  42.  
  43. /**------------------------------Настройки почты начало--------------------------*/
  44.  
  45.     /*-----------------SMTP серверы-----------------*/
  46.     static const char SMTP_SERVER_0[]        PROGMEM;
  47.     //static const char SMTP_SERVER_1[]        PROGMEM;//раскомментируйте строку для добавления SMTP сервера 1
  48.     //static const char SMTP_SERVER_2[]         PROGMEM;//раскомментируйте строку для добавления SMTP сервера 2
  49.  
  50.     static const char * const SMTP_SERVER_SETTINGS[] PROGMEM;
  51.  
  52.     /*-----------------Порты-----------------*/
  53.     static const char PORT_0[]             PROGMEM;
  54.     //static const char PORT_1[]             PROGMEM;//раскомментируйте строку для добавления порта для сервера 1
  55.     //static const char PORT_2[]               PROGMEM;//раскомментируйте строку для добавления порта для сервера 2
  56.  
  57.     static const char * const PORT_SETTINGS[] PROGMEM;
  58.  
  59.     /*-----------------Имена пользователей-----------------*/
  60.     static const char USER_0[]               PROGMEM;
  61.     //static const char USER_1[]               PROGMEM;//раскомментируйте строку для добавления логина для сервера 1
  62.     //static const char USER_2[]               PROGMEM;//раскомментируйте строку для добавления логина для сервера 2
  63.  
  64.     static const char * const USER_SETTINGS[] PROGMEM;
  65.  
  66.     /*-----------------Пароли-----------------*/
  67.     static const char PASS_0[]               PROGMEM;
  68.     //static const char PASS_1[]               PROGMEM;//раскомментируйте строку для добавления пароля для сервера 1
  69.     //static const char PASS_2[]               PROGMEM;//раскомментируйте строку для добавления пароля для сервера 2
  70.  
  71.     static const char * const PASS_SETTINGS[] PROGMEM;
  72.  
  73.     /*-----------------От кого письмо-----------------*/
  74.     static const char FROM_0[]               PROGMEM;
  75.     //static const char FROM_1[]               PROGMEM;//раскомментируйте строку для добавления адреса для поля from сервера 1
  76.     //static const char FROM_2[]               PROGMEM;//раскомментируйте строку для добавления адреса для поля from сервера 2
  77.  
  78.     static const char * const FROM_SETTINGS[] PROGMEM;
  79.  
  80.     /*-----------------Кому письмо-----------------*/
  81.     static const char TO_0[]               PROGMEM;
  82.     //static const char TO_1[]               PROGMEM;//раскомментируйте строку для добавления адреса для поля to 1
  83.     //static const char TO_2[]               PROGMEM;//раскомментируйте строку для добавления адреса для поля to 2
  84.  
  85.     static const char * const TO_SETTINGS[] PROGMEM;
  86.  
  87.     /*-----------------Темы-----------------*/
  88.     static const char SUBJECT_0[]        PROGMEM;
  89.     //static const char SUBJECT_1[]        PROGMEM;//раскомментируйте строку для добавления темы 1
  90.     //static const char SUBJECT_2[]        PROGMEM;//раскомментируйте строку для добавления темы 2
  91.     //static const char SUBJECT_3[]        PROGMEM;//раскомментируйте строку для добавления темы 3
  92.     //static const char SUBJECT_4[]        PROGMEM;//раскомментируйте строку для добавления темы 4
  93.  
  94.     static const char * const SUBJECT_LIST[] PROGMEM;
  95.  
  96.     /*-----------------Текст-----------------*/
  97.     static const char MESSAGE_0[]        PROGMEM;
  98.     //static const char MESSAGE_1[]        PROGMEM;//раскомментируйте строку для добавления сообщения 1
  99.     //static const char MESSAGE_2[]        PROGMEM;//раскомментируйте строку для добавления сообщения 2
  100.     //static const char MESSAGE_3[]        PROGMEM;//раскомментируйте строку для добавления сообщения 3
  101.     //static const char MESSAGE_4[]        PROGMEM;//раскомментируйте строку для добавления сообщения 4
  102.     //static const char MESSAGE_5[]        PROGMEM;//раскомментируйте строку для добавления сообщения 5
  103.     //static const char MESSAGE_6[]        PROGMEM;//раскомментируйте строку для добавления сообщения 6
  104.     //static const char MESSAGE_7[]        PROGMEM;//раскомментируйте строку для добавления сообщения 7
  105.     //static const char MESSAGE_8[]        PROGMEM;//раскомментируйте строку для добавления сообщения 8
  106.     //static const char MESSAGE_9[]        PROGMEM;//раскомментируйте строку для добавления сообщения 9
  107.  
  108.     static const char * const MESSAGE_LIST[] PROGMEM;
  109. /**------------------------------Настройки почты окончание--------------------------*/
  110.  
  111.  
  112.  
  113.     EthernetClient  _client;
  114.     char _responseCode[3];
  115.     bool _status;
  116.     bool readResponse ();
  117.     void closeConnection(uint8_t * p_processStatus, bool status);
  118.  
  119.     /*Команды передаваемые серверу сохранены в PROGMEM для экономии оперативной памяти*/
  120.     static const char COMMAND_EHLO[]        PROGMEM;
  121.     static const char COMMAND_AUTHLOGIN[]   PROGMEM;
  122.     static const char COMMAND_MAILFROM[]    PROGMEM;
  123.     static const char COMMAND_MAILTO[]      PROGMEM;
  124.     static const char COMMAND_DATA[]        PROGMEM;
  125.     static const char COMMAND_SUBJECT[]     PROGMEM;
  126.     static const char COMMAND_TO[]          PROGMEM;
  127.     static const char COMMAND_QUIT[]        PROGMEM;
  128. };
  129.  
  130. #endif

AdvancedMail.cpp

  1. #include "AdvancedMail.h"
  2. //#define NDBG //раскомментируйте строку если лог не нужен
  3.  
  4.  
  5. AdvancedSmtpClient::AdvancedSmtpClient(){}
  6.  
  7.     /**-----------------Настройки ящика-----------------*/
  8.  
  9.     /*-----------------SMTP серверы-------------------*/
  10.     const char AdvancedSmtpClient::SMTP_SERVER_0[] = "smtp.spaceweb.ru"; // замените на адрес вашего сервера
  11.     //const char SmtpClient::SMTP_SERVER_1[] = "укажите адрес SMTP сервера";//раскомментируйте строку для добавления SMTP сервера 1
  12.     //const char SmtpClient::SMTP_SERVER_2[] = "укажите адрес SMTP сервера";//раскомментируйте строку для добавления SMTP сервера 2
  13.  
  14.     const char * const AdvancedSmtpClient::SMTP_SERVER_SETTINGS[] = {
  15.         SMTP_SERVER_0
  16.         //,SMTP_SERVER_1 //раскомментируйте строку для добавления SMTP сервера 1
  17.         //,SMTP_SERVER_2//раскомментируйте строку для добавления SMTP сервера 2
  18.     } ;
  19.  
  20.     /*-----------------Порты-----------------*/
  21.     const char AdvancedSmtpClient::PORT_0[] = "25"; // замените на ваш порт
  22.     //const char SmtpClient::PORT_1[] = "укажите порт для сервера 1"; //раскомментируйте строку для добавления порта для сервера 1
  23.     //const char SmtpClient::PORT_2[] = "укажите порт для сервера 2"; //раскомментируйте строку для добавления порта для сервера 2
  24.  
  25.     const char * const AdvancedSmtpClient::PORT_SETTINGS[] = {
  26.         PORT_0
  27.         //,PORT_1   //раскомментируйте строку для добавления порта для сервера 1
  28.         //,PORT_2   //раскомментируйте строку для добавления порта для сервера 2
  29.     };
  30.  
  31.     /*-----------------Имена пользователей-----------------*/
  32.     const char AdvancedSmtpClient::USER_0[] = "c2VuZG1haWxAYXZyZ3VhcmQucnU="; // замените на ваш логин
  33.     //const char SmtpClient::USER_1[] = "укажите логин для сервера 1 в кодировке Base64";   //раскомментируйте строку для добавления логина для сервера 1
  34.     //const char SmtpClient::USER_2[] = "укажите логин для сервера 2 в кодировке Base64";   //раскомментируйте строку для добавления логина для сервера 2
  35.  
  36.     const char * const AdvancedSmtpClient::USER_SETTINGS[] = {
  37.         USER_0
  38.         //,USER_1  //раскомментируйте строку для добавления логина для сервера 1
  39.         //,USER_2  //раскомментируйте строку для добавления логина для сервера 2
  40.     };
  41.  
  42.     /*-----------------Пароли-----------------*/
  43.     const char AdvancedSmtpClient::PASS_0[] = "dDdONjI1NFk1Knk0V0NW";// замените на ваш пароль
  44.     //const char SmtpClient::PASS_1[] = "укажите пароль для сервера 1 в кодировке Base64";  //раскомментируйте строку для добавления пароля для сервера 1
  45.     //const char SmtpClient::PASS_2[] = "укажите пароль для сервера 1 в кодировке Base64";  //раскомментируйте строку для добавления пароля для сервера 2
  46.  
  47.     const char * const AdvancedSmtpClient::PASS_SETTINGS[] = {
  48.         PASS_0
  49.         //,PASS_1   //раскомментируйте строку для добавления пароля для сервера 1
  50.         //,PASS_2   //раскомментируйте строку для добавления пароля для сервера 1
  51.     };
  52.  
  53.     /*-----------------От кого письмо-----------------*/
  54.     const char AdvancedSmtpClient::FROM_0[] = "sendmail@avrguard.ru"; // замените на ваш адрес отправителя
  55.     //const char SmtpClient::FROM_1[] = "укажите адрес для поля from сервера 1";    //раскомментируйте строку для добавления адреса для поля from сервера 1
  56.     //const char SmtpClient::FROM_2[] = "укажите адрес для поля from сервера 2";    //раскомментируйте строку для добавления адреса для поля from сервера 2
  57.  
  58.     const char * const AdvancedSmtpClient::FROM_SETTINGS[] = {
  59.         FROM_0
  60.         //,FROM_1   //раскомментируйте строку для добавления адреса для поля from сервера 1
  61.         //,FROM_2   //раскомментируйте строку для добавления адреса для поля from сервера 2
  62.     };
  63.  
  64.     /*-----------------Кому письмо-----------------*/
  65.     const char AdvancedSmtpClient::TO_0[] = "test@test.com";//"!!!УКАЖИТЕ ЯЩИК ПОЛУЧАТЕЛЯ!!!";
  66.     //const char SmtpClient::TO_1[] = "укажите адрес для поля to"; //раскомментируйте строку для добавления адреса для поля to
  67.     //const char SmtpClient::TO_2[] = "укажите адрес для поля to"; //раскомментируйте строку для добавления адреса для поля to
  68.  
  69.     const char * const AdvancedSmtpClient::TO_SETTINGS[] = {
  70.         TO_0
  71.         //,TO_1   //раскомментируйте строку для добавления адреса для поля to
  72.         //,TO_2   //раскомментируйте строку для добавления адреса для поля to
  73.     };
  74.  
  75.     /*-----------------Темы-----------------*/
  76.     const char AdvancedSmtpClient::SUBJECT_0[] = "Test subject";
  77.     //const char SmtpClient::SUBJECT_1[] = "укажите тему 1";    //раскомментируйте строку для добавления темы 1
  78.     //const char SmtpClient::SUBJECT_2[] = "укажите тему 2";    //раскомментируйте строку для добавления темы 2
  79.     //const char SmtpClient::SUBJECT_3[] = "укажите тему 3";    //раскомментируйте строку для добавления темы 3
  80.     //const char SmtpClient::SUBJECT_4[] = "укажите тему 4";    //раскомментируйте строку для добавления темы 4
  81.  
  82.  
  83.     const char * const AdvancedSmtpClient::SUBJECT_LIST[] = {
  84.         SUBJECT_0
  85.         //,SUBJECT_1    //раскомментируйте строку для добавления темы 1
  86.         //,SUBJECT_2    //раскомментируйте строку для добавления темы 2
  87.         //,SUBJECT_3    //раскомментируйте строку для добавления темы 3
  88.         //,SUBJECT_4    //раскомментируйте строку для добавления темы 4
  89.     };
  90.  
  91.     /*-----------------Текст-----------------*/
  92.     const char AdvancedSmtpClient::MESSAGE_0[] = "Test message";
  93.     //const char SmtpClient::MESSAGE_1[] = "укажите сообщение 1";   //раскомментируйте строку для добавления сообщения 1
  94.     //const char SmtpClient::MESSAGE_2[] = "укажите сообщение 2";   //раскомментируйте строку для добавления сообщения 2
  95.     //const char SmtpClient::MESSAGE_3[] = "укажите сообщение 3";   //раскомментируйте строку для добавления сообщения 3
  96.     //const char SmtpClient::MESSAGE_4[] = "укажите сообщение 4";   //раскомментируйте строку для добавления сообщения 4
  97.     //const char SmtpClient::MESSAGE_5[] = "укажите сообщение 5";   //раскомментируйте строку для добавления сообщения 5
  98.     //const char SmtpClient::MESSAGE_6[] = "укажите сообщение 6";   //раскомментируйте строку для добавления сообщения 6
  99.     //const char SmtpClient::MESSAGE_7[] = "укажите сообщение 7";   //раскомментируйте строку для добавления сообщения 7
  100.     //const char SmtpClient::MESSAGE_8[] = "укажите сообщение 8";   //раскомментируйте строку для добавления сообщения 8
  101.     //const char SmtpClient::MESSAGE_9[] = "укажите сообщение 9";   //раскомментируйте строку для добавления сообщения 9
  102.  
  103.     const char * const AdvancedSmtpClient::MESSAGE_LIST[] = {
  104.         MESSAGE_0
  105.         //,MESSAGE_1    //раскомментируйте строку для добавления сообщения 1
  106.         //,MESSAGE_2    //раскомментируйте строку для добавления сообщения 2
  107.         //,MESSAGE_3    //раскомментируйте строку для добавления сообщения 3
  108.         //,MESSAGE_4    //раскомментируйте строку для добавления сообщения 4
  109.         //,MESSAGE_5    //раскомментируйте строку для добавления сообщения 5
  110.         //,MESSAGE_6    //раскомментируйте строку для добавления сообщения 6
  111.         //,MESSAGE_7    //раскомментируйте строку для добавления сообщения 7
  112.         //,MESSAGE_8    //раскомментируйте строку для добавления сообщения 8
  113.         //,MESSAGE_9    //раскомментируйте строку для добавления сообщения 9
  114.     };
  115.  
  116. bool AdvancedSmtpClient::sendMail(uint8_t boxNum, uint8_t recipientNum, uint8_t subjectNum, uint8_t messageNum){
  117.     static uint8_t processStatus = 0;
  118.     static char buff[50]; // если есть любая строка (сервер, логин, пароль, адреса, тема или сообщение) более указанной длины (50) увеличить размер буфера до нужной длины.
  119.     if (!_client.connected()){
  120.         char portBuff[4];
  121.         strcpy_P(buff, pgm_read_word_near((int)(SMTP_SERVER_SETTINGS + boxNum)));
  122.         strcpy_P(portBuff, pgm_read_word_near((int)(PORT_SETTINGS + boxNum)));
  123.         if (_client.connect(buff, atoi(portBuff))){
  124.             #ifndef NDBG
  125.             Serial.println(F("SimpleMail >> SMTP client connected"));
  126.             #endif // NDBG
  127.         }
  128.         else {
  129.             #ifndef NDBG
  130.             Serial.println(F("SimpleMail >> SMTP client connection failed"));
  131.             #endif // NDBG
  132.         }
  133.     }
  134.     else {
  135.         switch (processStatus){
  136.             case 0:
  137.                 if (readResponse ()){
  138.                     if(atoi(_responseCode) == 220 || atoi(_responseCode) == 221){
  139.                         _client.println(strcpy_P(buff, COMMAND_EHLO));
  140.                         processStatus = 1;
  141.                     }
  142.                     else{
  143.                         closeConnection(&processStatus, false);
  144.                         return true;
  145.                     }
  146.                 }
  147.             break;
  148.             case 1:
  149.                 if (readResponse ()){
  150.                     if(atoi(_responseCode) == 250){
  151.                         _client.println(strcpy_P(buff, COMMAND_AUTHLOGIN));
  152.                         processStatus = 2;
  153.  
  154.                     }
  155.                     else{
  156.                         closeConnection(&processStatus, false);
  157.                         return true;
  158.                     }
  159.                 }
  160.             break;
  161.             case 2:
  162.                 if (readResponse ()){
  163.                     if(atoi(_responseCode) == 334){
  164.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(USER_SETTINGS + boxNum))));
  165.                         processStatus = 3;
  166.                     }
  167.                     else{
  168.                         /*closeConnection(&processStatus, false);
  169.                         return true;*/
  170.                     }
  171.                 }
  172.             case 3:
  173.                 if (readResponse ()){
  174.                     if(atoi(_responseCode) == 334){
  175.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(PASS_SETTINGS + boxNum))));
  176.                         processStatus = 4;
  177.                     }
  178.                     else{
  179.                         closeConnection(&processStatus, false);
  180.                         return true;
  181.                     }
  182.  
  183.                 }
  184.             break;
  185.             case 4:
  186.                 if (readResponse ()){
  187.                     if(atoi(_responseCode) == 235){
  188.                         strcpy_P(buff, COMMAND_MAILFROM);
  189.                         _client.print(buff);
  190.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(FROM_SETTINGS + boxNum))));
  191.                         processStatus = 5;
  192.                     }
  193.                     else{
  194.                         closeConnection(&processStatus, false);
  195.                         return true;
  196.                     }
  197.                 }
  198.             break;
  199.             case 5:
  200.                 if (readResponse ()){
  201.                     if(atoi(_responseCode) == 250){
  202.                         strcpy_P(buff, COMMAND_MAILTO);
  203.                         _client.print(buff);
  204.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(TO_SETTINGS + recipientNum))));
  205.                         processStatus = 6;
  206.                     }
  207.                     else{
  208.                         closeConnection(&processStatus, false);
  209.                         return true;
  210.                     }
  211.                 }
  212.             break;
  213.             case 6:
  214.                 if (readResponse ()){
  215.                     if(atoi(_responseCode) == 250){
  216.                         strcpy_P(buff, COMMAND_DATA);
  217.                         _client.println(buff);
  218.                         processStatus = 7;
  219.                     }
  220.                     else{
  221.                         closeConnection(&processStatus, false);
  222.                         return true;
  223.                     }
  224.                 }
  225.             break;
  226.             case 7:
  227.                 if (readResponse ()){
  228.                     if(atoi(_responseCode) == 354){
  229.                         strcpy_P(buff, COMMAND_TO);
  230.                         _client.print(buff);
  231.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(TO_SETTINGS + recipientNum))));
  232.                         strcpy_P(buff, COMMAND_SUBJECT);
  233.                         _client.print(buff);
  234.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(SUBJECT_LIST + subjectNum))));
  235.                         _client.println();
  236.                         _client.println(strcpy_P(buff, pgm_read_word_near((int)(MESSAGE_LIST + messageNum))));
  237.                         _client.println(F("."));
  238.                         processStatus = 8;
  239.                     }
  240.                     else{
  241.                         closeConnection(&processStatus, false);
  242.                         return true;
  243.                     }
  244.                 }
  245.             break;
  246.             case 8:
  247.                 if (readResponse ()){
  248.                     if(atoi(_responseCode) == 250){
  249.                         strcpy_P(buff, COMMAND_QUIT);
  250.                         _client.println(buff);
  251.                         processStatus = 9;
  252.  
  253.                     }
  254.                     else{
  255.                         closeConnection(&processStatus, false);
  256.                         return true;
  257.                     }
  258.                 }
  259.             break;
  260.             case 9:
  261.                 if (readResponse ()){
  262.                     if(atoi(_responseCode) == 221){
  263.                         closeConnection(&processStatus, true);
  264.                         return true;
  265.                     }
  266.                 }
  267.             break;
  268.             default:
  269.                 Serial.println(F("Zombies rising!"));
  270.         }
  271.     }
  272.     return false;
  273. };
  274. bool AdvancedSmtpClient::readResponse (){
  275.     if (_client.available()) {
  276.         static uint8_t n = 0;
  277.         #ifndef NDBG
  278.         if (!n) Serial.print(F("SMTP SERVER >>"));
  279.         #endif // NDBG
  280.         if (n < 3){
  281.             char sym = _client.read();
  282.             _responseCode[n] = sym;
  283.             #ifndef NDBG
  284.             Serial.print(sym);
  285.             #endif // NDBG
  286.             n++;
  287.             return false;
  288.         }
  289.         else {
  290.             char sym = _client.read();
  291.             #ifndef NDBG
  292.             Serial.print(sym);
  293.             #endif // NDBG
  294.             if (sym == 0x0A){
  295.                 n = 0;
  296.                 return true;
  297.             }
  298.             return false;
  299.         }
  300.     }
  301.     else {
  302.         return false;
  303.     }
  304. };
  305. void AdvancedSmtpClient::closeConnection(uint8_t * p_processStatus, bool status){
  306.     * p_processStatus = 0;
  307.     _client.flush();
  308.     _client.stop();
  309.     #ifndef NDBG
  310.     if(!_client.connected()) {
  311.         Serial.println();
  312.         if (status) Serial.println(F("SimpleMail >> NO error detected"));
  313.         else Serial.println(F("SimpleMail >> Error detected"));
  314.         Serial.println(F("SimpleMail >> SMTP client disconnected"));
  315.     }
  316.     #endif // NDBG
  317.     _status = status;
  318. };
  319. bool AdvancedSmtpClient::getStatus(){return _status;};
  320.  
  321. /**-----------------Команды серверу-----------------*/
  322. const char AdvancedSmtpClient::COMMAND_EHLO[] = "EHLO 127.0.0.1";
  323. const char AdvancedSmtpClient::COMMAND_AUTHLOGIN[] = "AUTH LOGIN";
  324. const char AdvancedSmtpClient::COMMAND_MAILFROM[] = "MAIL From:";
  325. const char AdvancedSmtpClient::COMMAND_MAILTO[] = "RCPT To:";
  326. const char AdvancedSmtpClient::COMMAND_DATA[] = "DATA";
  327. const char AdvancedSmtpClient::COMMAND_SUBJECT[] = "Subject:";
  328. const char AdvancedSmtpClient::COMMAND_TO[] = "To:";
  329. const char AdvancedSmtpClient::COMMAND_QUIT[] = "QUIT";

Пример использования

  1. #include <SPI.h> // подключаем библиотеку SPI
  2. #include <Ethernet.h> // подключаем библиотеку Ethernet
  3. #include <AdvancedMail.h> // подключаем библиотеку AdvancedMail
  4.  
  5. uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // задаем MAKадрес
  6. IPAddress ip(192, 168, 0, 77); // задаем айпи адрес (проверьте чтобы была корректная подсеть и не было конфликта айпи адресов)
  7. AdvancedSmtpClient client; // создаем экземпляр класса AdvancedSmtpClient (клиента SMTP)
  8.  
  9. bool flag = false; // создаем флаг для отправки письма
  10.  
  11. void setup() {
  12.   Serial.begin(9600); // инициализируем Serial
  13.   Ethernet.begin(mac, ip); // инициализируем Ethernet соединение
  14.   delay(1000);
  15. }
  16.  
  17. void loop() {
  18.   test();
  19.    if (flag) {// если флаг есть - пытаемся отправить письмо
  20.     if (client.sendMail(0,0,0,0)){// если сеанс закончен
  21.       flag = false;//сбрасываем флаг
  22.       if (client.getStatus()) Serial.println(F("Message sent!"));
  23.       else Serial.println(F("Message not sent!"));
  24.     }
  25.   }
  26.  
  27. }
  28. void test() {// при приеме из Serial знака 0 переводит flag в true для инициализации отправки письма
  29.   if (Serial.available()) {
  30.     byte symbol = Serial.read();
  31.     if (symbol == '0') {
  32.       Serial.println(F("Try to send message..."));
  33.       flag = true;
  34.     }
  35.   }
  36. }


Оцените пожалуйста статью:

ПечальноТак себеНе плохоХорошоОтличная статья! 2 оценок.
Загрузка...

4 Replies to “Отправка почты с помощью ARDUINO.

  1. Александр! День добрый! В примере к библиотеке “SimpleMail” в строчке 25 ошибка при компиляции “‘test’ was not declared in this scope”. Если эту строчку заблокировать то код программы загружается но не работоспособен.

  2. День добрый! в примере к библиотеке “SimpleMail” строчка №25 при компиляции выдаёт ошибку “не известная переменная”. Как убрать эту ошибку? Заранее спасибо!

    1. Евгений! В строке 25 мы вызываем ФУНКЦИЮ test() ! Там нет переменной. Реализация этой функции описана ниже loop(). У меня все компилируется.
      Вот лог:
      Используем библиотеку SPI версии 1.0 из папки: F:\arduino\DATAArduino\hardware\arduino\avr\libraries\SPI
      Используем библиотеку Ethernet версии 1.1.2 из папки: F:\arduino\DATAArduino\libraries\Ethernet
      Используем библиотеку SimpleMail в папке: F:\arduino\DATAArduino\libraries\SimpleMail (legacy)
      Скетч использует 11288 байт (34%) памяти устройства. Всего доступно 32256 байт.
      Глобальные переменные используют 888 байт (43%) динамической памяти, оставляя 1160 байт для локальных переменных. Максимум: 2048 байт.

      Присылайте лог. Будем посмотреть

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *