Отправка электронных писем с ESP32

Узнайте, как отправлять электронные письма с помощью ESP32 с использованием SMTP-сервера. Мы покажем вам, как отправить простое письмо в формате HTML или обычного текста, а также как отправлять вложения, такие как изображения и файлы (.txt). Плата ESP32 будет запрограммирована с использованием Arduino IDE.

Содержание

  1. Введение в SMTP-сервера

  2. Библиотека ESP Mail Client

  3. Создание нового аккаунта отправителя

  4. Создание пароля приложения

  5. Код

Отправка электронных писем с ESP32 с использованием SMTP-сервера: HTML, текст и вложения (Arduino IDE)

В этом уроке мы рассмотрим следующие темы:

  • Отправка электронных писем с ESP32 (HTML и обычный текст)

  • Отправка электронных писем с вложениями (изображение и файл .txt)

Введение в SMTP-сервера

SMTP означает Simple Mail Transfer Protocol (Простой протокол передачи почты) и является интернет-стандартом для передачи электронной почты. Для отправки писем с использованием ESP32 необходимо подключиться к SMTP-серверу.

Библиотека ESP Mail Client

Для отправки электронных писем с ESP32 мы будем использовать библиотеку ESP-Mail-Client. Эта библиотека позволяет ESP32 отправлять и получать электронные письма с вложениями или без них через SMTP и IMAP серверы.

В этом уроке мы будем использовать SMTP для отправки письма с вложениями и без них. В качестве примера мы отправим изображение (.png) и файл текста (.txt). Файлы, отправляемые по электронной почте, могут быть сохранены в файловой системе ESP32 (SPIFFS, LittleFS или FatFs) или на карте microSD (не рассматривается в этом уроке).

Установка библиотеки ESP-Mail-Client

Перед тем как продолжить, вам необходимо установить библиотеку ESP-Mail-Client.

Перейдите в Скетч> Подключить библиотеку > Управлять библиотеками и найдите ESP Mail Client. Установите библиотеку ESP Mail Client от Mobizt.

Открытие Serial Monitor

Создание нового аккаунта отправителя

Рекомендуется создать новый аккаунт электронной почты для отправки писем на ваш основной личный адрес электронной почты. Не используйте свой основной личный email для отправки писем через ESP32. Если что-то пойдет не так в вашем коде или если по ошибке вы сделаете слишком много запросов, вас могут заблокировать или временно отключить ваш аккаунт.

Мы будем использовать вновь созданный аккаунт Gmail.com для отправки писем, но вы можете использовать любого другого почтового провайдера. Получатель может использовать вашу личную почту без проблем.

Создание аккаунта отправителя

Создайте новый аккаунт электронной почты для отправки писем с помощью ESP32. Если вы хотите использовать аккаунт Gmail, перейдите по этой ссылке для создания нового аккаунта.

Открытие Serial Monitor

Создание пароля приложения

Вам необходимо создать пароль приложения, чтобы ESP32 мог отправлять письма с использованием вашего аккаунта Gmail. Пароль приложения — это 16-значный код, который дает менее безопасному приложению или устройству доступ к вашей учетной записи Google. Узнайте больше о входе с использованием паролей приложений здесь.

Пароль приложения можно использовать только с учетными записями, у которых включена двухэтапная аутентификация.

  1. Откройте свою учетную запись Google.

  2. В панели поиска выберите Безопасность.

  3. В разделе Вход в Google выберите Двухэтапная аутентификация > Начать.

  4. Следуйте инструкциям на экране.

После включения двухэтапной аутентификации вы сможете создать пароль приложения.

  1. Откройте свою учетную запись Google.

  2. В панели поиска найдите Пароли приложений(App password).

  3. Откройте меню Пароли приложений(App password).

