Arduino UNO/Mega and Ethernet: Sending Emails with Attachments (EMailSender v4.0.0 Library)

Spread the love

It’s time for an updated guide for sending emails with Arduino UNO and Mega using my EmailSender v4.0.0 library. This article builds upon the previous one, focusing on the new library version and introducing a robust and reliable solution for boards with limited RAM: the Brevo SMTP service.

Arduino’s RAM Limitations and The Solution

Before we begin, it’s essential to clarify a crucial point: Arduino UNO and Arduino Mega do not have enough RAM to handle SSL/TLS encryption.

  • Arduino UNO: Has only 2KB of RAM.
  • Arduino Mega: Has 8KB of RAM.
  • SSL/TLS Requirements: A secure connection requires at least 24KB of RAM just for the encryption buffers.

This means that it is not possible to connect directly to services like Gmail, Outlook, or Yahoo, which strictly require SSL/TLS.

So, what’s the solution? Use a professional SMTP service that allows authentication on standard ports (like 587) without forcing SSL/TLS encryption. Brevo (formerly Sendinblue) is the perfect choice and the one I recommend, as it offers a generous free plan and is perfectly compatible with Arduino’s limitations.

In this guide, we will walk through how to set up a complete, working project using an Arduino Mega, a W5500 Ethernet Shield, and the Brevo service.

The W5500 controller is the best choice, thanks to its hardware TCP/IP stack that reduces the load on the Arduino’s CPU.

PlatformWiFiEthernetSSL/TLSSTARTTLSStatus
ESP32Full Support
ESP8266Full Support
Arduino MegaLimited Memory
Arduino UnoLimited Memory
Arduino SAMDFull Support
STM32✅*With Ethernet
Raspberry Pi Pico WFull Support

* Need a good quantity of ram (>24K)

Arduino requirements

What Works on Arduino Mega/Uno

FeatureArduino MegaArduino UnoNotes
Available RAM8KB2KBSufficient for basic SMTP
SMTP Port 587✅ YES⚠️ LimitedWith AUTH LOGIN (no SSL)
SMTP Port 25✅ YES✅ YESLocal networks/relays only
SSL/TLS (465)❌ NO❌ NORequires 24KB+ RAM
STARTTLS (587 secure)❌ NO❌ NORequires BearSSL
SD Attachments✅ YES⚠️ LimitedMega recommended

Email Services Compatible with Arduino Mega/Uno

IMPORTANT: On Arduino Mega/Uno, it is only possible to send emails through SMTP services that accept connections without SSL/TLS, due to RAM limitations and the lack of hardware support for SSL.

ServicePortSSLDomain RequiredEmails/DayArduino MegaRecommendation
Brevo587300⭐⭐⭐⭐⭐
SMTP2GO25251000⭐⭐⭐
Mailgun5875000⭐⭐⭐
Local Relay25Unlimited⭐⭐⭐⭐

Check the updated list on relative forum section.

Hardware Requirements

Here to buy Arduino at low price Arduino UNO - Arduino MEGA 2560 R3 - Arduino Nano - Arduino Pro Mini

Here to buy some ethernet variants modules w5500 lite - w5500 - enc26j60 mini - enc26j60 - lan8720

For this project, I recommend the following setup to ensure you have enough memory and pins:

  • Arduino Board: Arduino Mega 2560 R3 (recommended for its 8KB of RAM); however, Arduino Uno is sufficient for the basic example.
  • Network Shield: W5500-based Ethernet Shield.
  • Storage (Optional): A MicroSD card reader module to send attachments.
  • Power Supply: A stable 5V, 1A power adapter.
  • Ethernet Cable.

Here the connection diagram of Ethernet module

To manage attachments from SD, here is the connection schema with theSD module.

Here to buy my selection of SD card module AliExpress

Software and Library Setup

1. Arduino IDE

Ensure you have the latest version of the Arduino IDE from the official website.

2. Install Libraries

Arduino IDE

  1. Open Arduino IDE
  2. Go to Sketch > Include Library > Manage Libraries
  3. Search for “EMailSender
  4. Click Install

PlatformIO

Add to your platformio.ini:

lib_deps = 
    xreef/EMailSender@^4.0.0

Manual Installation

  1. Download the library from GitHub
  2. Extract to Arduino libraries folder
  3. Restart Arduino IDE

Configuring Your Brevo Account

Brevo is an excellent service that offers 300 free emails per day, perfect for IoT projects.

  1. Create a Free Account: Go to brevo.com and sign up.
  2. Verify Your Account: Complete the verification process. This may take a few hours.
  3. Get Your SMTP Credentials: Once your account is active, navigate to Account -> SMTP & API. Here you will find your credentials:
    • SMTP Server: smtp-relay.brevo.com
    • Port: 587
    • Login: Your registration email address.
    • Password: Your SMTP key (copy this and store it securely).
  4. Verify a Sender: In the Senders & IP section, make sure you have verified the email address you will use as the sender (From) in your code.

Basic EMailSender example

Arduino Mega Examples
ArduinoMega_EthernetW5500_BrevoArduino MegaBrevo SMTP❌ Port 587RECOMMENDED – No SSL required

This sketch demonstrates how to send a simple email using an Arduino Mega and your Brevo credentials.

