Sending messages with Telegram, Whatsapp and Email

Sending Messages with the ESP8266 and ESP32

Would you like to send messages with your ESP8266 or ESP32, for example to receive a warning from a motion detector or temperature sensor? In this tutorial, you’ll learn three ways to implement this – via Telegram, email, and WhatsApp.

Contents of this tutorial:

  1. Sending messages via Telegram
  2. Sending emails
  3. Sending messages via WhatsApp

Sending Messages via Telegram

A common option is to send messages via Telegram – more specifically to a Telegram bot. You can then read these messages immediately on your smartphone. On Pollux Labs, there are several projects that use Telegram, such as a Dash Button or a photo trap with the ESP32-CAM. Telegram is particularly interesting for the latter project because it’s also possible to send images.

First, you need a Telegram bot. You can learn how to set this up in no time in this tutorial. You also need the UniversalTelegramBot library, which you can find in the Arduino IDE’s library manager. Make sure to install the latest version and keep the library up to date. If the version in the library manager is outdated, you can always find the latest version for download on GitHub.

Here’s the example sketch for your ESP8266. This sends a message after the board starts:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// Your WiFi Credentials
const char* ssid = "YOUR NETWORK";
const char* password = "YOUR PASSWORD";

// Your Bot Token
#define botToken "YOURTOKEN"  // this token you get from the Botfather)

//Your User ID
#define userID "YOUR USER ID"

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

void setup() {
  Serial.begin(115200);
  client.setInsecure();

  // Connect to WiFi
  Serial.print("Connecting to: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.println("Connected!");

  bot.sendMessage(userID, "Hey there, this is your ESP8266.", "");
}

void loop() {
}

After uploading, the following message should appear in your Telegram app:

How the Sketch Works

After including the required libraries (the first two are already pre-installed), you need to add some data. These are your WiFi credentials as well as your bot token and user ID. If you don’t have the latter two yet, take a look at our tutorial linked above first.

Then you initialize the WifiClient and the UniversalTelegramBot with respective instances:

WiFiClientSecure client;
UniversalTelegramBot bot(botToken, client);

In the setup, you then establish the connection to your WiFi. Once the connection is established, you use the bot.sendMessage function to send a message to your Telegram bot:

bot.sendMessage(userID, "Hey there, this is your ESP8266.", "");

The first parameter in this function is your userID, which you specified at the beginning of the sketch – followed by the message you want to send. And that’s basically it! You can now adapt this pattern for your project by sending the message, for example, when a certain temperature is exceeded – the content of the message could then be the current measured value.

Sending a Telegram Message with the ESP32

Of course, you can also send messages via Telegram with an ESP32 or an ESP32-CAM instead of the ESP8266. For this, you only need to exchange one library. Instead of ESP8266WiFI.h, use WiFi.h.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

And: To send a correct message, you can adjust the content. 😉

bot.sendMessage(userID, "Hey there, this is your ESP32", "");

Sending Emails with the ESP8266 or ESP32

After Telegram, let’s look at the classic of electronic messages, emails. In this tutorial, we use the Gmail service to send emails. Even if you already have a Gmail address, we recommend creating a brand new email address for experimenting. If something goes wrong, e.g., an account suspension because your ESP8266 accidentally sends countless emails in quick succession, your private email address won’t be affected.

To create a new address, first go to Gmail here and click on Create Account. Once your account is set up, you need an app password that your ESP8266 can use. To create an app password, open your Google Account and click on the Security menu item. Then click on the menu item Two-Step Verification and follow the instructions to activate this two-factor authentication – it’s the prerequisite for an app password.

Once you’re done with the setup, open Security > Two-Step Verification again and scroll all the way down to the App Passwords entry. Now create a password for Email and select Other (custom name) as the device. Then you can assign a name, e.g., ESP8266 or ESP32.

That’s it for the preparations, now let’s move on to an example sketch that sends an email to you.

Sending an Email

First, you need a library that you can install via the library manager: ESP Mail Client:

Install ESP Mail Client library

After installation, you can turn directly to the sketch. In this tutorial, we use the sketch from the RandomNerdTutorials blog, which is a very good starting point for this topic. In the following sketch, you only need to make a few adjustments. Enter your data at the following points:

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID" //YOUR NETWORK
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" //YOUR WIFI PASSWORD
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com" //YOUR GMAIL ADDRESS
#define AUTHOR_PASSWORD "YOUR_EMAIL_APP_PASS" //YOUR APP PASSWORD
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com" //EMAIL ADDRESS OF THE RECEIVER

The entire sketch:

/*
  Rui Santos
  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.
  Example adapted from: https://github.com/mobizt/ESP-Mail-Client
*/

#include <Arduino.h>
#if defined(ESP32)
  #include <WiFi.h>
#elif defined(ESP8266)
  #include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>

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

/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

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

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

/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;

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

void setup(){
  Serial.begin(115200);
  Serial.println();
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  /*  Set the network reconnection option */
  MailClient.networkReconnect(true);

  /** Enable the debug via Serial port
   * 0 for no debugging
   * 1 for basic level debugging
   *
   * Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h
   */
  smtp.debug(1);

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

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

  /* Set the session config */
  config.server.host_name = SMTP_HOST;
  config.server.port = SMTP_PORT;
  config.login.email = AUTHOR_EMAIL;
  config.login.password = AUTHOR_PASSWORD;
  config.login.user_domain = "";

  /*
  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 = 1;
  config.time.day_light_offset = 0;
  */

  /* Declare the message class */
  SMTP_Message message;

  /* Set the message headers */
  message.sender.name = F("ESP");
  message.sender.email = AUTHOR_EMAIL;
  message.subject = F("ESP Test Email");
  message.addRecipient(F("Sara"), RECIPIENT_EMAIL);
    
  /*Send HTML message*/
  /*String htmlMsg = "<div style=\"color:#2f4468;\"><h1>Hello World!</h1><p>- Sent from ESP board</p></div>";
  message.html.content = htmlMsg.c_str();
  message.html.content = htmlMsg.c_str();
  message.text.charSet = "us-ascii";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/

   
  //Send raw text message
  String textMsg = "Hallo Mensch!";
  message.text.content = textMsg.c_str();
  message.text.charSet = "us-ascii";
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
  
  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;


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

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

  /* Start sending Email and close the session */
  if (!MailClient.sendMail(&smtp, &message))
    ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());

}