Открытие Serial Monitor
  1. Дайте имя паролю приложения, например ESP. Затем нажмите Создать. Откроется окно с паролем, который вы будете использовать для отправки писем с ESP32 или ESP8266. Сохраните этот пароль (хотя и указано, что его не нужно запоминать), так как он понадобится вам позже.

Открытие Serial Monitor Открытие Serial Monitor

Теперь у вас должен быть пароль приложения, который вы будете использовать в коде ESP для отправки писем.

Открытие Serial Monitor

Если вы используете другого почтового провайдера, узнайте, как создать пароль приложения. Вы можете найти инструкции с помощью быстрого поиска в Google: «ваш_почтовый_провайдер + создать пароль приложения».

Настройки SMTP-сервера Gmail

Если вы используете аккаунт Gmail, вот настройки SMTP-сервера:

  • SMTP Server: smtp.gmail.com

  • SMTP username: полный адрес Gmail

  • SMTP password: ваш пароль Gmail

  • SMTP port (TLS): 587

  • SMTP port (SSL): 465

  • SMTP TLS/SSL required: да

Настройки SMTP-сервера Outlook

Для учетных записей Outlook, вот настройки SMTP-сервера:

  • SMTP Server: smtp.office365.com

  • SMTP Username: полный адрес электронной почты Outlook

  • SMTP Password: ваш пароль Outlook

  • SMTP Port: 587

  • SMTP TLS/SSL Required: да

Настройки SMTP-сервера Live или Hotmail

Для учетных записей Live или Hotmail, вот настройки SMTP-сервера:

  • SMTP Server: smtp.live.com

  • SMTP Username: полный адрес электронной почты Live/Hotmail

  • SMTP Password: ваш пароль Windows Live Hotmail

  • SMTP Port: 587

  • SMTP TLS/SSL Required: да

Если вы используете другого почтового провайдера, вам нужно найти его настройки SMTP-сервера. Теперь у вас есть все необходимое, чтобы начать отправлять письма с ESP32.

Отправка письма в формате HTML или обычного текста с ESP32 (Arduino IDE)

Следующий код отправляет письмо через SMTP-сервер в формате HTML или обычного текста. Для демонстрации ESP32 отправляет письмо один раз при загрузке. Затем вы сможете изменить код и интегрировать его в свои проекты.

Не загружайте код сразу, вам нужно внести некоторые изменения, чтобы он работал.

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS"
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

SMTPSession smtp;

void smtpCallback(SMTP_Status status);

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

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    Serial.print(".");
  }

  MailClient.networkReconnect(true);
  smtp.debug(1);
  smtp.callback(smtpCallback);

  Session_Config config;
  config.server.host_name = SMTP_HOST;
  config.server.port = SMTP_PORT;
  config.login.email = AUTHOR_EMAIL;
  config.login.password = AUTHOR_PASSWORD;

  config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
  config.time.gmt_offset = 3;
  config.time.day_light_offset = 0;

  SMTP_Message message;
  message.sender.name = F("ESP");
  message.sender.email = AUTHOR_EMAIL;
  message.subject = F("Тестовое письмо от ESP");
  message.addRecipient(F("Sara"), RECIPIENT_EMAIL);
  message.text.content = "Привет, мир! - Отправлено с платы ESP";
  message.text.charSet = "utf-8";
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

  if (!smtp.connect(&config)) {
    Serial.println("Ошибка подключения.");
    return;
  }

  if (!MailClient.sendMail(&smtp, &message)) {
    Serial.println("Ошибка отправки письма.");
  }
}

void loop() {}

void smtpCallback(SMTP_Status status) {
  Serial.println(status.info());
  if (status.success()) {
    for (size_t i = 0; i < smtp.sendingResult.size(); i++) {
      SMTP_Result result = smtp.sendingResult.getItem(i);
      Serial.printf("Статус: %s\n", result.completed ? "успех" : "неудача");
      Serial.printf("Получатель: %s\n", result.recipients.c_str());
      Serial.printf("Тема: %s\n", result.subject.c_str());
    }
    smtp.sendingResult.clear();
  }
}