/*
 * EMailSender Library - Arduino Mega + Brevo (Sendinblue) Example
 *
 * This example shows how to send email using Arduino Mega with Ethernet shield
 * and Brevo SMTP service (port 587 without SSL/TLS).
 *
 * WHY BREVO?
 * - Arduino Mega has only 8KB RAM (not enough for SSL/TLS which needs 24KB+)
 * - Brevo accepts port 587 WITHOUT SSL/TLS encryption
 * - 300 emails/day free tier
 * - No domain verification required (just verify your email address)
 *
 * SETUP INSTRUCTIONS:
 * 1. Register at https://www.brevo.com (free account)
 * 2. Go to SMTP & API → SMTP settings
 * 3. Get your SMTP credentials:
 *    - Login: something like "98a01e002@smtp-brevo.com"
 *    - Password: your API key (e.g., "xsmtpsib-abc123...")
 * 4. Verify a sender email address in Brevo dashboard
 * 5. Update the credentials below
 *
 * HARDWARE:
 * - Arduino Mega 2560
 * - W5500 or W5100 Ethernet Shield
 * - Ethernet cable connected to router
 *
 * WIRING (W5500):
 * - MOSI → Pin 51
 * - MISO → Pin 50
 * - SCK  → Pin 52
 * - CS   → Pin 10
 * - VCC  → 5V
 * - GND  → GND
 *
 * Author: Renzo Mischianti
 * Website: https://www.mischianti.org
 * Library: https://github.com/xreef/EMailSender
 * License: MIT
 * Date: 2025-01-07
 */

#include <SPI.h>
#include <Ethernet.h>
#include <EMailSender.h>

// ========== CONFIGURATION - UPDATE THESE VALUES ==========

// Brevo SMTP Credentials (get from https://app.brevo.com/settings/keys/smtp)
const char* BREVO_LOGIN = "<YOUR-BREVO-SMTP-LOGIN>";        // Your Brevo SMTP login
const char* BREVO_PASSWORD = "<YOUR-BREVO-PASSWD>";   // Your Brevo SMTP password/API key

// Email addresses
const char* EMAIL_FROM = "<YOUR-EMAIL-VERIFIED-IN-BREVO>";   // Must be verified in Brevo
const char* EMAIL_TO = "<RECEIVER-EMAIL>";               // Recipient email

// Ethernet MAC address (make it unique on your network)
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// Optional: Static IP configuration (comment out to use DHCP)
// IPAddress ip(192, 168, 1, 177);
// IPAddress gateway(192, 168, 1, 1);
// IPAddress subnet(255, 255, 255, 0);
// IPAddress dns(8, 8, 8, 8);

// ========== END CONFIGURATION ==========

// Create EMailSender instance for Brevo
EMailSender emailSend(
  BREVO_LOGIN,              // Brevo SMTP login
  BREVO_PASSWORD,           // Brevo SMTP password
  EMAIL_FROM,               // From email (must be verified in Brevo)
  "ArduinoMega",            // Sender name
  "smtp-relay.brevo.com",   // Brevo SMTP server
  587                        // Port 587 (AUTH LOGIN without SSL)
);

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ; // Wait for serial port to connect (needed for native USB)
  }

  Serial.println("\n========================================");
  Serial.println("Arduino Mega + Brevo Email Example");
  Serial.println("========================================\n");

  // Initialize Ethernet
  Serial.println("Initializing Ethernet...");

  // Try DHCP first
  if (Ethernet.begin(mac) == 0) {
    Serial.println("DHCP failed!");

    // Fallback to static IP (uncomment the IP variables above)
    // Serial.println("Trying static IP...");
    // Ethernet.begin(mac, ip, dns, gateway, subnet);

    Serial.println("ERROR: Cannot initialize Ethernet!");
    Serial.println("Check:");
    Serial.println("  - Ethernet cable is connected");
    Serial.println("  - Shield is properly seated");
    Serial.println("  - Router DHCP is enabled");
    while (1) {
      delay(1000);
    }
  }

  // Give Ethernet time to initialize
  delay(1500);

  // Print network information
  Serial.println("✓ Ethernet connected!");
  Serial.print("  IP Address: ");
  Serial.println(Ethernet.localIP());
  Serial.print("  Gateway: ");
  Serial.println(Ethernet.gatewayIP());
  Serial.print("  Subnet Mask: ");
  Serial.println(Ethernet.subnetMask());
  Serial.print("  DNS Server: ");
  Serial.println(Ethernet.dnsServerIP());
  Serial.println();

  // Check link status
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("WARNING: Ethernet cable not connected!");
  }

  // Send test email
  Serial.println("Preparing to send email...");
  sendTestEmail();
}

void loop() {
  // Keep Ethernet connection alive
  Ethernet.maintain();

  // Nothing else to do in loop
  delay(10000);
}

