ESP32-CAM: Take and Send Photos via Email using an SMTP Server

This tutorial shows how to send captured photos from the ESP32-CAM to your email account using an SMTP Server. We’ll show you a simple example that takes a photo when the ESP32 boots and sends it as an attachment in an email. The last photo taken is temporarily saved in the ESP32 SPIFFS.

ESP32-CAM Take and Send Photos via Email using an SMTP Server Arduino IDE

To make this project work, the ESP32-CAM needs to be connected to a router with access to the internet – needs to be connected to your local network.

This project is compatible with any ESP32 camera board with the OV2640 camera. You just need to make sure you use the right pin assignment for the board you’re using: ESP32-CAM Camera Boards: Pin and GPIOs Assignment Guide.

ESP32 MailClient Library

To send emails with the ESP32-CAM, we’ll use the ESP32 MailClient library. This library allows the ESP32 to send and receive emails with or without attachment via SMTP and IMAP servers.

In this project, we’ll use SMTP to send an email with an attachment. The attachment is a photo taken with the ESP32-CAM.

SMTP means Simple Mail Transfer Protocol and it is an internet standard for email transmission. To send emails through code, you need to know your SMTP server details. Each email provider has a different SMTP server.

Installing the ESP32 MailClient Library

Before proceeding with this tutorial, you need to install the ESP32 MailClient library. This library can be installed through the Arduino IDE Library Manager.

In your Arduino IDE go to Sketch > Include Library > Manage Libraries…

The Library Manager should open. Search for ESP32 Mail Client by Mobizt and install the library as shown below.

Install library ESP32 Send Email SMTP Server Arduino IDE

Sender Email (New Account)

We recommend creating a new email account to send the emails to your main personal email address. Do not use your main personal email to send emails via ESP32. If something goes wrong in your code or if by mistake you make too many requests, you can be banned or have your account temporary disabled.

We’ll use a newly created Gmail.com account to send the emails, but you can use any other email provider. The receiver email can be your personal email without any problem.

Create a Sender Email Account

Create a new email account for sending emails with the ESP32. If you want to use a Gmail account, go to this link to create a new one.

Gmail Create a new account

Allow less secure apps

Allow less secure apps to get access to this new Gmail account, so that you’re able to send emails. You can open this link to go to that menu.

Gmail Allow Less Secure Apps to Send Email with ESP32

Gmail SMTP Server Settings

If you’re using a Gmail account, these are the SMTP Server details:

  • SMTP Server: smtp.gmail.com
  • SMTP username: Complete Gmail address
  • SMTP password: Your Gmail password
  • SMTP port (TLS): 587
  • SMTP port (SSL): 465
  • SMTP TLS/SSL required: yes

Outlook SMTP Server Settings

For Outlook accounts, these are the SMTP Server settings:

  • SMTP Server: smtp.office365.com
  • SMTP Username: Complete Outlook email address
  • SMTP Password: Your Outlook password
  • SMTP Port: 587
  • SMTP TLS/SSL Required: Yes

Live or Hotmail SMTP Server Settings

For Live or Hotmail accounts, these are the SMTP Server settings:

  • SMTP Server: smtp.live.com
  • SMTP Username: Complete Live/Hotmail email address
  • SMTP Password: Your Windows Live Hotmail password
  • SMTP Port: 587
  • SMTP TLS/SSL Required: Yes

If you’re using another email provider, you need to search for its SMTP Server settings. Now, you have everything ready to start sending emails with the ESP32-CAM.

Code – ESP32-CAM Send Email

The following code takes a photo when the ESP32-CAM first boots and sends it to your email account. Before uploading the code, make sure you insert your sender email settings as well as your recipient email.