Вам необходимо вставить свои учетные данные сети, а также указать email отправителя, данные SMTP-сервера, email получателя и сообщение.

Как работает код

Этот код адаптирован из примера, предоставленного библиотекой. Пример хорошо прокомментирован, чтобы вы понимали, что делает каждая строка кода. Давайте рассмотрим только важные части, которые вам нужно изменить или которые могут потребовать изменений.

Во-первых, вставьте свои учетные данные сети в следующие строки:

#define WIFI_SSID "MyWiFiName"
#define WIFI_PASSWORD "MyStrongPassword123"

Вставьте настройки вашего SMTP-сервера. Если вы используете аккаунт Gmail для отправки писем, вот настройки:

#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

Вставьте учетные данные для входа отправителя (полный email и пароль приложения, который вы создали ранее).

#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_PASS"

Вставьте email получателя:

#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

Вам может потребоваться настроить переменную gmt_offset в зависимости от вашего местоположения, чтобы письмо было помечено правильным временем.

config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;

Установите заголовки сообщения в следующих строках в функции setup() — имя отправителя, email отправителя, тему письма и имя и email получателя:

// Устанавливаем заголовки письма
message.sender.name = F("ESP");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Тестовое письмо от ESP");
message.addRecipient(F("Sara"), RECIPIENT_EMAIL);

В следующих строках установите содержимое сообщения (обычный текст) в переменной textMsg:

// Отправка сообщения в формате обычного текста
String textMsg = "Привет, мир! - Отправлено с платы ESP";
message.text.content = textMsg.c_str();
message.text.charSet = "utf-8";
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

Если вы хотите отправить текст в формате HTML, раскомментируйте следующие строки — вам нужно вставить ваш HTML-текст в переменную htmlMsg.

/* Отправка сообщения в формате HTML */
String htmlMsg = "<div style="color:#2f4468;"><h1>Привет, мир!</h1><p>- Отправлено с платы ESP</p></div>";
message.html.content = htmlMsg.c_str();
message.html.charSet = "utf-8";
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

Наконец, следующие строки отправляют сообщение:

if (!MailClient.sendMail(&smtp, &message))
Serial.println("Ошибка отправки Email, " + smtp.errorReason());

Демонстрация

Загрузите код на ваш ESP32. После загрузки откройте Серийный монитор на скорости 115200. Нажмите кнопку Reset на ESP32.

Если все прошло успешно, вы должны увидеть подобное сообщение в Серийном мониторе.

Открытие Serial Monitor

Проверьте ваш почтовый ящик. Вы должны получить письмо от вашей платы ESP32.

Открытие Serial Monitor

Если вы включили отправку сообщения в формате обычного текста, вот какое письмо вы должны получить.

Открытие Serial Monitor

Отправка вложений по электронной почте с ESP32 (Arduino IDE)

В этом разделе мы покажем вам, как отправлять вложения в письмах, отправляемых с ESP32. Мы покажем вам, как отправлять файлы .txt или изображения. Это может быть полезно для отправки файла .txt с показаниями датчиков за последние несколько часов или для отправки фотографии, сделанной с помощью ESP32-CAM.

Для этого урока файлы, которые будут отправлены, должны быть сохранены в файловой системе ESP32 (LittleFS).

Загрузка файлов в LittleFS

Чтобы отправить файлы по электронной почте, они должны быть сохранены в файловой системе ESP32 или на карте microSD. Мы загрузим изображение и файл .txt в файловую систему ESP32 LittleFS с использованием плагина ESP32 Filesystem Uploader для Arduino IDE. Следуйте следующему руководству, чтобы установить плагин, если он еще не установлен:

[Arduino IDE 2: Установка загрузчика ESP32 LittleFS (Загрузка файлов в файловую систему)].

