• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Отправка почты

AlexTVR

Member
Добрый день!
Домашняя сеть, роутер Микротик раздает интернет по wifi.
NodeMcu клиент (тестовый пример), после подачи питания подключается к wifi, запрашивает удаленный сайт (порт 80), получает ответ, результаты видны в мониторе COM-порта.

Загружаю пример отправки email (SMTP, порт 465), настраиваю свои логины и пароли - отправки не происходит.
Затык возникает при попытке получения ответа от SMTP-сервера - ответа нет, потому происходит выход по тайм-ауту (пробовал с разными серверами - ситуация аналогичная).

Вопрос, почему в первом случае получение данных с удаленного сервера происходит, а во втором - нет?
 

AlexTVR

Member
Спасибо за SSL, но использование другой библиотеки и WiFiClientSecure ничего не дает.
Ошибка та же, вот здесь:

if(!client.connect(SMTP_SERVER, SMTP_PORT)) {
_error = "Could not connect to mail server";
return false;
}

Может микротик что-то не пропускает?
 

Сергей_Ф

Moderator
Команда форума
@AlexTVR скорее вы просто не подключились. Библиотеки для 100% отправки почты по SSL для esp8266 нет, насколько я знаю. Все от почтового сервера зависит.
 

AlexTVR

Member
Кто-нибудь использует ESP8266 для отправки писем из локальной сети? Поделитесь кодом, не могу никак отправить письма.
 

AlexTVR

Member
На чем поднимать почтовый сервер? У меня в режиме ОХРАНА будет работать только ESP8266. Домашний ПК будет выключен.
 

Сергей_Ф

Moderator
Команда форума
@AlexTVR в некоторые роутеры можно поставить. Малинка, апельсинка - решать вам. Современные защищенные протоколы esp8266 не по зубам. Либо арендуйте сервер у провайдера и поставьте туда свой без SSL.
 

AlexTVR

Member
- вот люди шлют письма.
Я бы и не парился, если бы знал, что слать письма из ESP8266 невозможно.
 

AlexTVR

Member
Код:
#include <ESP8266WiFi.h>
#include "Mail.h"

const char* const staSSID = "****";
const char* const staPass = "****";

const char* const smtpHost[] = {"smtp.inbox.ru"};
const uint16_t smtpPort = 465;
const char* const smtpUser[] = { "-----@inbox.ru"};
const char* const smtpPass[] = { "--------"};
const char* const mailTo = "-------@inbox.ru";
const char* const mailSubject = "Проверочное сообщение";

void setup() {
  Serial.begin(115200);
  Serial.println();

  Serial.print(F("Connecting to \""));
  Serial.print(staSSID);
  Serial.print('"');

  WiFi.begin(staSSID, staPass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print('.');
  }
  Serial.print(' ');
  Serial.println(WiFi.localIP());

  delay(10000);

  for (int8_t i = 0; i < 3; ++i) {
    Serial.println();
    if (sendMail(smtpHost[i], smtpPort, smtpUser[i], smtpPass[i], mailTo, mailSubject, F("Это многострочное сообщение для проверки\r\nВторая строка\r\nТретья строка"))) {
      Serial.print(F("Mail sended through "));
      Serial.println(smtpHost[i]);
    } else {
      Serial.print(F("Error sending mail through "));
      Serial.print(smtpHost[i]);
      Serial.println('!');
    }
  }

  WiFi.disconnect();
}

void loop() {

}
 

AlexTVR

Member
Выше мой код, а это библиотека к нему.

Код:
#include <WiFiClientSecure.h>
//#include <WiFiClientSecureAxTLS.h>
//using namespace axTLS;
#include <base64.h>
#include "Mail.h"

#define NDEBUG

static inline bool checkResponse(const String& response, int16_t code) {
  return response.startsWith(String(code) + ' ');
}

static bool checkResponse(const String& response, int16_t code, const String& errorMsg) {
  bool result = checkResponse(response, code);

  if (! result) {
    Serial.print(errorMsg);
    Serial.print(F(": \""));
    if (response.endsWith(F("\r\n")))
      Serial.print(response.substring(0, response.length() - 2));
    else
      Serial.print(response);
    Serial.println(F("\"!"));
  }

  return result;
}

static String getLine(WiFiClient& client) {
  String result;

  if (client.connected())
    result = client.readStringUntil('\n');
#ifndef NDEBUG
  Serial.print(F("<<"));
  Serial.println(result);
#endif

  return result;
}

static void sendLine(WiFiClient& client, const String& str) {
#ifndef NDEBUG
  Serial.print(F(">>"));
  Serial.println(str);
#endif
  if (client.connected())
    client.println(str);
}

