#include "AdvancedMail.h"
//#define NDBG //раскомментируйте строку если лог не нужен
AdvancedSmtpClient::AdvancedSmtpClient(){}
/**-----------------Настройки ящика-----------------*/
/*-----------------SMTP серверы-------------------*/
const char AdvancedSmtpClient::SMTP_SERVER_0[] = "smtp.spaceweb.ru"; // замените на адрес вашего сервера
//const char SmtpClient::SMTP_SERVER_1[] = "укажите адрес SMTP сервера";//раскомментируйте строку для добавления SMTP сервера 1
//const char SmtpClient::SMTP_SERVER_2[] = "укажите адрес SMTP сервера";//раскомментируйте строку для добавления SMTP сервера 2
const char * const AdvancedSmtpClient::SMTP_SERVER_SETTINGS[] = { SMTP_SERVER_0
//,SMTP_SERVER_1 //раскомментируйте строку для добавления SMTP сервера 1
//,SMTP_SERVER_2//раскомментируйте строку для добавления SMTP сервера 2
} ;
/*-----------------Порты-----------------*/
const char AdvancedSmtpClient::PORT_0[] = "25"; // замените на ваш порт
//const char SmtpClient::PORT_1[] = "укажите порт для сервера 1"; //раскомментируйте строку для добавления порта для сервера 1
//const char SmtpClient::PORT_2[] = "укажите порт для сервера 2"; //раскомментируйте строку для добавления порта для сервера 2
const char * const AdvancedSmtpClient::PORT_SETTINGS[] = { PORT_0
//,PORT_1 //раскомментируйте строку для добавления порта для сервера 1
//,PORT_2 //раскомментируйте строку для добавления порта для сервера 2
};
/*-----------------Имена пользователей-----------------*/
const char AdvancedSmtpClient::USER_0[] = "c2VuZG1haWxAYXZyZ3VhcmQucnU="; // замените на ваш логин
//const char SmtpClient::USER_1[] = "укажите логин для сервера 1 в кодировке Base64"; //раскомментируйте строку для добавления логина для сервера 1
//const char SmtpClient::USER_2[] = "укажите логин для сервера 2 в кодировке Base64"; //раскомментируйте строку для добавления логина для сервера 2
const char * const AdvancedSmtpClient::USER_SETTINGS[] = { USER_0
//,USER_1 //раскомментируйте строку для добавления логина для сервера 1
//,USER_2 //раскомментируйте строку для добавления логина для сервера 2
};
/*-----------------Пароли-----------------*/
const char AdvancedSmtpClient::PASS_0[] = "dDdONjI1NFk1Knk0V0NW";// замените на ваш пароль
//const char SmtpClient::PASS_1[] = "укажите пароль для сервера 1 в кодировке Base64"; //раскомментируйте строку для добавления пароля для сервера 1
//const char SmtpClient::PASS_2[] = "укажите пароль для сервера 1 в кодировке Base64"; //раскомментируйте строку для добавления пароля для сервера 2
const char * const AdvancedSmtpClient::PASS_SETTINGS[] = { PASS_0
//,PASS_1 //раскомментируйте строку для добавления пароля для сервера 1
//,PASS_2 //раскомментируйте строку для добавления пароля для сервера 1
};
/*-----------------От кого письмо-----------------*/
const char AdvancedSmtpClient::FROM_0[] = "sendmail@avrguard.ru"; // замените на ваш адрес отправителя
//const char SmtpClient::FROM_1[] = "укажите адрес для поля from сервера 1"; //раскомментируйте строку для добавления адреса для поля from сервера 1
//const char SmtpClient::FROM_2[] = "укажите адрес для поля from сервера 2"; //раскомментируйте строку для добавления адреса для поля from сервера 2
const char * const AdvancedSmtpClient::FROM_SETTINGS[] = { FROM_0
//,FROM_1 //раскомментируйте строку для добавления адреса для поля from сервера 1
//,FROM_2 //раскомментируйте строку для добавления адреса для поля from сервера 2
};
/*-----------------Кому письмо-----------------*/
const char AdvancedSmtpClient::TO_0[] = "test@test.com";//"!!!УКАЖИТЕ ЯЩИК ПОЛУЧАТЕЛЯ!!!";
//const char SmtpClient::TO_1[] = "укажите адрес для поля to"; //раскомментируйте строку для добавления адреса для поля to
//const char SmtpClient::TO_2[] = "укажите адрес для поля to"; //раскомментируйте строку для добавления адреса для поля to
const char * const AdvancedSmtpClient::TO_SETTINGS[] = { TO_0
//,TO_1 //раскомментируйте строку для добавления адреса для поля to
//,TO_2 //раскомментируйте строку для добавления адреса для поля to
};
/*-----------------Темы-----------------*/
const char AdvancedSmtpClient::SUBJECT_0[] = "Test subject";
//const char SmtpClient::SUBJECT_1[] = "укажите тему 1"; //раскомментируйте строку для добавления темы 1
//const char SmtpClient::SUBJECT_2[] = "укажите тему 2"; //раскомментируйте строку для добавления темы 2
//const char SmtpClient::SUBJECT_3[] = "укажите тему 3"; //раскомментируйте строку для добавления темы 3
//const char SmtpClient::SUBJECT_4[] = "укажите тему 4"; //раскомментируйте строку для добавления темы 4
const char * const AdvancedSmtpClient::SUBJECT_LIST[] = { SUBJECT_0
//,SUBJECT_1 //раскомментируйте строку для добавления темы 1
//,SUBJECT_2 //раскомментируйте строку для добавления темы 2
//,SUBJECT_3 //раскомментируйте строку для добавления темы 3
//,SUBJECT_4 //раскомментируйте строку для добавления темы 4
};
/*-----------------Текст-----------------*/
const char AdvancedSmtpClient::MESSAGE_0[] = "Test message";
//const char SmtpClient::MESSAGE_1[] = "укажите сообщение 1"; //раскомментируйте строку для добавления сообщения 1
//const char SmtpClient::MESSAGE_2[] = "укажите сообщение 2"; //раскомментируйте строку для добавления сообщения 2
//const char SmtpClient::MESSAGE_3[] = "укажите сообщение 3"; //раскомментируйте строку для добавления сообщения 3
//const char SmtpClient::MESSAGE_4[] = "укажите сообщение 4"; //раскомментируйте строку для добавления сообщения 4
//const char SmtpClient::MESSAGE_5[] = "укажите сообщение 5"; //раскомментируйте строку для добавления сообщения 5
//const char SmtpClient::MESSAGE_6[] = "укажите сообщение 6"; //раскомментируйте строку для добавления сообщения 6
//const char SmtpClient::MESSAGE_7[] = "укажите сообщение 7"; //раскомментируйте строку для добавления сообщения 7
//const char SmtpClient::MESSAGE_8[] = "укажите сообщение 8"; //раскомментируйте строку для добавления сообщения 8
//const char SmtpClient::MESSAGE_9[] = "укажите сообщение 9"; //раскомментируйте строку для добавления сообщения 9
const char * const AdvancedSmtpClient::MESSAGE_LIST[] = { MESSAGE_0
//,MESSAGE_1 //раскомментируйте строку для добавления сообщения 1
//,MESSAGE_2 //раскомментируйте строку для добавления сообщения 2
//,MESSAGE_3 //раскомментируйте строку для добавления сообщения 3
//,MESSAGE_4 //раскомментируйте строку для добавления сообщения 4
//,MESSAGE_5 //раскомментируйте строку для добавления сообщения 5
//,MESSAGE_6 //раскомментируйте строку для добавления сообщения 6
//,MESSAGE_7 //раскомментируйте строку для добавления сообщения 7
//,MESSAGE_8 //раскомментируйте строку для добавления сообщения 8
//,MESSAGE_9 //раскомментируйте строку для добавления сообщения 9
};
bool AdvancedSmtpClient::sendMail(uint8_t boxNum, uint8_t recipientNum, uint8_t subjectNum, uint8_t messageNum){ static uint8_t processStatus = 0;
static char buff[50]; // если есть любая строка (сервер, логин, пароль, адреса, тема или сообщение) более указанной длины (50) увеличить размер буфера до нужной длины.
if (!_client.connected()){ char portBuff[4];
strcpy_P(buff, pgm_read_word_near((int)(SMTP_SERVER_SETTINGS + boxNum)));
strcpy_P(portBuff, pgm_read_word_near((int)(PORT_SETTINGS + boxNum)));
if (_client.connect(buff, atoi(portBuff))){ #ifndef NDBG
Serial.println(F("SimpleMail >> SMTP client connected")); #endif // NDBG
}
else { #ifndef NDBG
Serial.println(F("SimpleMail >> SMTP client connection failed")); #endif // NDBG
}
}
else { switch (processStatus){ case 0:
if (readResponse ()){ if(atoi(_responseCode) == 220 || atoi(_responseCode) == 221){ _client.println(strcpy_P(buff, COMMAND_EHLO));
processStatus = 1;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 1:
if (readResponse ()){ if(atoi(_responseCode) == 250){ _client.println(strcpy_P(buff, COMMAND_AUTHLOGIN));
processStatus = 2;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 2:
if (readResponse ()){ if(atoi(_responseCode) == 334){ _client.println(strcpy_P(buff, pgm_read_word_near((int)(USER_SETTINGS + boxNum))));
processStatus = 3;
}
else{ /*closeConnection(&processStatus, false);
return true;*/
}
}
case 3:
if (readResponse ()){ if(atoi(_responseCode) == 334){ _client.println(strcpy_P(buff, pgm_read_word_near((int)(PASS_SETTINGS + boxNum))));
processStatus = 4;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 4:
if (readResponse ()){ if(atoi(_responseCode) == 235){ strcpy_P(buff, COMMAND_MAILFROM);
_client.print(buff);
_client.println(strcpy_P(buff, pgm_read_word_near((int)(FROM_SETTINGS + boxNum))));
processStatus = 5;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 5:
if (readResponse ()){ if(atoi(_responseCode) == 250){ strcpy_P(buff, COMMAND_MAILTO);
_client.print(buff);
_client.println(strcpy_P(buff, pgm_read_word_near((int)(TO_SETTINGS + recipientNum))));
processStatus = 6;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 6:
if (readResponse ()){ if(atoi(_responseCode) == 250){ strcpy_P(buff, COMMAND_DATA);
_client.println(buff);
processStatus = 7;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 7:
if (readResponse ()){ if(atoi(_responseCode) == 354){ strcpy_P(buff, COMMAND_TO);
_client.print(buff);
_client.println(strcpy_P(buff, pgm_read_word_near((int)(TO_SETTINGS + recipientNum))));
strcpy_P(buff, COMMAND_SUBJECT);
_client.print(buff);
_client.println(strcpy_P(buff, pgm_read_word_near((int)(SUBJECT_LIST + subjectNum))));
_client.println();
_client.println(strcpy_P(buff, pgm_read_word_near((int)(MESSAGE_LIST + messageNum))));
_client.println(F(".")); processStatus = 8;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 8:
if (readResponse ()){ if(atoi(_responseCode) == 250){ strcpy_P(buff, COMMAND_QUIT);
_client.println(buff);
processStatus = 9;
}
else{ closeConnection(&processStatus, false);
return true;
}
}
break;
case 9:
if (readResponse ()){ if(atoi(_responseCode) == 221){ closeConnection(&processStatus, true);
return true;
}
}
break;
default:
Serial.println(F("Zombies rising!")); }
}
return false;
};
bool AdvancedSmtpClient::readResponse (){ if (_client.available()) { static uint8_t n = 0;
#ifndef NDBG
if (!n) Serial.print(F("SMTP SERVER >>")); #endif // NDBG
if (n < 3){ char sym = _client.read();
_responseCode[n] = sym;
#ifndef NDBG
Serial.print(sym);
#endif // NDBG
n++;
return false;
}
else { char sym = _client.read();
#ifndef NDBG
Serial.print(sym);
#endif // NDBG
if (sym == 0x0A){ n = 0;
return true;
}
return false;
}
}
else { return false;
}
};
void AdvancedSmtpClient::closeConnection(uint8_t * p_processStatus, bool status){ * p_processStatus = 0;
_client.flush();
_client.stop();
#ifndef NDBG
if(!_client.connected()) { Serial.println();
if (status) Serial.println(F("SimpleMail >> NO error detected")); else Serial.println(F("SimpleMail >> Error detected")); Serial.println(F("SimpleMail >> SMTP client disconnected")); }
#endif // NDBG
_status = status;
};
bool AdvancedSmtpClient::getStatus(){return _status;};
/**-----------------Команды серверу-----------------*/
const char AdvancedSmtpClient::COMMAND_EHLO[] = "EHLO 127.0.0.1";
const char AdvancedSmtpClient::COMMAND_AUTHLOGIN[] = "AUTH LOGIN";
const char AdvancedSmtpClient::COMMAND_MAILFROM[] = "MAIL From:";
const char AdvancedSmtpClient::COMMAND_MAILTO[] = "RCPT To:";
const char AdvancedSmtpClient::COMMAND_DATA[] = "DATA";
const char AdvancedSmtpClient::COMMAND_SUBJECT[] = "Subject:";
const char AdvancedSmtpClient::COMMAND_TO[] = "To:";
const char AdvancedSmtpClient::COMMAND_QUIT[] = "QUIT";
Александр! День добрый! В примере к библиотеке «SimpleMail» в строчке 25 ошибка при компиляции «‘test’ was not declared in this scope». Если эту строчку заблокировать то код программы загружается но не работоспособен.
День добрый! в примере к библиотеке «SimpleMail» строчка №25 при компиляции выдаёт ошибку «не известная переменная». Как убрать эту ошибку? Заранее спасибо!
Проверю
Евгений! В строке 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 байт.
Присылайте лог. Будем посмотреть
Александр! Заполнил поля (приложено внизу). После отправления 0 в порт пишет:
Try to send mail…
SimpleMail >> SMTP client connection failed
SimpleMail >> SMTP client connected
и все. Сообщение не отправлено. В чем может быть проблема?
#include // подключаем библиотеку SPI
#include // подключаем библиотеку Ethernet
#include // подключаем библиотеку SimpleMail
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };// задаем MAKадрес
IPAddress ip(192, 168, 1, 16);// задаем айпи адрес (проверьте чтобы была корректная подсеть и не было конфликта айпи адресов)
SimpleSmtpClient client; //создаем экземпляр класса SimpleSmtpClient (клиента SMTP)
char smtpServer[] = «smtp.mail.ru»; // указываем адрес сервера
uint16_t port = 465; // указываем порт сервера
char user[] = «ard****erf@mail.ru»; // указываем логин
char pass[] = «Zxc*****Rty$56»; // указываем пароль
char mailto[] = «daf****y@mail.ru»; // указываем адрес получателя
char mailfrom[] = «ard****erf@mail.ru»; // указываем адрес отправителя
char subject[] = «Test subject»; // указываем тему
char message[] = «Test\nmessage»; // указываем текст сообщения
bool flag = false;// создаем флаг для отправки письма
void setup() {
Serial.begin(9600);// инициализируем Serial
Ethernet.begin(mac, ip);// инициализируем Ethernet соединение
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
test();
if (flag) {// если флаг есть — пытаемся отправить письмо
if (client.sendMail(smtpServer,port,user,pass,mailfrom,mailto,subject,message)) {// если сеанс закончен
flag = false;//сбрасываем флаг
if (client.getStatus()) Serial.println(F(«Message sent!»));
else Serial.println(F(«Message not sent!»));
}
}
}
void test() {
if (Serial.available()) {// при приеме из Serial знака 0 переводит flag в true для инициализации отправки письма
byte symbol = Serial.read();
if (symbol == ‘0’) {
Serial.println(F(«Try to send mail…»));
flag = true;
}
}
}
Даниил здравствуйте.
Вы пытаетесь установить соединение с сервером по 465 порту, который использует шифрование (SSL/TLS)
Данная библиотека не поддерживает режим работы с шифрованием, т.к. у ардуинки мало памяти. Вам нужно найти почтовый сервис или хостинг с почтой, с возможностью работы с открытым SMTP (например по порту 25).
Есть ли какой-то способ переделать, с поддержкой шифрования, очень хотелось бы использовать именно mail.ru
И еще вопрос, если нельзя переработать, то какой почтовый сервис выбрать
В течении 2 часов искал другую почту. Вот что вышло:
Try to send mail…
SimpleMail >> SMTP client connected
SMTP SERVER >>220 smtp.ngs.ru ESMTP ready
SMTP SERVER >>250-smtp.ngs.ru
SMTP SERVER >>250-SIZE 50000000
SMTP SERVER >>250-ETRN
SMTP SERVER >>250-ENHANCEDSTATUSCODES
SimpleMail >> Error detected
SimpleMail >> SMTP client disconnected
Message not sent!
В чем может быть ошибка?
Еще чуток покопался и получил такой результат: (опять вернулся на mail.ru)
Try to send mail…
SimpleMail >> SMTP client connected
SMTP SERVER >>220 smtp3.mail.ru ESMTP ready (Looking for Mail for your domain? Visit https://biz.mail.ru)
SMTP SERVER >>250-smtp3.mail.ru
SMTP SERVER >>250-SIZE 73400320
SMTP SERVER >>250-8BITMIME
SMTP SERVER >>250-PIPELINING
SMTP SERVER >>250 STARTTLS
SMTP SERVER >>500 AUTH available only with SSL or TLS
SimpleMail >> Error detected
SimpleMail >> SMTP client disconnected
Message not sent!
Даниил! Вы опять соединяетесь с сервером с ШИФРОВАНИЕМ!
К сожалению, нет возможности реализовать шифрование на простой ардуинке. Нужно использовать другую плату, либо одеть на плату Dragino Yun shield и действовать через OpenVPN, например использовать программу xmail или что-то подобное.
Я не могу понять что я не так делаю. Мне нужно использовать другой адрес сервера или вообще другую почту или что-то другое. Не могли бы вы предоставить пример, где нужно будет заменить лишь email и пароль, а то я не сильно много в этом понимаю если честно…
Даниил, нужно найти | купить | организовать хостинг где есть поддержка почтового сервера БЕЗ шифрования. Найти очень сложно, т.к. все гиганты почты уже давно используют шифрование. Если данная услуга нужна вам для множества проектов или для себя — проще купить. Я писал в посте что данная услуга обходится приблизительно в 600 р/год.
прошу помощи. авторизация судя по логу проходит, но потом неизвестная команда.
Try to send mail…
SimpleMail >> SMTP client connected
SMTP SERVER >>220 **********************************************************************
SMTP SERVER >>250-v********g.ru Hello 127.0.0.1 [8*****2]
SMTP SERVER >>250-SIZE 52428800
SMTP SERVER >>250-8BITMIME
SMTP SERVER >>250-PIPELINING
SMTP SERVER >>250-AUTH LOGIN PLAIN
SMTP SERVER >>250-XXXXXXXA
SMTP SERVER >>250 XXXB
SMTP SERVER >>334 VXNlcm5hbWU6
SMTP SERVER >>334 UGFzc3dvcmQ6
SMTP SERVER >>235 Authentication succeeded
SMTP SERVER >>250 OK
SMTP SERVER >>250 Accepted
SMTP SERVER >>500 unrecognized command
SimpleMail >> Error detected
SimpleMail >> SMTP client disconnected
Message not sent!
cepzik, здравствуйте. Данная библиотека была написана под стандартные команды большинства оставшихся почтовых серверов. Возможно ваш сервер требует ещё каких-то команд. Доступа к нему у меня нет. Не знаю в какой степени вы можете «пообщаться» с сервером через telnet. Если у вас получится — попробуйте отправить письмо в ручную. Именно так я и делал прежде чем написать библиотеку. Я в свою очередь, как будет время, попробую по логам посмотреть в каком месте возникает ошибка.
для reg.ru:
в SimpleMail.cpp
закомментировать строки 137-141 и 241
Спасибо за тест! Рад если вам помогли мои скромные труды)
Не подскажете почтовый сервис, который будет отправлять сообщения без лишних манипуляций?
Илья, здравствуйте. Вот ссылка на сервис, сразу на страницу с почтой.
Я использовал его.
Спасибо!
Здравствуйте, при отправке почты отправитель подписывается как MAILER-DAEMON, делал как вы через sweb, не знаете с чем может быть связано?
Возможно сервер не корректно обрабатывает команду MAIL From:
Александр, привет!
соединяюсь с SMTP сервером девайсом GPRS DTU (rs485-GPRS) по TCP/IP(вместо SIM800C GPRS/GSM Shield for Arduino), Ардуино кидает данные через девайс(GPRS DTU) на TCP/IP сервер, но нужно посылать Email… Т.е. мне не надо «bool SimpleSmtpClient::sendMail(char * smtpServer, uint16_t port,), а надо авторизоваться на SMTP сервере(с которым уже произошло соединение на аппаратном уровне) и послать мейл по Serial1.write или Serial1.print… Это реализуемо?? Спасибо!
Алексей, в настоящее время все общественные, да и не только, серверы используют авторизацию через tls / ssl. Если ваше устройство обладает достаточным количеством оперативной памяти — можно использовать, например, библиотеку OpenSSL для авторизации, а далее по протоколу smtp отправляем письмо.
Спасибо, Александр!
Но боюсь, я плохо объяснил суть задачи…
Почту поднял свою, без шифрования (hMailServer);
ардуино(вернее , ESP8266) соединяю с GPRS передатчиком (GPRS DTU ) через COM-rs485-GPRS DTU ;
ардуино должен послать почту на hMailServer через Serial…
И я не понимаю, каким образом авторизоваться на SMTP hMailServer …, т.е. какие команды «кидать» в Serial