void sendTestEmail() {
  Serial.println("\n--- Sending Email ---");

  // Prepare email message
  EMailSender::EMailMessage message;
  message.subject = "Test from Arduino Mega + Brevo";

  // IMPORTANT: Add space at beginning to avoid first character bug
  message.message = " Hello from Arduino Mega!\n\n";
  message.message += "This email was sent using:\n";
  message.message += "- Arduino Mega 2560\n";
  message.message += "- Ethernet Shield (W5500/W5100)\n";
  message.message += "- Brevo SMTP service (port 587 without SSL)\n";
  message.message += "- EMailSender Library v4.0.0\n\n";
  message.message += "Brevo is perfect for Arduino because:\n";
  message.message += "✓ No SSL/TLS required (Arduino Mega has only 8KB RAM)\n";
  message.message += "✓ 300 emails/day free tier\n";
  message.message += "✓ No domain verification needed\n";
  message.message += "✓ Simple AUTH LOGIN authentication\n\n";
  message.message += "Timestamp: " + String(millis() / 1000) + " seconds\n\n";
  message.message += "---\n";
  message.message += "Sent using EMailSender Library by Renzo Mischianti\n";
  message.message += "More info: https://www.mischianti.org\n";
  message.message += "GitHub: https://github.com/xreef/EMailSender\n";

  message.mime = MIME_TEXT_PLAIN;

  // Print email details
  Serial.println("From: " + String(EMAIL_FROM));
  Serial.println("To: " + String(EMAIL_TO));
  Serial.println("Subject: " + message.subject);
  Serial.println();

  // Send email
  Serial.println("Connecting to Brevo SMTP server...");
  Serial.println("Server: smtp-relay.brevo.com:587");

  EMailSender::Response resp = emailSend.send(EMAIL_TO, message);

  // Print result
  Serial.println("\n--- Result ---");
  Serial.print("Status Code: ");
  Serial.println(resp.code);
  Serial.print("Description: ");
  Serial.println(resp.desc);
  Serial.print("Success: ");
  Serial.println(resp.status ? "YES ✓" : "NO ✗");

  if (resp.status) {
    Serial.println("\n✓✓✓ EMAIL SENT SUCCESSFULLY! ✓✓✓");
    Serial.println("Check your inbox at: " + String(EMAIL_TO));
  } else {
    Serial.println("\n✗✗✗ EMAIL SENDING FAILED! ✗✗✗");
    Serial.println("\nTroubleshooting:");
    Serial.println("1. Check Brevo credentials are correct");
    Serial.println("2. Verify sender email in Brevo dashboard");
    Serial.println("3. Check internet connection");
    Serial.println("4. Make sure port 587 is not blocked by firewall");
    Serial.println("5. Verify Brevo account is active");
  }

  Serial.println("\n========================================\n");
}


And here the output on Serial Monitor.

========================================
Arduino Mega + Brevo Email Example
========================================

Initializing Ethernet...
✓ Ethernet connected!
  IP Address: 192.168.1.54
  Gateway: 192.168.1.1
  Subnet Mask: 255.255.255.0
  DNS Server: 192.168.1.10

Preparing to send email...

--- Sending Email ---
From: xxx@xxx.xx
To: xxx@xxx.xx
Subject: Test from Arduino Mega + Brevo
Connecting to Brevo SMTP server...
Server: smtp-relay.brevo.com:587

--- Result ---
Status Code: 0
Description: Message sent!
Success: YES ✓

✓✓✓ EMAIL SENT SUCCESSFULLY! ✓✓✓
Check your inbox at: xxx@xxx.xx

========================================


Notes on the Code

  • Credentials: Replace the placeholders with your actual Brevo SMTP credentials.
  • Sender Email: The verified-sender@yourdomain.com address must match a sender you have verified in your Brevo dashboard.
  • Space in Message: Adding a leading space to message.message resolves a known bug where the first character could be cut off during transmission.

Sending Emails with SD Card Attachments

Arduino Mega Examples
ArduinoMega_EthernetW5500_Brevo_SD_AttachArduino MegaBrevo + SD❌ Port 587Email with SD card attachments

The EMailSender library excels at sending attachments. Here’s how to send a log.txt file from an SD card.

/*
 * EMailSender Library - Arduino Mega + Brevo + SD Card Attachment Example
 *
 * This sketch demonstrates how to send an email with a file attachment
 * from an SD card using an Arduino Mega, Ethernet Shield, and Brevo.
 *
 * HARDWARE:
 * - Arduino Mega 2560
 * - W5500 or W5100 Ethernet Shield
 * - MicroSD Card Reader Module
 * - MicroSD Card (formatted as FAT16 or FAT32)
 *
 * WIRING (Common SD Card Module):
 * - VCC  → 5V
 * - GND  → GND
 * - MISO → Pin 50 (shared with Ethernet)
 * - MOSI → Pin 51 (shared with Ethernet)
 * - SCK  → Pin 52 (shared with Ethernet)
 * - CS   → Pin 4 (or any other free digital pin)
 *
 * Author: Renzo Mischianti
 * Website: https://www.mischianti.org
 * Date: 2025-10-07
 */

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <EMailSender.h>

// ========== CONFIGURATION - UPDATE THESE VALUES ==========

// Brevo SMTP Credentials
const char* BREVO_LOGIN = "<YOUR-BREVO-SMTP-LOGIN>";
const char* BREVO_PASSWORD = "<YOUR-BREVO-SMTP-KEY>";

// Email addresses
const char* EMAIL_FROM = "<YOUR-EMAIL-VERIFIED-IN-BREVO>";
const char* EMAIL_TO = "<RECEIVER-EMAIL>";

// Network configuration
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// SD Card configuration
const int SD_CS_PIN = 4; // Chip Select pin for the SD card module

// ========== END CONFIGURATION ==========

EMailSender emailSend(
  BREVO_LOGIN,
  BREVO_PASSWORD,
  EMAIL_FROM,
  "ArduinoLogger", // Sender name (no spaces)
  "smtp-relay.brevo.com",
  587
);