Создайте новый скетч Arduino и сохраните его. Перейдите в Скетч > Показать папку скетча. Внутри папки скетча создайте папку под названием data. Переместите файл .jpg и файл .txt в вашу папку data.

Вы также можете скачать папку с проектом, нажав здесь.

Ваши файлы должны иметь следующие имена: image.png и text_file.txt. Вы можете изменить код, чтобы импортировать файлы с другими именами.

Мы будем отправлять эти файлы:

Открытие Serial Monitor

Ваша структура папок должна выглядеть следующим образом(cкачать папку с проектом):

Открытие Serial Monitor

После перемещения файлов в папку data, вам нужно загрузить их на вашу плату. В Arduino IDE нажмите [Ctrl] + [Shift] + [P] в Windows или [⌘] + [Shift] + [P] на MacOS, чтобы открыть палитру команд. Найдите команду «Upload LittleFS to Pico/ESP8266/ESP32» и щелкните по ней.

Открытие Serial Monitor Открытие Serial Monitor

Если файлы успешно загружены, переходите к следующему разделу.

Код

Следующий код отправляет письмо с прикрепленным файлом .txt и изображением. Перед загрузкой кода убедитесь, что вы вставили учетные данные отправителя и email получателя.

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS"
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

SMTPSession smtp;

void smtpCallback(SMTP_Status status);

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

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Подключение к AP");

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(200);
  }

  Serial.println("");
  Serial.println("Wi-Fi подключен.");
  Serial.print("IP адрес: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  ESP_MAIL_DEFAULT_FLASH_FS.begin();
  smtp.debug(1);
  smtp.callback(smtpCallback);

  Session_Config config;
  config.server.host_name = SMTP_HOST;
  config.server.port = SMTP_PORT;
  config.login.email = AUTHOR_EMAIL;
  config.login.password = AUTHOR_PASSWORD;
  config.login.user_domain = "mydomain.net";
  config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
  config.time.gmt_offset = 3;
  config.time.day_light_offset = 0;

  SMTP_Message message;
  message.enable.chunking = true;
  message.sender.name = "ESP Mail";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = F("Тест отправки Email с вложениями и встроенными изображениями из Flash");
  message.addRecipient(F("Sara"), RECIPIENT_EMAIL);

  String htmlMsg = "Это сообщение содержит вложения: изображение и текстовый файл.";
  message.html.content = htmlMsg.c_str();
  message.html.charSet = "utf-8";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;

  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

  SMTP_Attachment att;
  att.descr.filename = "image.png";
  att.descr.mime = "image/png";
  att.file.path = "/image.png";
  att.file.storage_type = esp_mail_file_storage_type_flash;
  att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
  message.addAttachment(att);

  message.resetAttachItem(att);
  att.descr.filename = "text_file.txt";
  att.descr.mime = "text/plain";
  att.file.path = "/text_file.txt";
  att.file.storage_type = esp_mail_file_storage_type_flash;
  att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
  message.addAttachment(att);

  if (!smtp.connect(&config)) {
    ESP_MAIL_PRINTF("Ошибка подключения, Код состояния: %d, Код ошибки: %d, Причина: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
    return;
  }

  if (!smtp.isLoggedIn()) {
    Serial.println("\nЕще не вошел в систему.");
  } else {
    if (smtp.isAuthenticated())
      Serial.println("\nУспешный вход.");
    else
      Serial.println("\nПодключен без авторизации.");
  }

  if (!MailClient.sendMail(&smtp, &message, true))
    Serial.println("Ошибка отправки Email, " + smtp.errorReason());
}

void loop() {
}

void smtpCallback(SMTP_Status status) {
  Serial.println(status.info());

  if (status.success()) {
    Serial.println("----------------");
    ESP_MAIL_PRINTF("Успешно отправлено сообщение: %d\n", status.completedCount());
    ESP_MAIL_PRINTF("Сообщение не отправлено: %d\n", status.failedCount());
    Serial.println("----------------\n");

    struct tm dt;

    for (size_t i = 0; i < smtp.sendingResult.size(); i++) {
      SMTP_Result result = smtp.sendingResult.getItem(i);
      time_t ts = (time_t)result.timestamp;
      localtime_r(&ts, &dt);

      ESP_MAIL_PRINTF("Сообщение №: %d\n", i + 1);
      ESP_MAIL_PRINTF("Статус: %s\n", result.completed ? "успех" : "неудача");
      ESP_MAIL_PRINTF("Дата/Время: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);
      ESP_MAIL_PRINTF("Получатель: %s\n", result.recipients.c_str());
      ESP_MAIL_PRINTF("Тема: %s\n", result.subject.c_str());
    }

    Serial.println("----------------\n");
    smtp.sendingResult.clear();
  }
}

Как работает код

Этот код очень похож на предыдущий, поэтому мы рассмотрим только важные части, касающиеся отправки вложений.

В функции setup() вы инициализируете файловую систему с использованием метода библиотеки ESP Mail Client. Файловая система по умолчанию, установленная в библиотеке для ESP32, — это LittleFS (вы можете изменить файловую систему по умолчанию в файле библиотеки ESP_Mail_FS.h).

// Инициализация файловой системы
ESP_MAIL_DEFAULT_FLASH_FS.begin();

Вам нужно создать вложение следующим образом:

/* Элемент данных вложения */
SMTP_Attachment att;

Затем добавьте информацию о вложении: имя файла, MIME тип, путь к файлу, тип хранения файла и кодировку передачи. В следующих строках мы отправляем файл изображения.

att.descr.filename = "image.png";
att.descr.mime = "image/png";
att.file.path = "/image.png";
att.file.storage_type = esp_mail_file_storage_type_flash;
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

Наконец, добавьте вложение к сообщению:

/* Добавить вложение к сообщению */
message.addAttachment(att);

Если вы хотите отправить дополнительные вложения, вам нужно вызвать следующую строку перед добавлением следующего вложения:

message.resetAttachItem(att);

Затем введите детали другого вложения (текстового файла):

att.descr.filename = "text_file.txt";
att.descr.mime = "text/plain";
att.file.path = "/text_file.txt";
att.file.storage_type = esp_mail_file_storage_type_flash;
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

И добавьте это вложение к сообщению:

message.addAttachment(att);

Наконец, вам нужно только отправить сообщение, как в предыдущем примере:

if (!MailClient.sendMail(&smtp, &message, true))
  Serial.println("Ошибка отправки Email, " + smtp.errorReason());

Демонстрация

После загрузки кода откройте Серийный монитор на скорости 115200 и нажмите на кнопку EN/RESET на плате. Если все пройдет гладко, вы должны увидеть похожее сообщение в Серийном мониторе.

Открытие Serial Monitor

Проверьте адрес электронной почты получателя. У вас должно быть новое письмо с двумя вложениями.

Открытие Serial Monitor

Заключение

В этом уроке вы узнали, как отправлять письма с ESP32 с использованием SMTP-сервера. Для того чтобы этот метод работал, ESP32 должен иметь доступ к интернету.

Если вы не хотите использовать SMTP-сервер, вы также можете написать PHP-скрипт для отправки уведомлений по электронной почте с плат ESP32 или ESP8266.

Вы узнали, как отправить простое письмо с текстом и вложениями. При использовании вложений они должны быть сохранены в файловой системе ESP32 (LittleFS) или на карте microSD (не рассматривается в этом уроке).

Примеры, представленные в этом уроке, показывают, как отправить одно письмо при загрузке ESP32. Идея заключается в том, чтобы изменить код и включить его в свои проекты. Например, это может быть полезно для отправки файла .txt с показаниями датчиков, отправки фотографии, сделанной с помощью ESP32-CAM, использования режима глубокого сна для пробуждения платы каждый час и отправки данных по электронной почте и т.д.