void loop(){
}

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

  /* Print the sending result */
  if (status.success()){
    // ESP_MAIL_PRINTF used in the examples is for format printing via debug Serial port
    // that works for all supported Arduino platform SDKs e.g. AVR, SAMD, ESP32 and ESP8266.
    // In ESP8266 and ESP32, you can use Serial.printf directly.

    Serial.println("----------------");
    ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
    ESP_MAIL_PRINTF("Message sent failed: %d\n", status.failedCount());
    Serial.println("----------------\n");

    for (size_t i = 0; i < smtp.sendingResult.size(); i++)
    {
      /* Get the result item */
      SMTP_Result result = smtp.sendingResult.getItem(i);

      // In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
      // your device time was synched with NTP server.
      // Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
      // You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
      
      ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
      ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
      ESP_MAIL_PRINTF("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
      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();
  }
}

How the Sketch Works

Above, you’ve already learned about the places you need to adjust to make the sketch work. You can also set your time zone to give the email the correct timestamp:

config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 1;
config.time.day_light_offset = 0;

The gmt_offset for Germany (i.e., the distance from Greenwich Mean Time) would be 1 in this example – in winter time. In summer, it’s 2 hours.

You enter the subject and the sender or recipient name here:

/* Set the message headers */
message.sender.name = F("SENDER NAME");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("SUBJECT");
message.addRecipient(F("RECIPIENT NAME"), RECIPIENT_EMAIL);

You’ll find the actual message here:

//Send raw text message
String textMsg = "Hey there!";

Here you can, of course, also send variables depending on what makes sense in your own project. Upload the sketch with your adjustments to your ESP8266 or ESP32. In the Serial Monitor, you can follow how the email is sent and finally arrives in your recipient’s inbox.

The above sketch works for both the ESP8266 and the ESP32. No adjustments are necessary when switching boards.

Sending a WhatsApp Message with the ESP8266 and ESP32

Let’s come to the third way to let your ESP8266 or ESP32 send a message: WhatsApp. The prerequisite here is an external service. In the following, we use CallMeBot.com – a free API that allows you to send WhatsApp text messages to your smartphone.

This doesn’t require complex registration, you just need to briefly register your mobile number with the API to receive an API key. You can access the official instructions via the link above – or simply follow these steps:

  1. Add the following number to your contacts via WhatsApp (you can choose the contact name freely): +34 644 71 81 99
  2. Then send the following message to this number: I allow callmebot to send me messages
  3. You will then receive a reply with your API key – and that’s it
Get the API key von callmebot.com

The Library for Encoding Messages

To be able to send messages via WhatsApp, you also need a library that you can quickly install via the library manager: UrlEncode

You need this because the messages are transmitted via a URL – e.g., like this:

https://api.callmebot.com/whatsapp.php?phone=+49123123123&text=Dieser+Text+ist+codiert&apikey=123123

The library you’re about to install takes care of formatting your message string into the correct format. So open the library manager and search for UrlEncode. Then install the latest version.

Install UrlEncode in the Arduino IDE

Sending the WhatsApp Message

Here’s the complete sketch to send a WhatsApp message with your ESP8266:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <UrlEncode.h>

const char* ssid = "YOUR WIFI NETWORK";
const char* password = "YOUR PASSWORD";

// including area code, for example: +49176999888777
String phoneNumber = "YOUR MOBILE NUMBER";
String apiKey = "YOUR API KEY";

void sendMessage(String message) {

  // Data to be sent
  String url = "http://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);
  WiFiClient client;
  HTTPClient http;
  http.begin(client, url);

  // Header
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");

  // HTTP Post request
  int httpResponseCode = http.POST(url);
  if (httpResponseCode == 200) {
    Serial.print("Message sent successfully");
  } else {
    Serial.println("Error sending the message");
    Serial.print("HTTP response code: ");
    Serial.println(httpResponseCode);
  }

  http.end();
}

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  // WhatsApp message
  sendMessage("Hey, this is your ESP8266 speaking.");
}