static String sendCommand(WiFiClient& client, const String& str) {
  sendLine(client, str);
  client.flush();

  return getLine(client);
}

bool sendMail(const String& smtpHost, uint16_t smtpPort, const String& smtpUser, const String& smtpPassword, const String& mailTo, const String& mailSubject, const String& mailMessage) {
  WiFiClientSecure client;
  String str;

  Serial.print(F("Connecting to "));
  Serial.println(smtpHost);

//  client.setInsecure();
 
  if (! client.connect(smtpHost.c_str(), smtpPort)) {
    Serial.println(F("Connection failed!"));
    return false;
  }
  client.setTimeout(15000); // 15 sec. read timeout
  str = getLine(client);
  if (! checkResponse(str, 220, F("SMTP connection error")))
    return false;
  str = sendCommand(client, F("HELO esp8266.local"));
  if (! checkResponse(str, 250, F("SMTP HELO error")))
    return false;
  if (smtpPassword.length()) {
    str = sendCommand(client, F("AUTH LOGIN"));
    if (! checkResponse(str, 334, F("SMTP AUTH error")))
      return false;
    str = sendCommand(client, base64::encode(smtpUser));
    if (! checkResponse(str, 334, F("SMTP AUTH USER error")))
      return false;
    str = sendCommand(client, base64::encode(smtpPassword));
    if (! checkResponse(str, 235, F("SMTP AUTH PASS error")))
      return false;
  }
  str = F("MAIL FROM: <");
  str += smtpUser;
  str += '>';
  str = sendCommand(client, str);
  if (! checkResponse(str, 250, F("SMTP MAIL FROM error")))
    return false;
  str = F("RCPT TO: <");
  str += mailTo;
  str += '>';
  str = sendCommand(client, str);
  if (! checkResponse(str, 250, F("SMTP RCPT TO error")))
    return false;
  str = sendCommand(client, F("DATA"));
  if (! checkResponse(str, 354, F("SMTP DATA error")))
    return false;
  str = F("Subject: =?utf-8?B?");
  str += base64::encode(mailSubject);
  str += F("=?=");
  sendLine(client, str);
  sendLine(client, F("MIME-Version: 1.0"));
  sendLine(client, F("Content-type: text/plain; charset=utf-8"));
  str = F("From: <");
  str += smtpUser;
  str += '>';
  sendLine(client, str);
  str = F("To: <");
  str += mailTo;
  str += '>';
  sendLine(client, str);
  sendLine(client, "");
  sendLine(client, mailMessage);
  str = sendCommand(client, F("\r\n."));
  if (! checkResponse(str, 250, F("SMTP send error")))
    return false;
  sendCommand(client, F("QUIT"));
  client.stop();

  return true;
}
 

AlexTVR

Member
Ошибка возникает на строке 67 библиотеки:

if (! client.connect(smtpHost.c_str(), smtpPort)) {
Serial.println(F("Connection failed!"));
return false;

Никакой код не возвращается.
 

AlexTVR

Member
Проблема решена.

Код с сайта
работает отлично.
Если появятся проблемы как у меня на NODEMCU, используйте рекомендацию автора :
1. Замените начальную строку в файле mail.cpp на следующие строки:

//#include <WiFiClientSecure.h>
#include <WiFiClientSecureAxTLS.h>
using namespace axTLS;

2. В файле mail.cpp перед строкой с client.connect(...) - где обычно возникает ошибка, добавьте строку client.setInsecure();"

! Не копируйте эти коды с сайта (другая кодировка и будут ошибки), а пропишите их вручную в ардуино.
 

Алексей.

Active member
Выше мой код, а это библиотека к нему.
Код не безопасный, не проверяете подлинность хоста "smtp.inbox.ru", к которому подключается клиент.
Поделкам на esp от этих ssl/tls-оф ни горячо ни холодно, плевать они хотели на безопасность.
 

pvvx

Активный участник сообщества
Adafruit и прочие уже давно начали отказываться от ESP8266. Основные причины:
1) Нет наличия USB у чипа.
2) Нет поддержки современного уровня SSL.

Welcome to CircuitPython!
Авто-перевод:
Почему мы отказываемся от поддержки ESP8266?
CircuitPython на ESP8266 не очень удобен для пользователей. Трудно отправить файлы на устройство, потому что у него нет собственного USB, и вы можете быстро исчерпать ОЗУ (это меньше, чем вы думаете, после добавления сетевого стека). Мы решили использовать ESP только в качестве сопроцессора. В частности, ESP32, потому что он имеет хорошую поддержку TLS / SSL, которая сейчас необходима даже для самых простых взаимодействий.

Если вы хотите добавить поддержку WiFi, ознакомьтесь с нашим руководством по ESP32 / ESP8266 в качестве сопроцессора.
 
Сверху Снизу