void setup() {
  Serial.begin(115200);
  while (!Serial) { ; }

  Serial.println("\n==================================================");
  Serial.println("Arduino Mega + Brevo Email with SD Attachment");
  Serial.println("==================================================\n");

  // Initialize Ethernet
  Serial.println("Initializing Ethernet...");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("ERROR: DHCP configuration failed. Halting.");
    while (true);
  }
  Serial.println("✓ Ethernet connected!");
  Serial.print("  IP Address: ");
  Serial.println(Ethernet.localIP());
  delay(1500);

  // Initialize SD Card
  Serial.println("\nInitializing SD card...");
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("ERROR: SD card initialization failed! Check wiring and card format. Halting.");
    while (true);
  }
  Serial.println("✓ SD card ready.");

  // Send the email with an attachment
  sendEmailWithAttachment();
}

void loop() {
  Ethernet.maintain();
  delay(10000);
}

void sendEmailWithAttachment() {
  Serial.println("\n--- Sending Email with Attachment ---");

  // 1. Create a sample log file on the SD card
  Serial.println("Creating sample file 'datalog.txt' on SD card...");
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println("System Status Report");
    dataFile.print("Timestamp: ");
    dataFile.println(millis());
    dataFile.println("Temperature: 24.7 C");
    dataFile.println("Humidity: 55%");
    dataFile.println("Status: OK");
    dataFile.close();
    Serial.println("✓ File created successfully.");
  } else {
    Serial.println("ERROR: Failed to create file on SD card.");
    return;
  }

  // 2. Prepare the email message
  EMailSender::EMailMessage message;
  message.subject = "Daily System Report with Attachment";
  message.message = " Hello,\n\nPlease find the daily system log attached.\n\n- Arduino Monitoring System";
  message.mime = MIME_TEXT_PLAIN;

  // 3. Configure the attachment
  EMailSender::FileDescriptior fileDescriptor;
  fileDescriptor.filename = "datalog.txt";
  fileDescriptor.url = "/datalog.txt"; // Absolute path on the SD card
  fileDescriptor.mime = MIME_TEXT_PLAIN;
  fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
  fileDescriptor.encode64 = true; // Use Base64 encoding for reliability

  EMailSender::Attachments attachments;
  attachments.number = 1;
  attachments.fileDescriptor = &fileDescriptor;

  // 4. Send the email
  Serial.println("\nConnecting to Brevo SMTP server to send email...");
  EMailSender::Response resp = emailSend.send(EMAIL_TO, message, attachments);

  // 5. Print the result
  Serial.println("\n--- Result ---");
  Serial.print("Status Code: ");
  Serial.println(resp.code);
  Serial.print("Description: ");
  Serial.println(resp.desc);

  if (resp.status) {
    Serial.println("\n✓✓✓ EMAIL WITH ATTACHMENT SENT SUCCESSFULLY! ✓✓✓");
  } else {
    Serial.println("\n✗✗✗ EMAIL SENDING FAILED! ✗✗✗");
    Serial.println("\nTroubleshooting tips:");
    Serial.println(" - Double-check your Brevo credentials and sender email.");
    Serial.println(" - Ensure the SD card is working and the file path is correct.");
    Serial.println(" - Check your network connection and firewall settings.");
  }
  Serial.println("\n==================================================\n");
}

Working with Arduino UNO: A Memory-Optimized Approach

The Arduino UNO, with its tiny 2KB of RAM, presents a significant challenge. However, it’s still possible to send basic email notifications by carefully managing memory. The key is to disable the attachment feature in the library, as it consumes a large portion of the available RAM.

Disabling Attachments for Memory Savings

To make the EMailSender library lean enough for the UNO, you must disable the attachment functionality.

  1. Navigate to your Arduino libraries folder.
  2. Open the EMailSender folder.
  3. Edit the EMailSenderKey.h file.
  4. Find the following line:C++#define ENABLE_ATTACHMENTS
  5. Comment it out by adding // at the beginning:C++// #define ENABLE_ATTACHMENTS
  6. Save the file. This will exclude all attachment-related code from compilation, freeing up critical RAM.

Arduino UNO + Brevo: Memory-Optimized Example Code

Arduino UNO Examples
ArduinoUNO_EthernetShield_Brevo_BasicArduino UNOBrevo SMTP❌ Port 587OPTIMIZED – Only 58% RAM usage

This code is specifically designed to run within the tight memory constraints of the Arduino UNO. It sends a simple status report without attachments.

/*
 * EMailSender Library - Arduino UNO + Ethernet Shield + Brevo Basic Email
 *
 * This example shows how to send simple emails from Arduino UNO using minimal RAM.
 * Perfect for memory-constrained projects that need email notifications.
 *
 * MEMORY USAGE:
 * - RAM:   [======    ]  58.1% (used 1190 bytes from 2048 bytes)
 * - Flash: [=======   ]  70.8% (used 22832 bytes from 32256 bytes)
 * - No attachments to minimize memory usage (comment #define ENABLE_ATTACHMENTS in EMailSenderKey.h)
 *
 * WHY BREVO FOR ARDUINO UNO?
 * - No SSL/TLS required (UNO has only 2KB RAM)
 * - Port 587 with simple AUTH LOGIN
 * - 300 emails/day free tier
 *
 * HARDWARE:
 * - Arduino UNO R3
 * - W5100/W5500 Ethernet Shield
 * - Ethernet cable
 *
 * WIRING:
 * - Stack the shield on top of Arduino UNO
 * - MOSI → Pin 11, MISO → Pin 12, SCK → Pin 13, CS → Pin 10
 *
 * SETUP:
 * 1. Register at https://www.brevo.com
 * 2. Get SMTP credentials from SMTP & API settings
 * 3. Verify sender email address in Brevo dashboard
 * 4. Update credentials below
 *
 * Author: Renzo Mischianti
 * Website: https://www.mischianti.org
 * Library: https://github.com/xreef/EMailSender
 */