void loop() {
}

At the beginning of the sketch, you again enter your WiFi credentials. You also need your own mobile number, which you must enter in international format (e.g., for Germany starting with +49). Finally, enter your API key that you received via WhatsApp message:

Everything else in the sketch is for connecting to your WiFi and the API request (in the sendMessage(String message) function). Quite near the end, you can enter your text message to be sent:

// WhatsApp message
sendMessage("Hey, this is your ESP8266 speaking.");
}

Upload the sketch to your ESP8266. After uploading, the corresponding message should appear on your smartphone within a few seconds.

Sending the WhatsApp Message with the ESP32

If you want to use an ESP32 or an ESP32-CAM instead of an ESP8266, you only need to include a few different libraries at the beginning of the sketch:

#include <WiFi.h>
#include <HTTPClient.h>
#include <UrlEncode.h>

You can keep the rest of the sketch without further adjustments. Please note that with CallMeBot you can only send pure text messages (which can of course also contain variables). Unfortunately, sending images doesn’t work with this service. If you plan to do this, it’s better to use Telegram or take a look at textmebot.com – however, this API is chargeable.

Conclusion

In this tutorial, you’ve learned three methods to send messages – via Telegram, email, or WhatsApp. You can find suitable projects on Pollux Labs: For example, you could expand the ESP8266 weather station with warnings that you receive as soon as certain measured values are exceeded or fallen below.