ESP32-CAM Mengirim Foto ke Email Menggunakan Server SMTP (ESP32-CAM-MB dengan Kamera OV3660)

ESP32-CAM merupakan salah satu papan mikrokontroler berbasis ESP32 yang dilengkapi dengan kamera dan konektivitas Wi-Fi. Modul ini banyak digunakan untuk aplikasi pemantauan jarak jauh, sistem keamanan, Internet of Things (IoT), pengenalan objek, hingga sistem dokumentasi otomatis karena mampu mengambil gambar dan mengirimkan data melalui jaringan internet.

 

Salah satu fitur menarik yang dapat diterapkan pada ESP32-CAM adalah kemampuan mengirim foto secara otomatis ke email. Dengan memanfaatkan protokol SMTP (Simple Mail Transfer Protocol), ESP32-CAM dapat mengambil gambar menggunakan kamera, menyimpannya sementara ke memori internal, kemudian mengirimkannya sebagai lampiran (attachment) ke alamat email yang telah ditentukan.

 

Pada tutorial ini, ESP32-CAM akan mengambil foto setiap kali perangkat dinyalakan (booting), lalu mengirimkan hasil foto tersebut ke email penerima. Foto yang berhasil diambil akan disimpan sementara pada sistem file LittleFS sebelum dikirim sebagai lampiran email. Tutorial ini menggunakan ESP32-CAM-MB dengan sensor kamera OV3660. Modul ESP32-CAM-MB berfungsi sebagai papan pemrograman sekaligus catu daya yang memudahkan proses pengunggahan program tanpa memerlukan modul USB-to-Serial tambahan.

Mengenal SMTP dan Library ESP Mail Client

Untuk mengirim email menggunakan ESP32-CAM diperlukan sebuah library yang mampu menangani komunikasi dengan server email. Pada proyek ini digunakan library ESP Mail Client yang dikembangkan oleh Mobizt. Library ini mendukung pengiriman email menggunakan SMTP, penerimaan email menggunakan IMAP, pengiriman lampiran file, pengiriman pesan dalam format HTML, dan dukungan SSL/TLS untuk keamanan komunikasi. SMTP (Simple Mail Transfer Protocol) merupakan standar komunikasi yang digunakan untuk mengirim email melalui internet. Agar ESP32-CAM dapat mengirim email, diperlukan informasi server SMTP dari penyedia layanan email yang digunakan.

Menginstal Library ESP Mail Client

Sebelum mulai membuat program, instal terlebih dahulu library yang diperlukan.

1. Buka Arduino IDE.

2. Pilih menu Sketch → Include Library → Manage Libraries.

 


3. Ketik ESP Mail Client pada kolom pencarian.

4. Instal library ESP Mail Client by Mobizt. 

 


Pastikan library berhasil terinstal sebelum melanjutkan ke tahap berikutnya.

Menyiapkan Akun Email Pengirim

Sebaiknya gunakan akun email khusus sebagai pengirim dan jangan menggunakan email pribadi utama. Hal ini bertujuan untuk menghindari pemblokiran akun apabila terjadi kesalahan konfigurasi atau pengiriman email dalam jumlah besar secara tidak sengaja. Pada tutorial ini digunakan akun Gmail sebagai email pengirim, namun Anda dapat menggunakan penyedia layanan email lainnya selama menyediakan akses SMTP.

1. Membuat Akun Gmail Baru

Buat akun Gmail baru yang nantinya akan digunakan oleh ESP32-CAM untuk mengirim email.

 

2. Membuat App Password Gmail

Google tidak mengizinkan aplikasi pihak ketiga menggunakan kata sandi akun Gmail secara langsung. Oleh karena itu, diperlukan App Password agar ESP32-CAM dapat melakukan autentikasi ke server SMTP Gmail. Sebelum membuat App Password, aktifkan terlebih dahulu fitur Verifikasi 2 Langkah (2-Step Verification) pada akun Gmail.

Langkah-langkahnya sebagai berikut:

1. Masuk ke akun Google.

2. Pilih menu Keamanan.

3. Aktifkan Verifikasi 2 Langkah.

4. Ikuti proses aktivasi hingga selesai 

Setelah fitur tersebut aktif:

1. Masuk kembali ke halaman akun Google.

2. Cari menu Sandi Aplikasi (App Passwords).

 

3. Buat aplikasi baru dengan nama misalnya ESP32-CAM.

4. Klik Buat.  


Google akan menampilkan kode App Password yang terdiri dari 16 karakter.



 

Simpan kode tersebut karena akan digunakan pada program ESP32-CAM sebagai kata sandi SMTP. 

Konfigurasi Server SMTP

1. SMTP Gmail

Jika menggunakan Gmail, gunakan konfigurasi berikut:

- Server SMTP: smtp.gmail.com

- Port SSL: 465