#include <SPI.h>
#include <Ethernet.h>
#include <EMailSender.h>

// ========== CONFIGURATION ==========
const char* BREVO_LOGIN = "your-login@smtp-brevo.com";
const char* BREVO_PASSWORD = "xsmtpsib-YOUR-API-KEY";
const char* EMAIL_FROM = "your-verified@example.com";
const char* EMAIL_TO = "recipient@example.com";
const char* SENDER_NAME = "ArduinoUNO";

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// Optional: Static IP (uncomment if needed)
// IPAddress ip(192, 168, 1, 177);
// IPAddress gateway(192, 168, 1, 1);
// IPAddress subnet(255, 255, 255, 0);

// ========== GLOBALS ==========
EMailSender emailSend(BREVO_LOGIN, BREVO_PASSWORD, EMAIL_FROM, SENDER_NAME, "smtp-relay.brevo.com", 587);

// ========== FUNCTIONS ==========
int freeRam() {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

bool initializeEthernet() {
  Serial.println(F("Initializing Ethernet..."));

  if (Ethernet.begin(mac) == 0) {
    Serial.println(F("DHCP failed!"));
    #ifdef ip
    Ethernet.begin(mac, ip, gateway, subnet);
    #else
    return false;
    #endif
  }

  delay(1500);

  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println(F("No Ethernet cable!"));
    return false;
  }

  Serial.print(F("IP: "));
  Serial.println(Ethernet.localIP());
  return true;
}

void sendEmail() {
  Serial.println(F("\n--- Sending Email ---"));
  Serial.print(F("Free RAM: "));
  Serial.print(freeRam());
  Serial.println(F(" bytes"));

  EMailSender::EMailMessage message;
  message.subject = F("Arduino UNO + Brevo Test");
  message.message = F(" Hello from Arduino UNO!\n\n");
  message.message += F("This email was sent using:\n");
  message.message += F("- Arduino UNO R3\n");
  message.message += F("- Ethernet Shield\n");
  message.message += F("- Brevo SMTP (port 587)\n");
  message.message += F("- EMailSender Library\n\n");
  message.message += F("System Info:\n- Free RAM: ");
  message.message += String(freeRam());
  message.message += F(" bytes\n- Uptime: ");
  message.message += String(millis() / 1000);
  message.message += F(" sec\n\n");
  message.message += F("---\nby Renzo Mischianti\n");
  message.message += F("mischianti.org\n");
  message.mime = MIME_TEXT_PLAIN;

  Serial.print(F("From: "));
  Serial.println(EMAIL_FROM);
  Serial.print(F("To: "));
  Serial.println(EMAIL_TO);
  Serial.println(F("Connecting to Brevo..."));

  EMailSender::Response resp = emailSend.send(EMAIL_TO, message);

  Serial.println(F("\n--- Result ---"));
  Serial.print(F("Code: "));
  Serial.println(resp.code);
  Serial.print(F("Status: "));
  Serial.println(resp.status ? F("✓ OK") : F("✗ FAILED"));

  if (!resp.status) {
    Serial.print(F("Error: "));
    Serial.println(resp.desc);
  }
}

// ========== MAIN ==========
void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println(F("\n=============================="));
  Serial.println(F("Arduino UNO + Brevo"));
  Serial.println(F("==============================\n"));
  Serial.print(F("Free RAM: "));
  Serial.print(freeRam());
  Serial.println(F(" bytes"));

  if (!initializeEthernet()) {
    Serial.println(F("Network init failed!"));
    while (1) {
      delay(5000);
      if (initializeEthernet()) break;
    }
  }

  Serial.println(F("✓ Network ready!\n"));
  sendEmail();
  Serial.println(F("\n=== Setup Complete ==="));
}

void loop() {
  Ethernet.maintain();
  delay(10000);
}

And here the result on serial monitor.

==============================
Arduino UNO + Brevo
==============================

Free RAM: 634 bytes
Initializing Ethernet...
IP: 192.168.1.54
✓ Network ready!


--- Sending Email ---
Free RAM: 634 bytes
From: renzo.mischianti@gmail.com
To: renzo.mischianti@gmail.com
Connecting to Brevo...

--- Result ---
Code: 0
Status: ✓ OK

=== Setup Complete ===

Key Optimizations in the UNO Code

  • Disabled Attachments: As instructed, this is the most critical step to free up RAM.
  • F() Macro: All literal strings like Serial.println(F("Hello")); are wrapped in the F() macro. This keeps them in Flash memory instead of copying them to RAM at startup.
  • Efficient String Building: The message body is constructed carefully to minimize the creation of temporary String objects, which can fragment the small amount of available RAM.
  • Memory Monitoring: The freeRam() function is included to help you monitor memory usage and diagnose potential issues.

Troubleshooting Common Issues

  • “Error: 220 -> …” or Timeout:
    • Verify that your Ethernet cable is properly connected.
    • Check that the SMTP server (smtp-relay.brevo.com) and port (587) are correct.
    • Ensure your network firewall is not blocking port 587.
  • “Error: 535 -> Authentication failed”:
    • Your credentials (Login or SMTP Key) are incorrect. Double-check the SMTP key from your Brevo dashboard.
    • Make sure your sender email address has been verified in Brevo.
  • SD Card Initialization Failed:
    • Check the wiring of your SD card module.
    • Ensure the SD_CS_PIN is correct and does not conflict with the Ethernet Shield’s CS pin (usually pin 10).

