使用 SMTP 服务器发送电子邮件:HTML、文本和附件-ESP8266/NodeMCU

释放双眼,带上耳机,听听看~!

在本教程中,您将学习如何使用 SMTP 服务器通过 ESP8266 NodeMCU 板发送电子邮件。我们将展示如何发送包含原始文本、HTML 文本的电子邮件,以及如何发送图像和文件 (.txt) 等附件。我们将使用 Arduino 内核对 ESP8266 NodeMCU 板进行编程。

ESP8266 NodeMCU Send Emails using an SMTP Server HTML Text and Attachments Arduino IDE

SMTP 服务器简介

SMTP 是指简单邮件传输协议,它是电子邮件传输的互联网标准。要使用ESP8266发送电子邮件,您需要将其连接到 SMTP 服务器。

 ESP-Mail-Client 库

要使用 ESP8266 NodeMCU 开发板发送电子邮件,我们将使用 ESP-Mail-Client 库。该库允许ESP8266通过 SMTP 和 IMAP 服务器发送和接收带或不带附件的电子邮件。

在本教程中,我们将使用 SMTP 发送带附件和不带附件的电子邮件。例如,我们将发送图像 (.png) 和文本 (.txt) 文件。通过电子邮件发送的文件可以保存在 ESP8266 文件系统(SPIFFS 或 LittleFS)或 microSD 卡(本教程未介绍)中。

安装 ESP-Mail-Client 库

在继续本教程之前,您需要安装 ESP-Mail-Client 库:

发件人电子邮件(新帐户)

我们建议您创建一个新的电子邮件帐户,以将电子邮件发送到您的主要个人电子邮件地址。不要使用您的主要个人电子邮件通过ESP8266发送电子邮件。如果您的代码出现问题,或者您错误地发出了太多请求,您可能会被禁止或暂时禁用您的帐户。

我们将使用新创建的 Gmail.com 帐户发送电子邮件,但您可以使用任何其他电子邮件提供商。收件人电子邮件可以是您的个人电子邮件,没有任何问题。

创建发件人电子邮件帐户

创建一个新的电子邮件帐户,用于ESP8266发送电子邮件。可以选择使用QQ或163邮箱等国内的邮箱。
对于163邮箱,需要在163邮箱的设置中开启“POP3/SMTP服务”并获取授权码,而不是使用常规密码。对于QQ邮箱,也需要开启相应的服务并获取授权码。

使用 SMTP 服务器发送电子邮件:HTML、文本和附件-ESP8266/NodeMCU

当使用国内常用的邮箱发送电子邮件时,您需要了解各个邮箱提供商的SMTP服务器设置。以下是一些其他国内常见邮箱的SMTP服务器设置:

  1. 网易(163)邮箱:
    • SMTP服务器:smtp.163.com
    • 端口:25
    • 需要SMTP TLS/SSL:是
  2. 腾讯(QQ)邮箱:
    • SMTP服务器:smtp.qq.com
    • 端口:465
    • 需要SMTP TLS/SSL:是
  3. 新浪邮箱:
    • SMTP服务器:smtp.sina.com
    • 端口:25
    • 需要SMTP TLS/SSL:是
  4. 搜狐邮箱:
    • SMTP服务器:smtp.sohu.com
    • 端口:25
    • 需要SMTP TLS/SSL:是

请在Arduino代码中使用相应的SMTP服务器设置和端口,并确保开启了相应邮箱的SMTP服务。对于每个邮箱,记得使用授权码或应用程序专用密码而不是常规密码,以提高安全性。

如果您使用的是其他电子邮件提供商,则需要搜索其 SMTP 服务器设置。现在,您已经准备好开始使用ESP8266发送电子邮件了。

在 Arduino IDE 中,您可以转到 ESP-Mail-Client > 文件>示例,并尝试使用提供的示例,您需要插入您的电子邮件详细信息(发件人和收件人帐户)、SMTP 服务器设置以及您的 SSID 和密码。


发送带有 HTML 的电子邮件或使用 ESP8266 发送原始文本

以下代码通过 SMTP 服务器发送带有 HTML 或原始文本的电子邮件。例如,ESP8266在启动时发送一次电子邮件。然后,您应该能够修改代码并将其集成到您自己的项目中。

先不要上传代码,您需要进行一些修改才能使其适合您。

 

您需要插入网络凭据并设置发件人电子邮件、SMTP 服务器详细信息、收件人和邮件。

代码的工作原理

此代码改编自库提供的示例。该示例注释得很好,以便您了解每行代码的作用。让我们看一下您需要或可能需要更改的相关部分。

首先,在以下行中插入您的网络凭据:

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

插入 SMTP 服务器设置。如果您使用 163邮箱 帐户发送电子邮件,则设置如下:

#define SMTP_HOST "smtp.163.com"
#define SMTP_PORT 25