- Port TLS: 587

- Memerlukan SSL/TLS: Ya

2. SMTP Outlook

- Server SMTP: smtp.office365.com

- Port: 587

- Memerlukan SSL/TLS: Ya 

3. SMTP Hotmail atau Live

- Server SMTP: smtp.live.com

- Port: 587

- Memerlukan SSL/TLS: Ya 

Apabila menggunakan layanan email lain, sesuaikan dengan konfigurasi SMTP yang disediakan oleh penyedia layanan tersebut.

Program ESP32-CAM Mengirim Foto ke Email

Program berikut akan:

1. Menghubungkan ESP32-CAM ke jaringan Wi-Fi.

2. Menginisialisasi kamera OV3660.

3. Mengambil foto.

4. Menyimpan foto ke LittleFS.

5. Mengirim foto sebagai lampiran email melalui SMTP.

 

#include "esp_camera.h"

#include "SPI.h"

#include "driver/rtc_io.h"

#include "soc/rtc_cntl_reg.h"  // Disable brownout problems

#include <ESP_Mail_Client.h>

#include <FS.h>

#include <WiFi.h>

#include <LittleFS.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 need to create an email app password

#define emailSenderAccount    "SENDER_EMAIL@gmail.com"

#define emailSenderPassword   "YOUR_EMAIL_APP_PASSWORD"

#define smtpServer            "smtp.gmail.com"

#define smtpServerPort        465

#define emailSubject          "ESP32-CAM Photo Captured"

#define emailRecipient        "YOUR_EMAIL_RECIPIENT@example.com"


#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 SMTP Session object used for Email sending */

SMTPSession smtp;


/* Callback function to get the Email sending status */

void smtpCallback(SMTP_Status status);


// Photo File Name to save in LittleFS

#define FILE_PHOTO "photo.jpeg"

#define FILE_PHOTO_PATH "/photo.jpeg"


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

 

  // Print ESP32 Local IP Address

  Serial.print("IP Address: http://");

  Serial.println(WiFi.localIP());


  // Init filesystem

  ESP_MAIL_DEFAULT_FLASH_FS.begin(true);

   

  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_sccb_sda = SIOD_GPIO_NUM;

  config.pin_sccb_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;

  config.grab_mode = CAMERA_GRAB_LATEST;

 

  if(psramFound()){

    config.frame_size = FRAMESIZE_UXGA;

    config.jpeg_quality = 10;

    config.fb_count = 1;

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

  }

 

  capturePhotoSaveLittleFS();

  sendPhoto();

}


void loop() {


}


// Capture Photo and Save it to LittleFS

void capturePhotoSaveLittleFS( void ) {

  // Dispose first pictures because of bad quality

  camera_fb_t* fb = NULL;

  // Skip first 3 frames (increase/decrease number as needed).

  for (int i = 0; i < 3; i++) {

    fb = esp_camera_fb_get();

    esp_camera_fb_return(fb);

    fb = NULL;

  }

   

  // Take a new photo

  fb = NULL;  

  fb = esp_camera_fb_get();  

  if(!fb) {

    Serial.println("Camera capture failed");

    delay(1000);

    ESP.restart();

  }  


  // Photo file name

  Serial.printf("Picture file name: %s\n", FILE_PHOTO_PATH);

  File file = LittleFS.open(FILE_PHOTO_PATH, 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_PATH);

    Serial.print(" - Size: ");

    Serial.print(fb->len);

    Serial.println(" bytes");

  }

  // Close the file

  file.close();

  esp_camera_fb_return(fb);

}


void sendPhoto( void ) {

 

  /** 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 data */

  Session_Config config;

 

  /*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 = 0;

  config.time.day_light_offset = 1;


  /* Set the session config */

  config.server.host_name = smtpServer;

  config.server.port = smtpServerPort;

  config.login.email = emailSenderAccount;

  config.login.password = emailSenderPassword;

  config.login.user_domain = "";


  /* 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 = "ESP32-CAM";

  message.sender.email = emailSenderAccount;


  message.subject = emailSubject;

  message.addRecipient("Sara", emailRecipient);


  String htmlMsg = "<h2>Photo captured with ESP32-CAM and attached in this email.</h2>";

  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 = FILE_PHOTO;

  att.descr.mime = "image/jpeg";

  att.file.path = FILE_PHOTO_PATH;

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

    return;


  /* Start sending the Email and close the session */

  if (!MailClient.sendMail(&smtp, &message, true))

    Serial.println("Error sending Email, " + smtp.errorReason());

}


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

    Serial.printf("Message sent success: %d\n", status.completedCount());

    Serial.printf("Message sent failled: %d\n", 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: %d\n", i + 1);

      ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");

      ESP_MAIL_PRINTF("Date/Time: %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("Recipient: %s\n", result.recipients.c_str());

      ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());

    }

    Serial.println("----------------\n");


   // You need to clear sending result as the memory usage will grow up.

   smtp.sendingResult.clear();

  }

}

 

Penjelasan Program

1. Menghubungkan ESP32-CAM ke Jaringan Wi-Fi

Saat perangkat dinyalakan, ESP32-CAM terlebih dahulu terhubung ke jaringan Wi-Fi menggunakan SSID dan password yang telah ditentukan.

 

WiFi.begin(ssid, password);


Koneksi internet diperlukan agar ESP32-CAM dapat berkomunikasi dengan server SMTP.

2. Inisialisasi Sistem File LittleFS

LittleFS digunakan sebagai media penyimpanan sementara hasil foto sebelum dikirim melalui email.

 

ESP_MAIL_DEFAULT_FLASH_FS.begin();


Dengan pendekatan ini, file gambar dapat diperlakukan seperti file biasa sehingga lebih mudah dijadikan lampiran email.

3. Konfigurasi Kamera OV3660

Meskipun menggunakan sensor OV3660, konfigurasi pin pada ESP32-CAM-MB tetap mengikuti tata letak modul AI-Thinker, karena sensor OV3660 dipasang pada modul kamera yang kompatibel dengan pinout bawaan ESP32-CAM. Program mengatur resolusi, kualitas JPEG, frekuensi clock kamera, serta buffer penyimpanan gambar.

 

config.pixel_format = PIXFORMAT_JPEG;


Format JPEG dipilih karena ukuran file lebih kecil dibandingkan format RAW sehingga lebih cepat dikirim melalui internet.

4. Mengambil Foto

Fungsi pengambilan foto akan membuang beberapa frame pertama sebelum mengambil gambar utama.

Hal ini dilakukan karena sensor kamera biasanya masih melakukan penyesuaian otomatis terhadap pencahayaan, eksposur, dan white balance saat pertama kali aktif.

 

for (int i = 0; i < 3; i++) {

  fb = esp_camera_fb_get();

  esp_camera_fb_return(fb);

}


Setelah itu kamera mengambil gambar yang akan digunakan sebagai lampiran email.

5. Menyimpan Foto ke LittleFS

Data gambar yang tersimpan pada framebuffer kemudian ditulis ke dalam file.

 

File file = LittleFS.open(FILE_PHOTO_PATH, FILE_WRITE);


File tersebut akan tersimpan dengan nama /photo.jpg.


6. Membuat Koneksi ke Server SMTP

ESP32-CAM menggunakan informasi akun email dan server SMTP yang telah ditentukan sebelumnya.

 

config.server.host_name = smtpServer;

config.server.port = smtpServerPort;


Pada contoh ini digunakan server SMTP Gmail dengan port SSL 465.

7. Menambahkan Lampiran Foto

Foto yang tersimpan di LittleFS kemudian ditambahkan sebagai lampiran email.

 

SMTP_Attachment att;


Konfigurasi lampiran meliputi nama file, lokasi penyimpanan, jenis file, dan metode encoding.

 

att.file.path = FILE_PHOTO_PATH;


8. Mengirim Email

Setelah seluruh parameter selesai dikonfigurasi, ESP32-CAM melakukan koneksi ke server SMTP dan mengirim email.

 

MailClient.sendMail(&smtp, &message, true);


Apabila proses berhasil, email akan muncul pada kotak masuk penerima lengkap dengan lampiran foto hasil tangkapan kamera.

Mengunggah Program ke ESP32-CAM-MB

Sebelum mengunggah program, pastikan beberapa parameter berikut telah diubah sesuai kebutuhan:

- Nama jaringan Wi-Fi.

- Password Wi-Fi.

- Alamat email pengirim.

App Password Gmail.

- Alamat email penerima. 

Setelah semua parameter diisi, unggah program ke ESP32-CAM-MB menggunakan Arduino IDE.

Tunggu hingga proses kompilasi dan pengunggahan selesai tanpa error.

 

Hasil Pengujian

1. Setelah ESP32-CAM berhasil menyala dan terhubung ke internet, perangkat akan secara otomatis mengambil foto dan mengirimkannya ke alamat email tujuan. Beberapa detik kemudian, email baru akan muncul pada kotak masuk penerima.

2. Email tersebut akan menampilkan nama pengirim yang telah ditentukan pada program serta subjek email yang telah dikonfigurasi sebelumnya.

 

3. Saat email dibuka, foto hasil tangkapan kamera OV3660 akan terlihat sebagai lampiran.

 


4. Lampiran dapat dibuka secara langsung atau diunduh untuk melihat gambar dalam ukuran penuh.





Dalam praktik, hasil dan kendala yang ditemui bisa berbeda tergantung perangkat, konfigurasi, versi library, dan sistem yang digunakan.

Posting Komentar

0 Komentar