Library Specifications

Supported Platforms

PlatformWiFiEthernetSSL/TLSSTARTTLS
ESP32
ESP8266
Arduino Mega/Uno
Arduino SAMD
STM32
Raspberry Pi Pico (RP2040)

Arduino Mega and Uno DO NOT support SSL/TLS due to severe RAM limitations:

  • Arduino Mega has only 8KB of RAM
  • Arduino Uno has only 2KB of RAM
  • BearSSL for SSL/TLS requires at least 24KB of RAM for encryption buffers

Alternative solutions for Arduino Mega/Uno:

  1. ✅ Use non-secure SMTP (port 25) – Works but not recommended
  2. ✅ Use a local SMTP relay – Configure a local server that handles SSL
  3. ✅ Switch to ESP32/ESP8266 – They have more RAM and native SSL/TLS support
  4. ✅ Use Arduino SAMD (MKR WiFi 1010) – Has 32KB RAM and supports SSL/TLS

Arduino Mega/Uno examples in this library use only non-secure SMTP!

Supported Network Interfaces

  • WiFi (ESP32/ESP8266) – WiFiClient / WiFiClientSecure
  • WiFi (SAMD/MBED) – WiFiNINA library
  • Ethernet W5100/W5200/W5500 – Standard Ethernet library
  • Ethernet ENC28J60 – UIPEthernet library
  • Ethernet with SSL – SSLClient wrapper for secure connections

Supported Storage Systems

Internal Storage (Microcontroller Flash)

  • SPIFFS (ESP32, ESP8266)
  • LittleFS (ESP32, ESP8266, RP2040)
  • FFAT (ESP32)
  • SPIFM (SPI Flash with Adafruit_SPIFlash)

External Storage (SD/microSD Cards)

  • SD (Standard SD library)
  • SdFat (Version 1.x for RP2040/ESP8266)
  • SdFat2 (Version 2.x for modern platforms)

Library Features

HTML Email with Multiple Recipients

EMailSender::EMailMessage message;
message.subject = "HTML Email Test";
message.message = "<h1>Hello!</h1><p>This is an <b>HTML</b> email.</p>";
message.mime = MIME_TEXT_HTML;  // Set MIME type to HTML

// Multiple recipients
const char* recipients[] = {
  "recipient1@example.com",
  "recipient2@example.com",
  "recipient3@example.com"
};

EMailSender::Response resp = emailSend.send(recipients, 3, message);

Email with CC and BCC

// Array with To, Cc, and Bcc addresses
const char* allRecipients[] = {
  "to@example.com",      // To (1)
  "cc@example.com",      // Cc (1)
  "bcc@example.com"      // Bcc (1)
};

// send(recipients, numTo, numCc, numBcc, message)
EMailSender::Response resp = emailSend.send(allRecipients, 1, 1, 1, message);

Port 587 (STARTTLS) – Recommended for Gmail

STARTTLS starts with a plain connection and upgrades to encrypted.

// Enable internal SSLClient in EMailSenderKey.h
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT

// Use port 587
EMailSender emailSend("user@gmail.com", "app_password", 
                      "user@gmail.com", "Sender Name",
                      "smtp.gmail.com", 587);

// Enable EHLO (required for STARTTLS)
emailSend.setEHLOCommand(true);

Port 465 (Implicit SSL/TLS)

Connection is encrypted from the start.

// Use WiFiClientSecure (ESP32/ESP8266)
EMailSender emailSend("user@gmail.com", "app_password",
                      "user@gmail.com", "Sender Name", 
                      "smtp.gmail.com", 465);

// No additional configuration needed

Using SSLClient with Ethernet (Arduino/STM32)

For boards without native SSL support:

#define EMAIL_ENABLE_OPENSLAB_SSLCLIENT

// The library will use BearSSL-based SSLClient
// for secure connections over Ethernet

Advanced Features

Custom Authentication Methods

// Use AUTH PLAIN (SASL)
emailSend.setSASLLogin(true);

// Use CRAM-MD5 (ESP32 only)
emailSend.setCramMD5Login(true);

// Disable authentication (open relay)
emailSend.setUseAuth(false);

EHLO Configuration

// Use EHLO instead of HELO (recommended for modern servers)
emailSend.setEHLOCommand(true);

// Set custom identifier for HELO/EHLO
emailSend.setPublicIpDescriptor("mydevice");

Email with Attachments from SD Card

#include <SD.h>

// Initialize SD card
SD.begin(SD_CS_PIN);

// Prepare attachment
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "photo.jpg";
fileDescriptor.url = "/photo.jpg";  // Path on SD card
fileDescriptor.mime = MIME_IMAGE_JPG;
fileDescriptor.encode64 = true;  // Base64 encode
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

EMailSender::Attachments attachments;
attachments.number = 1;
attachments.fileDescriptor = &fileDescriptor;

// Send email with attachment
EMailSender::Response resp = emailSend.send("recipient@example.com", 
                                            message, 
                                            attachments);

Multiple Attachments

EMailSender::FileDescriptior files[3];

files[0].filename = "document.pdf";
files[0].url = "/docs/document.pdf";
files[0].mime = "application/pdf";
files[0].encode64 = true;
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