/*********
  Rui Santos
  Complete instructions at https://RandomNerdTutorials.com/esp32-cam-projects-ebook/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/

#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>

// REPLACE WITH YOUR NETWORK CREDENTIALS
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// To send Email using Gmail use port 465 (SSL) and SMTP Server smtp.gmail.com
// YOU MUST ENABLE less secure app option https://myaccount.google.com/lesssecureapps?pli=1
#define emailSenderAccount    "[email protected]"
#define emailSenderPassword   "SENDER_ACCOUNT_PASSWORD"
#define smtpServer            "smtp.gmail.com"
#define smtpServerPort        465
#define emailSubject          "ESP32-CAM Photo Captured"
#define emailRecipient        "[email protected]"

#define CAMERA_MODEL_AI_THINKER

#if defined(CAMERA_MODEL_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
#else
  #error "Camera model not selected"
#endif

// The Email Sending data object contains config and data to send
SMTPData smtpData;

// Photo File Name to save in SPIFFS
#define FILE_PHOTO "/photo.jpg"

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  
  Serial.begin(115200);
  Serial.println();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  if (!SPIFFS.begin(true)) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    ESP.restart();
  }
  else {
    delay(500);
    Serial.println("SPIFFS mounted successfully");
  }
  
  // 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();
}

void loop() {

}

// Check if photo capture was successful
bool checkPhoto( fs::FS &fs ) {
  File f_pic = fs.open( FILE_PHOTO );
  unsigned int pic_sz = f_pic.size();
  return ( pic_sz > 100 );
}

// Capture Photo and Save it to SPIFFS
void capturePhotoSaveSpiffs( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean indicating if the picture has been taken correctly

  do {
    // Take a photo with the camera
    Serial.println("Taking a photo...");

    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("Camera capture failed");
      return;
    }

    // Photo file name
    Serial.printf("Picture file name: %s\n", FILE_PHOTO);
    File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);

    // Insert the data in the photo file
    if (!file) {
      Serial.println("Failed to open file in writing mode");
    }
    else {
      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");
    }
    // Close the file
    file.close();
    esp_camera_fb_return(fb);

    // check if file has been correctly saved in SPIFFS
    ok = checkPhoto(SPIFFS);
  } while ( !ok );
}

void sendPhoto( void ) {
  // Preparing email
  Serial.println("Sending email...");
  // Set the SMTP Server Email host, port, account and password
  smtpData.setLogin(smtpServer, smtpServerPort, emailSenderAccount, emailSenderPassword);
  
  // Set the sender name and Email
  smtpData.setSender("ESP32-CAM", emailSenderAccount);
  
  // Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
  smtpData.setPriority("High");

  // Set the subject
  smtpData.setSubject(emailSubject);
    
  // Set the email message in HTML format
  smtpData.setMessage("<h2>Photo captured with ESP32-CAM and attached in this email.</h2>", true);
  // Set the email message in text format
  //smtpData.setMessage("Photo captured with ESP32-CAM and attached in this email.", false);

  // Add recipients, can add more than one recipient
  smtpData.addRecipient(emailRecipient);
  //smtpData.addRecipient(emailRecipient2);

  // Add attach files from SPIFFS
  smtpData.addAttachFile(FILE_PHOTO, "image/jpg");
  // Set the storage type to attach files in your email (SPIFFS)
  smtpData.setFileStorageType(MailClientStorageType::SPIFFS);

  smtpData.setSendCallback(sendCallback);
  
  // Start sending Email, can be set callback function to track the status
  if (!MailClient.sendMail(smtpData))
    Serial.println("Error sending Email, " + MailClient.smtpErrorReason());

  // Clear all data from Email object to free memory
  smtpData.empty();
}

// Callback function to get the Email sending status
void sendCallback(SendStatus msg) {
  //Print the current status
  Serial.println(msg.info());
}

View raw code

How the Code Works

Continue reading to learn how the code works, or skip to the Demonstration section. Don’t forget to insert your network credentials and email settings in the code. Also, if you’re using a camera model other than an ESP32-CAM AI-Thinker, don’t forget to change the pin assignment.

Importing Libraries

Import the required libraries. The ESP32_MailClient.h is used to send emails, the FS.h and SPIFFS.h are used to access and save files to SPIFFS and the WiFi.h library is used to initialize Wi-Fi and connect your ESP32-CAM to your local network.

#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>

Network Credentials

Insert your network credentials in the following variables:

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Email Settings

Type the email sender account on the emailSenderAccount variable and its password on the emailSenderPassword variable.

#define emailSenderAccount   "[email protected]"
#define emailSenderPassword  "SENDER_ACCOUNT_PASSWORD"

Insert the recipient’s email. This is the email that will receive the emails sent by the ESP32:

#define emailRecipient "[email protected]"

Insert your email provider SMTP settings on the following lines. We’re using the settings for a Gmail account. If you’re using a different email provider, replace with the corresponding SMTP settings.

#define smtpServer "smtp.gmail.com"
#define smtpServerPort 465

Write the email subject on the emailSubject variable.

#define emailSubject "ESP32-CAM Photo Captured"

Create an STMPData object called smtpData that contains the data to send via email and all the other configurations.

SMTPData smtpData;

The photo taken with the ESP32 camera will be temporarily saved in SPIFFS under the name photo.jpg.

define FILE_PHOTO "/photo.jpg"

ESP32 Camera Pins

Define the pins used by your camera model. We’re using the 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()

In the setup(), connect the ESP32 to 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();

Initialize SPIFFS (SPI Flash File System) to save the last photo taken with the 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");
}

Print the ESP32-CAM IP address:

// Print ESP32 Local IP Address
Serial.print("IP Address: http://");
Serial.println(WiFi.localIP());

The following lines configure the camera and set the camera settings:

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 the camera.

// 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;
}

After initializing the camera, call the capturePhotoSaveSpiffs() and the sendPhoto() functions. These functions are defined at the end of the code.

capturePhotoSaveSpiffs() function

The capturePhotoSaveSpiffs() function captures a photo and saves it in the ESP32 SPIFFS. In the following lines, you take a photo and save it in the framebuffer fb:

fb = esp_camera_fb_get();
if (!fb) {
  Serial.println("Camera capture failed");
  return;
}

Then, create a new file in SPIFFS where the photo will be saved.

Serial.printf("Picture file name: %s\n", FILE_PHOTO);
File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);

Check if the file was successfully created. If not, print an error message.

if (!file) {
  Serial.println("Failed to open file in writing mode");
}

If a new file was successfully created, “copy” the image from the buffer to that newly created file.

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");

Close the file and clear the buffer for future use.

file.close();
esp_camera_fb_return(fb);

Finally, check whether the photo was successfully taken and saved. We can do that by checking the photo file size with the checkPhoto() function.

ok = checkPhoto(SPIFFS);

The checkPhoto() function, checks the file picture size. If the picture size is bigger than 100 bytes, it’s almost certain the photo was taken and saved successfully. In that case it returns 1.

bool checkPhoto( fs::FS &fs ) {
  File f_pic = fs.open( FILE_PHOTO );
  unsigned int pic_sz = f_pic.size();
  return ( pic_sz > 100 );
}

So, the ok variable is equal to 1.

ok = checkPhoto(SPIFFS);

In case the photo size is less than 100 bytes, the ok variable will continue to be 0, and it will keep trying to take a new photo and save it.

sendPhoto() function

After having the photo successfully saved in SPIFFS, we’ll send it via email by calling the sendPhoto() function. Let’s take a look at that function.

void sendPhoto( void ) {

The following line sets the SMTP Server host, SMTP port, account email address and password used to login:

smtpData.setLogin(smtpServer, smtpServerPort, emailSenderAccount, emailSenderPassword);

Set the sender name and sender email. In this case, we’re setting the sender name to ESP32-CAM.

smtpData.setSender("ESP32-CAM", emailSenderAccount);

Set the email priority.

smtpData.setPriority("High");

Set the email subject.

smtpData.setSubject(emailSubject);

The following line sets the message. You can send an HTML text or raw text. In this case, we’re sending a message with some HTML.

smtpData.setMessage("<h2>Photo captured with ESP32-CAM and attached in this email.</h2>", true);

When sending a message in HTML format, you should pass true as a second parameter to the setMessage() method. If you want to send raw text, set false.

//smtpData.setMessage("Photo captured with ESP32-CAM and attached in this email.", false);

Finally, set the recipient email. This is the email that will receive the messages from the ESP32.

smtpData.addRecipient(emailRecipient);

Then, to attach a file, you just need to call the addAtatachFile() on the smtpData object and pass as argument the file path.

smtpData.addAttachFile(FILE_PHOTO, "image/jpg");

Finally, you need to set where your files are saved (SPIFFS or SD card). We’re using SPIFFS:

smtpData.setFileStorageType(MailClientStorageType::SPIFFS);

Set a callback function that will be called upon sending an email.

smtpData.setSendCallback(sendCallback);

The sendCallback() function returns whether the email was successfully sent or not.

Now that we’ve set all the details of the smtpData, we’re ready to send the email.

if (!MailClient.sendMail(smtpData))
  Serial.println("Error sending Email, " + MailClient.smtpErrorReason());

After sending the email, you can clear all the data from the smtpData object.

smtpData.empty();

In this example, the email is sent once when the ESP32 boots, that’s why the loop() is empty. The idea is to adapt the code to use in your own projects.

void loop() {

}

To send a new email. You just need to reset your board (press the on-board RESET
button), so that it restarts and runs the code again.

Demonstration

After making the necessary changes to the code: camera pinout, sender’s email address, sender’s email password, recipient’s email address and network credentials, you can upload the code to your board.

If you don’t know how to upload code to the ESP32-CAM, read the following post:

After uploading, open the Serial Monitor and press the ESP32-CAM RESET button. The ESP32 should connect to Wi-Fi, take a photo, save it in SPIFFS, connect to the SMTP server and send the email as shown below.

ESP32 CAM send photo via email serial monitor demonstration

After a few seconds, you should have a new email from the ESP32-CAM in your inbox. As you can see in the image below, the sender’s email name is “ESP32-CAM” as we’ve defined in the code and the subject “ESP32-CAM Photo Captured”.

ESP32 CAM Email with Photo Received Inbox

Open the email and you should see a photo captured by the ESP32-CAM.

ESP32 CAM Send Photo To Email Gmail Inbox

You can open or download the photo to see it in full size.

Photo taken with ESP32 CAM Full Size

Wrapping Up

In this tutorial you’ve learned how to send emails with photos taken with the ESP32-CAM. The example presented is as simple as possible: it takes a photo and sends it via email when the ESP32-CAM first boots. To send another email, you need to reset the board.

This project doesn’t have a practical application, but it is useful to understand how to send an email with an attachment. After this, it should be fairly easy to include this feature in your own ESP32-CAM projects.

Other ESP32-CAM projects you may like:

Learn more about the ESP32-CAM:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

13 thoughts on “ESP32-CAM: Take and Send Photos via Email using an SMTP Server”

      • Caden,
        Thanks for your reply.
        I am not an expert in IFTTT.
        Do you know if it is possible to ‘trigger’ the reset button remote with an IFTTT command which is required to start the capturing process?

        Thanks for your help in advance.
        BR
        Arjen

        Reply
        • Arjen, I did some research on IFTTT and they sadly don’t support sending data back to the ESP32-Cam chip, such as asking it to start capturing. I found another option, which would be to set up a server with the ESP32-Cam, and have it run a Event (handleRoot) when its address (Wifi.localIP()) is opened, or “triggered”.

          The code would be:

          /*********
          Rui Santos
          Complete instructions at https://RandomNerdTutorials.com/esp32-cam-projects-ebook/

          Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
          The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
          *********/

          #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>
          #include <ESP8266WebServer.h>
          #include <ESP8266WiFi.h>
          #include <WiFiClient.h>

          // REPLACE WITH YOUR NETWORK CREDENTIALS
          const char* ssid = “REPLACE_WITH_YOUR_SSID”;
          const char* password = “REPLACE_WITH_YOUR_PASSWORD”;
          const char* host = “maker.ifttt.com”;
          //after you set up your account put your IFTTT key here. (see https://randomnerdtutorials.com/door-status-monitor-using-the-esp8266/)
          const char* apiKey = “YOUR_IFTTT_API_KEY”;

          // To send Email using Gmail use port 465 (SSL) and SMTP Server smtp.gmail.com
          // YOU MUST ENABLE less secure app option https://myaccount.google.com/lesssecureapps?pli=1
          #define emailSenderAccount “[email protected]
          #define emailSenderPassword “SENDER_ACCOUNT_PASSWORD”
          #define smtpServer “smtp.gmail.com”
          #define smtpServerPort 465
          #define emailSubject “ESP32-CAM Photo Captured”
          #define emailRecipient “[email protected]

          #define CAMERA_MODEL_AI_THINKER

          #if defined(CAMERA_MODEL_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
          #else
          #error “Camera model not selected”
          #endif

          // The Email Sending data object contains config and data to send
          SMTPData smtpData;

          // Photo File Name to save in SPIFFS
          #define FILE_PHOTO “/photo.jpg”

          void handleRoot() {
          //take capture and send via email.
          capturePhotoSaveSpiffs();
          sendPhoto();

          server.send(200, “text/plain”, “took capture and sent.”);
          }

          void handleNotFound() {
          digitalWrite(led, 1);
          String message = “File Not Found\n\n”;
          message += “URI: “;
          message += server.uri();
          message += “\nMethod: “;
          message += (server.method() == HTTP_GET) ? “GET” : “POST”;
          message += “\nArguments: “;
          message += server.args();
          message += “\n”;
          for (uint8_t i = 0; i < server.args(); i++) {
          message += ” ” + server.argName(i) + “: ” + server.arg(i) + “\n”;
          }
          server.send(404, “text/plain”, message);
          digitalWrite(led, 0);
          }

          void setup() {
          WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

          Serial.begin(115200);
          Serial.println();

          // Connect to Wi-Fi
          WiFi.mode(WIFI_STA);
          WiFi.begin(ssid, password);
          Serial.print(“Connecting to WiFi…”);
          while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print(“.”);
          }
          Serial.println();

          if (!SPIFFS.begin(true)) {
          Serial.println(“An Error has occurred while mounting SPIFFS”);
          ESP.restart();
          }
          else {
          delay(500);
          Serial.println(“SPIFFS mounted successfully”);
          }

          // Print ESP32 Local IP Address
          //opening this will trigger a capture
          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;
          }

          server.on(“/”, handleRoot);

          server.onNotFound(handleNotFound);

          server.begin();
          Serial.println(“HTTP server started! Ready to take photos.”);
          }

          void loop() {
          // in the original sketch this is empty.
          //now we just keep the server up to date.
          server.handleClient();
          MDNS.update();

          }

          // Check if photo capture was successful
          bool checkPhoto( fs::FS &fs ) {
          File f_pic = fs.open( FILE_PHOTO );
          unsigned int pic_sz = f_pic.size();
          return ( pic_sz > 100 );
          }

          // Capture Photo and Save it to SPIFFS
          void capturePhotoSaveSpiffs( void ) {
          camera_fb_t * fb = NULL; // pointer
          bool ok = 0; // Boolean indicating if the picture has been taken correctly

          do {
          // Take a photo with the camera
          Serial.println(“Taking a photo…”);

          fb = esp_camera_fb_get();
          if (!fb) {
          Serial.println("Camera capture failed");
          return;
          }

          // Photo file name
          Serial.printf("Picture file name: %s\n", FILE_PHOTO);
          File file = SPIFFS.open(FILE_PHOTO, FILE_WRITE);

          // Insert the data in the photo file
          if (!file) {
          Serial.println("Failed to open file in writing mode");
          }
          else {
          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");
          }
          // Close the file
          file.close();
          esp_camera_fb_return(fb);

          // check if file has been correctly saved in SPIFFS
          ok = checkPhoto(SPIFFS);

          } while ( !ok );
          }

          void sendPhoto( void ) {
          // Preparing email
          Serial.println(“Sending email…”);
          // Set the SMTP Server Email host, port, account and password
          smtpData.setLogin(smtpServer, smtpServerPort, emailSenderAccount, emailSenderPassword);

          // Set the sender name and Email
          smtpData.setSender(“ESP32-CAM”, emailSenderAccount);

          // Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
          smtpData.setPriority(“High”);

          // Set the subject
          smtpData.setSubject(emailSubject);

          // Set the email message in HTML format
          smtpData.setMessage(”

          Photo captured with ESP32-CAM and attached in this email.

          “, true);
          // Set the email message in text format
          //smtpData.setMessage(“Photo captured with ESP32-CAM and attached in this email.”, false);

          // Add recipients, can add more than one recipient
          smtpData.addRecipient(emailRecipient);
          //smtpData.addRecipient(emailRecipient2);

          // Add attach files from SPIFFS
          smtpData.addAttachFile(FILE_PHOTO, “image/jpg”);
          // Set the storage type to attach files in your email (SPIFFS)
          smtpData.setFileStorageType(MailClientStorageType::SPIFFS);

          smtpData.setSendCallback(sendCallback);

          // Start sending Email, can be set callback function to track the status
          if (!MailClient.sendMail(smtpData))
          Serial.println(“Error sending Email, ” + MailClient.smtpErrorReason());

          // Clear all data from Email object to free memory
          smtpData.empty();
          }

          // Callback function to get the Email sending status
          void sendCallback(SendStatus msg) {
          //Print the current status
          Serial.println(msg.info());
          }

          Reply
        • Create a function that calls capturePhotoSaveSpiffs() and sendPhoto() whenever you send an IFFT trigger to it, then put this function inside main loop(). You wouldn’t need that “reset” function.

          Reply
          • sirDaniel’s idea would work if IFTTT had a way to trigger the capturePhotoSaveSpiffs() and sendPhoto() function. might be able to if you use webhooks request.

  1. These two methods are what you want to call when the web URL is triggered:

    capturePhotoSaveSpiffs();
    sendPhoto();

    you might have to create your own applet.

    The idea would be that you set up a web server, and the IFTTT applet would send info to the server when a web URL is opened.

    Reply
  2. Hi Rui and Sara,
    Great post with interesting features for other projects!
    It would be really interesting in future posts to present the code part of the post on both the arduino IDE and also MicroPython.
    Do you thing it might be possible?
    Regards
    Alain

    Reply
    • Hi.
      Thanks for your comment.
      We intend to do some projects with the ESP32-CAM and MicroPython.
      However, I don’t know when they’ll be ready.
      Regards,
      Sara

      Reply
  3. Hi,
    I tried this project and could download to the ESP.
    In the serial monitor I can see that it do all until connect to the smtp server.
    There is an error : Error, could not connect to server.
    I have activated as mentioned the lower security of the new created gmail account.
    What can I do now?
    Thank You and Best Regards
    Michael

    16:15:57.346 -> Connecting to WiFi….
    16:15:58.510 -> SPIFFS mounted successfully
    16:15:58.510 -> IP Address: http://192.168.100.242
    16:15:59.193 -> Taking a photo…
    16:15:59.501 -> Picture file name: /photo.jpg
    16:16:01.075 -> The picture has been saved in /photo.jpg – Size: 145792 bytes
    16:16:01.110 -> Sending email…
    16:16:01.110 -> Connecting to SMTP server…
    16:16:01.110 -> Error, could not connect to server
    16:16:01.110 -> Error sending Email, could not connect to server

    #define smtpServer “smtp.gmail.com”
    #define smtpServerPort 465
    #define emailSubject “ESP32-CAM Photo Captured”

    can ping the ESP in my WiFi Network and it has internet access.

    Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.