插入发件人电子邮件登录凭据(之前创建的完整电子邮件和 APP 密码)

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

插入收件人电子邮件:

#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

您可能需要根据您所在的位置调整gmt_offset变量,以便电子邮件的时间戳正确。

config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 8;  // 中国标准时间偏移为UTC+8
config.time.day_light_offset = 0;

在 setup() 的以下行中设置邮件标题 – 发件人姓名、发件人电子邮件、电子邮件主题以及收件人姓名和电子邮件:

/* Set the message headers */
message.sender.name = "ESP";
message.sender.email = AUTHOR_EMAIL;
message.subject = "ESP Test Email";
message.addRecipient("Sara", RECIPIENT_EMAIL);

在以下行中,在 textMsg 变量中设置消息的内容(原始文本):

//Send raw text message
String textMsg = "Hello World! - Sent from ESP board";
message.text.content = textMsg.c_str();
message.text.charSet = "us-ascii";
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

如果要改为发送 HTML 文本,请取消注释以下行 – 您应该在 htmlMsg 变量中插入 HTML 文本。

/*Send HTML message*/
/*String htmlMsg = "<div style="color:#2f4468;"><h1>Hello World!</h1><p>- Sent from ESP board</p></div>";
message.html.content = htmlMsg.c_str();
message.html.content = htmlMsg.c_str();
message.text.charSet = "us-ascii";
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/

最后,以下行发送消息:

if (!MailClient.sendMail(&smtp, &message))
    Serial.println("Error sending Email, " + smtp.errorReason());

 示范

将代码上传到您的ESP8266。上传后,以 115200 的波特率打开串行监视器。

如果一切按预期进行,您应该会在串行监视器中收到类似的消息。

ESP8266 NodeMCU Send Email Message Successfully Serial Monitor

检查您的电子邮件帐户。您应该已经收到来自ESP8266板的电子邮件。

使用 SMTP 服务器发送电子邮件:HTML、文本和附件-ESP8266/NodeMCU


使用ESP8266通过电子邮件发送附件 (Arduino IDE)

本节将向您展示如何在ESP8266发送的电子邮件中发送附件。我们将向您展示如何发送 .txt 文件或图片。这对于发送包含过去几个小时或其他应用程序的传感器读数的 .txt 文件非常有用。

您应该将要发送的文件保存在 ESP8266 文件系统(SPIFFS 或 LittleFS)中。该库使用的默认文件系统是 LittleFS。您还可以发送保存在 microSD 卡上的附件,但我们不会在本教程中介绍此主题。

上传文件到 LittleFS

要通过电子邮件发送文件,您应该将它们保存在 ESP8266 文件系统中。该库默认使用 LittleFS。要使用 Arduino IDE 将文件上传到 LittleFS,您需要安装文件系统上传插件。阅读以下教程,了解如何安装文件并将其上传到 ESP8266 文件系统:

在Arduino IDE中安装ESP8266 NodeMCU LittleFS文件系统上传器

创建一个新的Arduino程序并保存它。转到“程序”>“显示程序”文件夹。在 Arduino sketch 文件夹中,创建一个名为 data 的文件夹。将 .png 文件和 .txt 文件移动到数据文件夹。

或者,您可以单击此处下载项目文件夹。

注意:使用默认代码时,您的文件必须命名为 image.png 和 text_file.txt,或者您可以修改代码以导入具有不同名称的文件。

我们将发送以下文件:

Upload the files to filesystem to send as an email attachment

您的文件夹结构应如下所示(下载项目文件夹):

Send email attachments folder structure filesystem organizing files

将文件移动到数据文件夹后,在 Arduino IDE 中,转到 LittleFS 数据上传> ESP8266工具,然后等待文件上传。

ESP8266 Tools LittleFS Data Upload Arduino IDE

您应该会在调试窗口中收到一条成功消息。如果文件已成功上传,请转到下一部分。

LittleFS image uploaded

 使用方法

以下代码发送一封电子邮件,其中包含 .txt 文件和附加的图片。在上传验证码之前,请确保插入发件人电子邮件设置以及收件人电子邮件。

/*
  
  更多Arduino/ESP8266/ESP32等教程请访问:https://www.qutaojiao.com
*/
// To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1

#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.163.com"

/** The smtp port e.g. 
 * 25  or esp_mail_smtp_port_25
 * 465 or esp_mail_smtp_port_465
 * 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT 25

/* The sign in credentials */
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS"

/* Recipient's email*/
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