files[1].filename = "image.png";
files[1].url = "/images/image.png";
files[1].mime = MIME_IMAGE_PNG;
files[1].encode64 = true;
files[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

files[2].filename = "data.txt";
files[2].url = "/data.txt";
files[2].mime = MIME_TEXT_PLAIN;
files[2].encode64 = false;
files[2].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

EMailSender::Attachments attachments;
attachments.number = 3;
attachments.fileDescriptor = files;

EMailSender::Response resp = emailSend.send("recipient@example.com", 
                                            message, 
                                            attachments);

Attachments from SPIFFS/LittleFS/FFat (ESP32/ESP8266)

#include <SPIFFS.h>

// Initialize SPIFFS
SPIFFS.begin();

EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "config.json";
fileDescriptor.url = "/config.json";
fileDescriptor.mime = "application/json";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

// Or use LittleFS
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_LITTLE_FS;

// Or use FFAT
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_FFAT;

Storage type SPIFM

There is also support for SPI Flash, but it’s better if you refer to the specified tutorial.

// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFM;

Storage type String or Stream

String jsonData = "{\"device\":\"ESP32\",\"temp\":22.5,\"hum\":65.3}";

EMailSender::FileDescriptior files[1];

// JSON attachment
files[0].filename = "data.json";
files[0].mime = "application/json";
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[0].content = jsonData;
Stream* myDataStream = ...; // Your Stream implementation
size_t dataSize = 1024;     // Size of the data in bytes

EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "sensor_data.csv";
fileDescriptor.mime = "text/csv";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_STREAM;
fileDescriptor.stream = myDataStream;      // Pointer to Stream
fileDescriptor.streamSize = dataSize;      // Size is required!

Common MIME Types for String Attachments

File TypeMIME TypeUsage
JSONapplication/jsonAPI data, sensor readings
CSVtext/csvExcel compatible data
XMLapplication/xmlConfiguration files
Texttext/plainLogs, reports
HTMLtext/htmlFormatted documents
JavaScriptapplication/javascriptCode files

Storage Type Comparison

Storage TypeBest ForComplexityMemory Usage
EMAIL_STORAGE_TYPE_STRING📝 Dynamic text content⭐ Very EasyRAM only
EMAIL_STORAGE_TYPE_STREAM🔄 Custom data sources⭐⭐ MediumRAM streaming
EMAIL_STORAGE_TYPE_SD📁 Large files⭐⭐ MediumSD Card
EMAIL_STORAGE_TYPE_SPIFFS🔧 Small config files⭐⭐ MediumInternal Flash
EMAIL_STORAGE_TYPE_LITTLE_FS📊 Medium files (ESP32/ESP8266)⭐⭐ MediumInternal Flash
EMAIL_STORAGE_TYPE_FFAT📈 Large files (ESP32 only)⭐⭐ MediumInternal Flash

Gmail Configuration

To use Gmail, you need an App Password:

  1. Enable 2-Factor Authentication on your Google account
  2. Go to Google App Passwords
  3. Generate a new app password
  4. Use this 16-character password in your code

Gmail Settings:

  • SMTP Server: smtp.gmail.com
  • Port: 587 (STARTTLS) or 465 (SSL/TLS)
  • Authentication: Required

On ESP32 and ESP8266 you can enable the EMAIL_ENABLE_INTERNAL_SSLCLIENT on EMailSenderKey.h file to use STARTTLS on port 587

// If you want to ENABLE the internal SSLClient wrapper (needed for STARTTLS on port 587)
// instead of relying solely on the native secure client (e.g., WiFiClientSecure for 465),
// uncomment the following define. Enabling it increases flash and RAM usage
// but provides STARTTLS support on non-secure base clients.
//#define EMAIL_ENABLE_INTERNAL_SSLCLIENT

For port 465 and SSL/TLS, ESP32 and ESP8266 don’t need any additional library, but to use with STM32 and Ethernet (or other similar device), you can enable EMAIL_ENABLE_OPENSLAB_SSLCLIENT, a lightweight implementation of SSL.

// Enable integration with OPEnSLab-OSU SSLClient (BearSSL) per AVR/Ethernet o schede che ne hanno bisogno.
// Usa questo backend solo se hai INSTALLATO la libreria esterna "SSLClient" (OPEnSLab-OSU).
// STARTTLS (porta 587) NON è supportato da questo backend; è pensato per TLS implicito (465) su Client non-SSL.
// Di default DISABILITATO: abilitalo nel tuo sketch o nelle build flags definendo
//   - EMAIL_ENABLE_EXTERNAL_SSLCLIENT_OPENSLAB (preferito) oppure
//   - EMAIL_ENABLE_OPENSLAB_SSLCLIENT
// #define EMAIL_ENABLE_OPENSLAB_SSLCLIENT

API Reference

Constructor

EMailSender(const char* email_login, 
            const char* email_password);

EMailSender(const char* email_login, 
            const char* email_password,
            const char* email_from);

EMailSender(const char* email_login, 
            const char* email_password,
            const char* email_from,
            const char* name_from);

EMailSender(const char* email_login, 
            const char* email_password,
            const char* email_from,
            const char* name_from,
            const char* smtp_server,
            uint16_t smtp_port);

Configuration Methods

void setSMTPServer(const char* smtp_server);
void setSMTPPort(uint16_t smtp_port);
void setEMailLogin(const char* email_login);
void setEMailFrom(const char* email_from);
void setNameFrom(const char* name_from);
void setEMailPassword(const char* email_password);

void setUseAuth(bool useAuth);
void setEHLOCommand(bool useEHLO);
void setSASLLogin(bool isSASLLogin);
void setCramMD5Login(bool onoff);  // ESP32 only

void setPublicIpDescriptor(const char* descriptor);
void setAdditionalResponseLineOnConnection(uint8_t numLines);
void setAdditionalResponseLineOnHELO(uint8_t numLines);

Send Methods

// Single recipient
Response send(const char* to, EMailMessage &email, Attachments att = {0, 0});
Response send(String to, EMailMessage &email, Attachments att = {0, 0});

// Multiple recipients (To only)
Response send(const char* to[], byte sizeOfTo, EMailMessage &email, Attachments att = {0, 0});
Response send(String to[], byte sizeOfTo, EMailMessage &email, Attachments att = {0, 0});

// Multiple recipients with Cc
Response send(const char* to[], byte sizeOfTo, byte sizeOfCc, EMailMessage &email, Attachments att = {0, 0});

// Multiple recipients with Cc and Bcc
Response send(const char* to[], byte sizeOfTo, byte sizeOfCc, byte sizeOfCCn, EMailMessage &email, Attachments att = {0, 0});

Data Structures

// Email Message
struct EMailMessage {
    String mime = "text/html";  // or "text/plain"
    String subject;
    String message;
};

// File Descriptor for Attachments
struct FileDescriptior {
    StorageType storageType = EMAIL_STORAGE_TYPE_SD;
    String mime;
    bool encode64 = false;
    String filename;
    String url;  // Path to file
};

// Attachments
struct Attachments {
    byte number;
    FileDescriptior *fileDescriptor;
};

// Response
struct Response {
    String code;
    String desc;
    bool status = false;
};

Storage Types

enum StorageType {
    EMAIL_STORAGE_TYPE_SPIFFS,
    EMAIL_STORAGE_TYPE_LITTLE_FS,
    EMAIL_STORAGE_TYPE_FFAT,
    EMAIL_STORAGE_TYPE_SPIFM,
    EMAIL_STORAGE_TYPE_SD
};

MIME Types

Predefined MIME type constants:

MIME_TEXT_HTML    // "text/html"
MIME_TEXT_PLAIN   // "text/plain"
MIME_IMAGE_JPG    // "image/jpg"
MIME_IMAGE_PNG    // "image/png"

Configuration File (EMailSenderKey.h)

The library uses a configuration file to enable/disable features:

// Enable STARTTLS support with internal SSLClient (ESP32/ESP8266)
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT

// Enable OpenSLab SSLClient for Ethernet shields (Arduino/STM32)
#define EMAIL_ENABLE_OPENSLAB_SSLCLIENT

// Enable attachments support
#define ENABLE_ATTACHMENTS

// Enable date header management
#define MANAGE_DATE_HEADER

// Network type (auto-detected based on platform)
// EMAIL_NETWORK_TYPE can be:
// - NETWORK_ESP8266 (ESP8266 WiFi)
// - NETWORK_ESP32 (ESP32 WiFi)
// - NETWORK_W5100 (Ethernet W5100/W5200/W5500)
// - NETWORK_ENC28J60 (ENC28J60 Ethernet)
// - NETWORK_WiFiNINA (SAMD/Arduino WiFiNINA)
// - etc.

// Storage types
// INTERNAL_STORAGE can be: STORAGE_SPIFFS, STORAGE_LITTLEFS, STORAGE_FFAT
// EXTERNAL_STORAGE can be: STORAGE_SD, STORAGE_SDFAT2

Debug Mode

Enable debugging by uncommenting in EMailSenderKey.h:

#define EMAIL_SENDER_DEBUG
#define DEBUG_PRINTER Serial

This will print detailed SMTP communication to Serial Monitor.

Thanks

  1. Arduino Remote/wireless Programming
  2. BMP280, DHT11 and DHT22, DHT12, Dallas Temperature ds18b20, Thermistor
  3. ATtiny Programmer Board (ArduinoUNO As ISP)
  4. Send email with esp8266 and Arduino (Library v1.x)
  5. How to use SD card with esp8266 and Arduino
  6. Ebyte LoRa E32 device for Arduino, esp32 or esp8266: WOR (wake on radio) microcontroller and new Arduino shield
  7. Manage JSON file with Arduino, esp32 and esp8266
  8. How to interface Arduino, esp8266 or esp32 to RS-485
  9. Send emails with attachments (v2.x library): Arduino Ethernet
  10. WebSocket
  11. Arduino AVR: compiled binary (.hex) from command line and GUI tool
  12. Arduino: fast external SPI Flash memory
  13. GY-291 ADXL345 i2c spi accelerometer with interrupt for esp32, esp8266, stm32 and Arduino
  14. i2c Arduino: how to create network, parameters and address scanner
  15. GY-273 QMC5883L clone HMC5883L magnetometer for Arduino, esp8266 and esp32
  16. WiFi remote debugging of an Arduino with DT-06
  17. Program Arduino UNO Remotely via WiFi with DT-06 ESP-Link Firmware
  18. Introduction to Remote Programming of Arduino UNO via WiFi with ESP8266
  19. Remote WiFi debugging on Arduino Using ESP8266 (NodeMCU and ESP01) with ESP-LINK Firmware
  20. Arduino: manage GPS signal with GY NEO 6M and similar devices
  21. Arduino UNO/Mega and Ethernet: Sending Emails with Attachments (EMailSender v4.0.0 Library)

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *