本教程介绍了如何使用SMTP服务器将捕获的照片从ESP32-CAM发送到您的电子邮件帐户。我们将向您展示一个简单的示例,该示例在ESP32引导时拍摄照片并将其作为电子邮件附件发送。拍摄的最后一张照片临时保存在ESP32 SPIFFS中。
为了使该项目正常进行,ESP32-CAM需要连接到可以访问互联网的路由器,并且需要连接到您的本地网络。
该项目与任何带OV2640相机的ESP32相机板兼容。您只需要确保为所使用的板使用了正确的引脚分配即可:
ESP32 MailClient库
要使用ESP32-CAM发送电子邮件 ,我们将使用 ESP32 MailClient库。该库允许ESP32通过SMTP和IMAP服务器发送和接收带有或不带有附件的电子邮件。
在此项目中,我们将使用SMTP发送带有附件的电子邮件。附件是用ESP32-CAM拍摄的照片。
SMTP表示简单邮件传输协议,它是电子邮件传输的互联网标准。要通过代码发送电子邮件,您需要知道您的SMTP服务器详细信息。每个电子邮件提供商都有一个不同的SMTP服务器。
安装ESP32 MailClient库
在继续本教程之前,您需要安装 ESP32 MailClient库。该库可以通过Arduino IDE库管理器安装:
ESP32 MailClient库
在您的Arduino IDE中,转到 “程序” >“ 包含库” >“ 管理库…”。
库管理器应打开。 通过搜索 ESP32 Mail Client并安装库,如下所示。
发件人电子邮件(新帐户)
我们建议创建一个新的电子邮件帐户,以将电子邮件发送到您的主要个人电子邮件地址。 请勿使用您的主要个人电子邮件通过ESP32发送电子邮件。如果您的代码出了问题,或者错误地提出了太多请求,则可能会被禁止或暂时禁用您的帐户。
我们将使用新创建的Gmail.com帐户发送电子邮件,但您可以使用任何其它电子邮件提供商。收件人电子邮件可以是您的个人电子邮件,没有任何问题。
没有gmail邮箱的,也可以使用QQ邮箱,163邮箱之类的,国内的邮箱注册方式就不说了,有的可以直接拿来用。
创建一个发件人电子邮件帐户
创建一个新的电子邮件帐户以使用ESP32发送电子邮件。如果要使用Gmail帐户,请转到此链接 创建一个新帐户 。
允许安全性较低的应用
允许安全性较差的应用访问此新的Gmail帐户,以便您可以发送电子邮件。您可以 打开此链接 转到该菜单。
Gmail SMTP服务器设置
如果您使用的是Gmail帐户,则这些是SMTP服务器详细信息:
- SMTP服务器: smtp.gmail.com
- SMTP用户名:完整的Gmail地址
- SMTP密码:您的Gmail密码
- SMTP端口(TLS): 587
- SMTP端口(SSL): 465
- 需要SMTP TLS / SSL: 是
Outlook SMTP服务器设置
对于Outlook帐户,这些是SMTP服务器设置:
- SMTP服务器: smtp.office365.com
- SMTP用户名:完整的Outlook电子邮件地址
- SMTP密码:您的Outlook密码
- SMTP端口: 587
- SMTP TLS / SSL必需: 是
Live或Hotmail SMTP服务器设置
对于Live或Hotmail帐户,这些是SMTP服务器设置:
- SMTP服务器: smtp.live.com
- SMTP用户名:完整的实时/ Hotmail电子邮件地址
- SMTP密码:您的Windows Live Hotmail密码
- SMTP端口: 587
- SMTP TLS / SSL必需: 是
腾讯企业邮箱
- SMTP服务器:smtp.exmail.qq.com
- SMTP端口号:SSL(465)
- SMTP用户名:腾讯企业邮箱地址
- SMTP密码:邮箱账户密码
需要在邮箱设置->客户端设置启用POP/SMTP服务
QQ邮箱
SMTP服务器:smtp.qq.com
SMTP端口号:25(无)/SSL(465)/TLS(587)
SMTP密码:第三方服务授权码,需要在邮箱设置中启用POP/SMTP服务并生成授权码。
163网易邮箱
可以参考CSDN博主的配置:https://www.cnblogs.com/zeussbook/p/10231526.html
如果您使用的是其它电子邮件提供商,则需要搜索其SMTP服务器设置。现在,您已准备就绪,可以开始使用ESP32-CAM发送电子邮件了。
代码– ESP32-CAM发送电子邮件
以下代码在ESP32-CAM首次启动时拍张照片,并将其发送到您的电子邮件帐户。在上传代码之前,请确保您插入了发件人电子邮件设置以及收件人电子邮件,完整代码如下:
代码如何工作
继续阅读以了解代码的工作原理,不要忘记在代码中插入网络凭据和电子邮件设置。另外,如果您使用的相机型号不是ESP32-CAM AI-Thinker,请不要忘记更改引脚分配。
导入库
导入所需的库。这ESP32_MailClient.h 用于发送电子邮件, FS.h 和 SPIFFS.h 用于访问文件并将文件保存到SPIFFS,并且 无线网络 库用于初始化Wi-Fi并将ESP32-CAM连接到本地网络。
#include "esp_camera.h"
#include "SPI.h"
#include "driver/rtc_io.h"
#include "ESP32_MailClient.h"
#include <FS.h>
#include <SPIFFS.h>
#include <WiFi.h>
网络凭证
在以下变量中插入您的网络凭据:
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
电邮设定
在上输入电子邮件发件人帐户 emailSenderAccount 变量及其上的密码 emailSenderPassword variable。
#define emailSenderAccount "EXAMPLE_SENDER_ACCOUNT@gmail.com"
#define emailSenderPassword "SENDER_ACCOUNT_PASSWORD"
插入收件人的电子邮件。这是将接收ESP32发送的电子邮件的电子邮件:
#define emailRecipient "YOUR_EMAIL_RECIPIENT@gmail.com"
在以下行中插入您的电子邮件提供商的SMTP设置。我们正在使用Gmail帐户的设置。如果您使用其它电子邮件提供商,请替换为相应的SMTP设置。
#define smtpServer "smtp.gmail.com"
#define smtpServerPort 465
将电子邮件主题写在 电子邮件主题 variable。
#define emailSubject "ESP32-CAM Photo Captured"
创建一个 STMP数据 对象称为 smtpData 包含要通过电子邮件发送的数据和所有其它配置。
SMTPData smtpData;
使用ESP32相机拍摄的照片将暂时保存在SPIFFS中,名称为 photo.jpg。
define FILE_PHOTO "/photo.jpg"
ESP32摄像头引脚
定义相机型号使用的引脚。我们正在使用ESP32-CAM AI-Thinker。
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
setup()
在 setup() 里面,将ESP32连接到Wi-Fi。
// Connect to Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
初始化SPIFFS(SPI Flash文件系统)以保存用ESP32-CAM拍摄的最后一张照片。
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
ESP.restart();
}
else {
delay(500);
Serial.println("SPIFFS mounted successfully");
}
打印ESP32-CAM的IP地址:
// Print ESP32 Local IP Address
Serial.print("IP Address: http://");
Serial.println(WiFi.localIP());
以下几行配置摄像机并设置摄像机设置:
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
初始化相机。
// Initialize camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
初始化相机后,调用 capturePhotoSaveSpiffs() 和 sendPhoto() 函数。这些功能在代码末尾定义。
capturePhotoSaveSpiffs()函数
这 capturePhotoSaveSpiffs()功能捕获照片并将其保存在ESP32 SPIFFS中。在以下几行中,您拍摄一张照片并将其保存在帧缓冲区中fb:
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
return;
}
然后,在SPIFFS中创建一个新文件,将照片保存在该文件中。
Serial.printf("Picture file name: %sn", FILE_PHOTO);
File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);
检查文件是否成功创建。如果不是,请打印错误信息。
if (!file) {
Serial.println("Failed to open file in writing mode");
}
如果成功创建了新文件,则将图像从缓冲区“复制”到该新创建的文件。
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.print("The picture has been saved in ");
Serial.print(FILE_PHOTO);
Serial.print(" - Size: ");
Serial.print(file.size());
Serial.println(" bytes");
关闭文件并清除缓冲区以备将来使用。
file.close();
esp_camera_fb_return(fb);
最后,检查照片是否已成功拍摄并保存。我们可以通过使用checkPhoto() 功能。
ok = checkPhoto(SPIFFS);
这 checkPhoto()功能,检查文件图片大小。如果图片大小大于100字节,则几乎可以确定该照片已成功拍摄并保存。在这种情况下,它将返回1。
bool checkPhoto( fs::FS &fs ) {
File f_pic = fs.open( FILE_PHOTO );
unsigned int pic_sz = f_pic.size();
return ( pic_sz > 100 );
}
所以 好的 变量等于1。
ok = checkPhoto(SPIFFS);
如果照片大小小于100字节,则 好的 变量将继续为0,并且会继续尝试拍摄新照片并将其保存。
sendPhoto()函数
将照片成功保存到SPIFFS后,我们将通过以下方式通过电子邮件发送该照片: 发送照片()功能。让我们看一下该函数。
void sendPhoto( void ) {
以下行设置了用于登录的SMTP服务器主机,SMTP端口,帐户电子邮件地址和密码:
smtpData.setLogin(smtpServer, smtpServerPort, emailSenderAccount, emailSenderPassword);
设置发件人名称和发件人电子邮件。在这种情况下,我们将发送方名称设置为ESP32-CAM。
smtpData.setSender("ESP32-CAM", emailSenderAccount);
设置电子邮件优先级。
smtpData.setPriority("High");
设置电子邮件主题。
smtpData.setSubject(emailSubject);
下一行设置了消息。您可以发送HTML文本或原始文本。在这种情况下,我们将使用一些HTML发送消息。
smtpData.setMessage("<h2>Photo captured with ESP32-CAM and attached in this email.</h2>", true);
以HTML格式发送消息时,您应该通过 真的 作为第二个参数 setMessage()方法。如果要发送原始文本,请设置错误的。
//smtpData.setMessage("Photo captured with ESP32-CAM and attached in this email.", false);
最后,设置收件人电子邮件。这是将从ESP32接收消息的电子邮件。
smtpData.addRecipient(emailRecipient);
然后,要附加文件,您只需调用 addAtatachFile() 在 smtpData 对象,并将文件路径作为参数传递。
smtpData.addAttachFile(FILE_PHOTO, "image/jpg");
最后,您需要设置文件的保存位置(SPIFFS或SD卡)。我们正在使用SPIFFS:
smtpData.setFileStorageType(MailClientStorageType::SPIFFS);
设置在发送电子邮件时将被调用的回调函数。
smtpData.setSendCallback(sendCallback);
这 sendCallback() 函数返回电子邮件是否已成功发送。
现在,我们已经设置了 smtpData,我们已经准备好发送电子邮件。
if (!MailClient.sendMail(smtpData))
Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
发送电子邮件后,您可以清除电子邮件中的所有数据 smtpData 目的。
smtpData.empty();
在此示例中,ESP32引导时,电子邮件仅发送一次,这就是为什么 loop() 是空的。这个想法是修改代码以在您自己的项目中使用。
void loop() {
}
发送新电子邮件。您只需要重置板(按板载的RESET按钮),即可重新启动并再次运行代码。
示范
在对代码进行了必要的更改后:摄像机引出线,发件人的电子邮件地址,发件人的电子邮件密码,收件人的电子邮件地址和网络凭据,您可以将代码上传到板上。
如果您不知道如何将代码上传到ESP32-CAM,请阅读以下文章:
上传后,打开串行监控器,然后按ESP32-CAM RESET按钮。ESP32应该连接到Wi-Fi,拍照,将其保存在SPIFFS中,连接到SMTP服务器并发送电子邮件,如下所示。
几秒钟后,您应该在收件箱中收到一封来自ESP32-CAM的新电子邮件。如下图所示,发件人的电子邮件名是“ ESP32-CAM”,如代码中所定义,主题为“ ESP32-CAM Photo Captured”。
打开电子邮件,您应该会看到ESP32-CAM拍摄的照片。
您可以打开或下载照片以查看完整尺寸。
按照你的教程,最后提示错误,怎样破?
17:48:40.345 -> Connecting to SMTP server…
17:48:42.170 -> SMTP server connected, wait for response…
17:48:42.170 -> Identification…
17:48:42.216 -> Error, identification failed
17:48:42.216 -> Error sending Email, identification failed
你的电子邮箱发件人账号密码估计错了
我也碰上了这个问题,请问你解决了么
我可以收到了(用的163邮箱) #define emailSenderAccount “123456@163.com” //发信账号 #define emailSenderPassword “OADSUVOUWE” //授权码(并非邮箱密码,这里的授权码是在邮箱中开通SMTP服务时提供的) #define smtpServer “smtp.163.com” //SMTP服务器地址(这里同样注意,不同公司的邮箱有不同SMTP服务器地址) #define smtpServerPort 465 //SSL协议端口号(同样注意) #define emailSubject “ESP32-CAM_strawberry_picture” //邮件主题(邮件标题,自己定义即可) #define emailRecipient “123456@163.com” //收信地址
一发邮箱就死机,不知道咋搞
emmmmm