/* The SMTP Session object used for Email sending */
SMTPSession smtp;

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to AP");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(200);
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  // Init filesystem
  ESP_MAIL_DEFAULT_FLASH_FS.begin();

  /** Enable the debug via Serial port
   * none debug or 0
   * basic debug or 1
  */
  smtp.debug(1);

  /* Set the callback function to get the sending results */
  smtp.callback(smtpCallback);

  /* Declare the Session_Config for user defined session credentials */
  Session_Config config;

  /* Set the session 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";
  
  /*
  Set the NTP config time
  For times east of the Prime Meridian use 0-12
  For times west of the Prime Meridian add 12 to the offset.
  Ex. American/Denver GMT would be -6. 6 + 12 = 18
  See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
  */
  config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
  config.time.gmt_offset = 3;
  config.time.day_light_offset = 0;

  /* Declare the message class */
  SMTP_Message message;

  /* Enable the chunked data transfer with pipelining for large message if server supported */
  message.enable.chunking = true;

  /* Set the message headers */
  message.sender.name = "ESP Mail";
  message.sender.email = AUTHOR_EMAIL;

  message.subject = F("Test sending Email with attachments and inline images from Flash");
  message.addRecipient(F("Sara"), RECIPIENT_EMAIL);

  /** Two alternative content versions are sending in this example e.g. plain text and html */
  String htmlMsg = "This message contains attachments: image and text file.";
  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;

  /* The attachment data item */
  SMTP_Attachment att;

  /** Set the attachment info e.g. 
   * file name, MIME type, file path, file storage type,
   * transfer encoding and content encoding
  */
  att.descr.filename = "image.png";
  att.descr.mime = "image/png"; //binary data
  att.file.path = "/image.png";
  att.file.storage_type = esp_mail_file_storage_type_flash;
  att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

  /* Add attachment to the message */
  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;

  /* Add attachment to the message */
  message.addAttachment(att);

  /* Connect to server with the session config */
  if (!smtp.connect(&config)){
    ESP_MAIL_PRINTF("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
    return;
  }

  if (!smtp.isLoggedIn()){
    Serial.println("nNot yet logged in.");
  }
  else{
    if (smtp.isAuthenticated())
      Serial.println("nSuccessfully logged in.");
    else
      Serial.println("nConnected with no Auth.");
  }

  /* Start sending the Email and close the session */
  if (!MailClient.sendMail(&smtp, &message, true))
    Serial.println("Error sending Email, " + smtp.errorReason());
}

void loop(){
}

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status){
  /* Print the current status */
  Serial.println(status.info());

  /* Print the sending result */
  if (status.success()){
    Serial.println("----------------");
    ESP_MAIL_PRINTF("Message sent success: %dn", status.completedCount());
    ESP_MAIL_PRINTF("Message sent failled: %dn", status.failedCount());
    Serial.println("----------------n");
    struct tm dt;

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

      ESP_MAIL_PRINTF("Message No: %dn", i + 1);
      ESP_MAIL_PRINTF("Status: %sn", result.completed ? "success" : "failed");
      ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%dn", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);
      ESP_MAIL_PRINTF("Recipient: %sn", result.recipients.c_str());
      ESP_MAIL_PRINTF("Subject: %sn", result.subject.c_str());
    }
    Serial.println("----------------n");
    
    // You need to clear sending result as the memory usage will grow up.
    smtp.sendingResult.clear();
  }
}

 

代码的工作原理

这段代码与上一段代码非常相似,因此我们只看一下发送附件的相关部分。

在 setup() 中,使用 ESP 邮件客户端库方法初始化文件系统。ESP32 库中设置的默认文件系统是 LittleFS(您可以在库文件 ESP_Mail_FS.h 中更改默认值)。

// Init filesystem
ESP_MAIL_DEFAULT_FLASH_FS.begin();

您需要按如下方式创建附件:

/* The attachment data item */
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);

如果要发送更多附件,则需要在添加下一个附件之前调用以下行:

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("Error sending Email, " + smtp.errorReason());

 示范

上传代码后,以 115200 的波特率打开串行监视器。如果一切按预期进行,您应该会在串行监视器上收到类似的消息。

ESP8266 NodeMCU Send Email Message Successfully Serial Monitor

如果您转到收件箱,您应该会收到包含两个附件的邮件。

 总结

在本教程中,您学习了如何使用 SMTP 服务器通过 ESP8266 NodeMCU 板发送电子邮件。您已经学习了如何发送 HTM 文本、原始文本和附件。

现在,我们的想法是修改代码并将其包含在您自己的项目中。例如,发送包含过去一小时的传感器读数、检测到运动时的通知等的 .txt 文件可能很有用。

给TA打赏
共{{data.count}}人
人已打赏
Nodemcu/ESP8266Nodemcu/ESP8266-进阶动态

在Arduino IDE中安装ESP8266 NodeMCU LittleFS文件系统上传器

2023-12-11 19:45:57

Nodemcu/ESP8266Nodemcu/ESP8266-进阶动态

HTTP GET 和 HTTP POST 请求教程:使用 ESP8266/NodeMCU

2023-12-11 22:22:35

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索