Sending text via gmail on ESP32 and ESP8266

I am trying to send at text message by emailing it to text.com. It works great on the ESP8266 using code from http://www.instructables.com/id/ESP8266-GMail-Sender/ .

When I run the same program it timesout on the last step. Any ideas why? Here is the transaction for the ESP32

Connecting to :smtp.gmail.com
220 smtp.gmail.com ESMTP h82sm13795626itb.38 - gsmtp

HELO friend:
250 smtp.gmail.com at your service

AUTH LOGIN:
334 BASE64stuff

EMAILBASE64_LOGIN:
334 EMAILBASE64stuff

EMAILBASE64_PASSWORD:
235 2.7.0 Accepted

MAIL FROM: myemail@gmail.com
250 2.1.0 OK h82sm13795626itb.38 - gsmtp

RCPT TO: 505myphone#@vtext.com
250 2.1.5 OK h82sm13795626itb.38 - gsmtp

DATA:
354 Go ahead h82sm13795626itb.38 - gsmtp

From: myemail@gmail.com
To: 505myphone#@vtext.com
Subject: Message from ESP8266!
Mime-Version: 1.0
Content-Type: text/html; charset=“UTF-8”
Content-Transfer-Encoding: 7bit

Setup test

.
Error sending message: Sending message error

It timesout at the . above.

for the esp8266 I get the following after the .

250 2.0.0 OK 1518619810 196sm16798858ioz.36 - gsmtp

221 2.0.0 closing connection 196sm16798858ioz.36 - gsmtp

hi karma,here is code for SMTP gmail sender using esp32

/ Arduino core for ESP32 WiFi chip SMTP Gmail sender

  • by jubaid hossain
  • 4.9.2018
  • you can copy and paste full code
    */
    main code

#include <WiFi.h>
#include “Gsender.h”
#include <WiFiClientSecure.h>

#pragma region Globals
const char* ssid = “xxxx”; // WIFI network name
const char* password = “xxxx”; // WIFI network password
uint8_t connection_state = 0; // Connected to WIFI or not
uint16_t reconnect_interval = 10000; // If not connected wait time to try again
#pragma endregion Globals

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
static uint16_t attempt = 0;
Serial.print("Connecting to ");
if(nSSID) {
WiFi.begin(nSSID, nPassword);
Serial.println(nSSID);
} else {
WiFi.begin(ssid, password);
Serial.println(ssid);
}

uint8_t i = 0;
while(WiFi.status()!= WL_CONNECTED && i++ < 50)
{
delay(200);
Serial.print(".");
}
++attempt;
Serial.println("");
if(i == 51) {
Serial.print("Connection: TIMEOUT on attempt: ");
Serial.println(attempt);
if(attempt % 2 == 0)
Serial.println(“Check if access point available or SSID and Password\r\n”);
return false;
}
Serial.println(“Connection: ESTABLISHED”);
Serial.print("Got IP address: ");
Serial.println(WiFi.localIP());
return true;
}

void Awaits()
{
uint32_t ts = millis();
while(!connection_state)
{
delay(200);
if(millis() > (ts + reconnect_interval) && !connection_state){
connection_state = WiFiConnect();
ts = millis();
}
}
}

void setup()
{
Serial.begin(115200);
connection_state = WiFiConnect();
if(!connection_state) // if not connected to WIFI
Awaits(); // constantly trying to connect

Gsender *gsender = Gsender::Instance(); // Getting pointer to class instance
String subject = “Subject is optional!”;
if(gsender->Subject(subject)->Send(“xxxxxxxxxxx@gmail.com”, “hi here is testing email”)) {
Serial.println(“Message send.”);
} else {
Serial.print("Error sending message: ");
Serial.println(gsender->getError());
}
}

void loop(){}

Gsender.cpp

#include “Gsender.h”
Gsender* Gsender::_instance = 0;
Gsender::Gsender(){}
Gsender* Gsender::Instance()
{
if (_instance == 0)
_instance = new Gsender;
return _instance;
}

Gsender* Gsender::Subject(const char* subject)
{
delete _subject;
_subject = new char[strlen(subject)+1];
strcpy(_subject, subject);
return _instance;
}
Gsender* Gsender::Subject(const String &subject)
{
return Subject(subject.c_str());
}

bool Gsender::AwaitSMTPResponse(WiFiClientSecure &client, const String &resp, uint16_t timeOut)
{
uint32_t ts = millis();
while (!client.available())
{
if(millis() > (ts + timeOut)) {
_error = “SMTP Response TIMEOUT!”;
return false;
}
}
_serverResponce = client.readStringUntil(’\n’);
#if defined(GS_SERIAL_LOG_1) || defined(GS_SERIAL_LOG_2)
Serial.println(_serverResponce);
#endif
if (resp && _serverResponce.indexOf(resp) == -1) return false;
return true;
}

String Gsender::getLastResponce()
{
return _serverResponce;
}

const char* Gsender::getError()
{
return _error;
}

bool Gsender::Send(const String &to, const String &message)
{
WiFiClientSecure client;
#if defined(GS_SERIAL_LOG_2)
Serial.print(“Connecting to :”);
Serial.println(SMTP_SERVER);
#endif
if(!client.connect(SMTP_SERVER, SMTP_PORT)) {
_error = “Could not connect to mail server”;
return false;
}
if(!AwaitSMTPResponse(client, “220”)) {
_error = “Connection Error”;
return false;
}

#if defined(GS_SERIAL_LOG_2)
Serial.println(“HELO friend:”);
#endif
client.println(“HELO friend”);
if(!AwaitSMTPResponse(client, “250”)){
_error = “identification error”;
return false;
}

#if defined(GS_SERIAL_LOG_2)
Serial.println(“AUTH LOGIN:”);
#endif
client.println(“AUTH LOGIN”);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“EMAILBASE64_LOGIN:”);
#endif
client.println(EMAILBASE64_LOGIN);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“EMAILBASE64_PASSWORD:”);
#endif
client.println(EMAILBASE64_PASSWORD);
if (!AwaitSMTPResponse(client, “235”)) {
_error = “SMTP AUTH error”;
return false;
}

String mailFrom = “MAIL FROM: <” + String(FROM) + ‘>’;
#if defined(GS_SERIAL_LOG_2)
Serial.println(mailFrom);
#endif
client.println(mailFrom);
AwaitSMTPResponse(client);

String rcpt = “RCPT TO: <” + to + ‘>’;
#if defined(GS_SERIAL_LOG_2)
Serial.println(rcpt);
#endif
client.println(rcpt);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“DATA:”);
#endif
client.println(“DATA”);
if(!AwaitSMTPResponse(client, “354”)) {
_error = “SMTP DATA error”;
return false;
}

client.println(“From: <” + String(FROM) + ‘>’);
client.println(“To: <” + to + ‘>’);

client.print("Subject: ");
client.println(_subject);

client.println(“Content-Type: text/html; charset=“UTF-8"”);
client.println(“Content-Transfer-Encoding: 7bit”);
client.println();
String body = “<html lang=“en”>” + message + “”;
// String body = message;
client.println(body);
client.println(”.");
if (!AwaitSMTPResponse(client, “250”)) {
_error = “Sending message error”;
return false;
}
client.println(“QUIT”);
if (!AwaitSMTPResponse(client, “221”)) {
_error = “SMTP QUIT error”;
return false;
}

return true;
}

Gsender.h

/* Gsender class helps send e-mails from Gmail account

  • using Arduino core for ESP32 WiFi chip
  • by jubaid hossain
  • 4.9.2018
  • you can copy and paste full code , here i am using Gsender library from boris
    */
    #ifndef G_SENDER
    #define G_SENDER
    #define GS_SERIAL_LOG_1 // Print to Serial only server responce
    //#define GS_SERIAL_LOG_2 // Print to Serial client commands and server responce
    #include <WiFiClientSecure.h>

class Gsender
{
protected:
Gsender();
private:
const int SMTP_PORT = 465;
const char* SMTP_SERVER = “smtp.gmail.com”;
const char* EMAILBASE64_LOGIN = “xxxxxxxxxxxxxxxxxxxxxxxxx”;//64 bit encoded email address name
const char* EMAILBASE64_PASSWORD = “xxxxxxxxxxxxxxx”;//64 bit encoded email password
const char* FROM = “xxxxxxxx”;//email
const char* _error = nullptr;
char* _subject = nullptr;
String _serverResponce;
static Gsender* _instance;
bool AwaitSMTPResponse(WiFiClientSecure &client, const String &resp = “”, uint16_t timeOut = 60000);

public:
static Gsender* Instance();
Gsender* Subject(const char* subject);
Gsender* Subject(const String &subject);
bool Send(const String &to, const String &message);
String getLastResponce();
const char* getError();
};
#endif // G_SENDER

jubaid_:
hi karma,here is code for SMTP gmail sender using esp32

/ Arduino core for ESP32 WiFi chip SMTP Gmail sender

  • by jubaid hossain
  • 4.9.2018
  • you can copy and paste full code
    */
    main code

#include <WiFi.h>
#include “Gsender.h”
#include <WiFiClientSecure.h>

#pragma region Globals
const char* ssid = “xxxx”; // WIFI network name
const char* password = “xxxx”; // WIFI network password
uint8_t connection_state = 0; // Connected to WIFI or not
uint16_t reconnect_interval = 10000; // If not connected wait time to try again
#pragma endregion Globals

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
static uint16_t attempt = 0;
Serial.print("Connecting to ");
if(nSSID) {
WiFi.begin(nSSID, nPassword);
Serial.println(nSSID);
} else {
WiFi.begin(ssid, password);
Serial.println(ssid);
}

uint8_t i = 0;
while(WiFi.status()!= WL_CONNECTED && i++ < 50)
{
delay(200);
Serial.print(".");
}
++attempt;
Serial.println("");
if(i == 51) {
Serial.print("Connection: TIMEOUT on attempt: ");
Serial.println(attempt);
if(attempt % 2 == 0)
Serial.println(“Check if access point available or SSID and Password\r\n”);
return false;
}
Serial.println(“Connection: ESTABLISHED”);
Serial.print("Got IP address: ");
Serial.println(WiFi.localIP());
return true;
}

void Awaits()
{
uint32_t ts = millis();
while(!connection_state)
{
delay(200);
if(millis() > (ts + reconnect_interval) && !connection_state){
connection_state = WiFiConnect();
ts = millis();
}
}
}

void setup()
{
Serial.begin(115200);
connection_state = WiFiConnect();
if(!connection_state) // if not connected to WIFI
Awaits(); // constantly trying to connect

Gsender *gsender = Gsender::Instance(); // Getting pointer to class instance
String subject = “Subject is optional!”;
if(gsender->Subject(subject)->Send(“xxxxxxxxxxx@gmail.com”, “hi here is testing email”)) {
Serial.println(“Message send.”);
} else {
Serial.print("Error sending message: ");
Serial.println(gsender->getError());
}
}

void loop(){}

Gsender.cpp

#include “Gsender.h”
Gsender* Gsender::_instance = 0;
Gsender::Gsender(){}
Gsender* Gsender::Instance()
{
if (_instance == 0)
_instance = new Gsender;
return _instance;
}

Gsender* Gsender::Subject(const char* subject)
{
delete _subject;
_subject = new char[strlen(subject)+1];
strcpy(_subject, subject);
return _instance;
}
Gsender* Gsender::Subject(const String &subject)
{
return Subject(subject.c_str());
}

bool Gsender::AwaitSMTPResponse(WiFiClientSecure &client, const String &resp, uint16_t timeOut)
{
uint32_t ts = millis();
while (!client.available())
{
if(millis() > (ts + timeOut)) {
_error = “SMTP Response TIMEOUT!”;
return false;
}
}
_serverResponce = client.readStringUntil(’\n’);
#if defined(GS_SERIAL_LOG_1) || defined(GS_SERIAL_LOG_2)
Serial.println(_serverResponce);
#endif
if (resp && _serverResponce.indexOf(resp) == -1) return false;
return true;
}

String Gsender::getLastResponce()
{
return _serverResponce;
}

const char* Gsender::getError()
{
return _error;
}

bool Gsender::Send(const String &to, const String &message)
{
WiFiClientSecure client;
#if defined(GS_SERIAL_LOG_2)
Serial.print(“Connecting to :”);
Serial.println(SMTP_SERVER);
#endif
if(!client.connect(SMTP_SERVER, SMTP_PORT)) {
_error = “Could not connect to mail server”;
return false;
}
if(!AwaitSMTPResponse(client, “220”)) {
_error = “Connection Error”;
return false;
}

#if defined(GS_SERIAL_LOG_2)
Serial.println(“HELO friend:”);
#endif
client.println(“HELO friend”);
if(!AwaitSMTPResponse(client, “250”)){
_error = “identification error”;
return false;
}

#if defined(GS_SERIAL_LOG_2)
Serial.println(“AUTH LOGIN:”);
#endif
client.println(“AUTH LOGIN”);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“EMAILBASE64_LOGIN:”);
#endif
client.println(EMAILBASE64_LOGIN);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“EMAILBASE64_PASSWORD:”);
#endif
client.println(EMAILBASE64_PASSWORD);
if (!AwaitSMTPResponse(client, “235”)) {
_error = “SMTP AUTH error”;
return false;
}

String mailFrom = “MAIL FROM: <” + String(FROM) + ‘>’;
#if defined(GS_SERIAL_LOG_2)
Serial.println(mailFrom);
#endif
client.println(mailFrom);
AwaitSMTPResponse(client);

String rcpt = “RCPT TO: <” + to + ‘>’;
#if defined(GS_SERIAL_LOG_2)
Serial.println(rcpt);
#endif
client.println(rcpt);
AwaitSMTPResponse(client);

#if defined(GS_SERIAL_LOG_2)
Serial.println(“DATA:”);
#endif
client.println(“DATA”);
if(!AwaitSMTPResponse(client, “354”)) {
_error = “SMTP DATA error”;
return false;
}

client.println(“From: <” + String(FROM) + ‘>’);
client.println(“To: <” + to + ‘>’);

client.print("Subject: ");
client.println(_subject);

client.println(“Content-Type: text/html; charset=“UTF-8"”);
client.println(“Content-Transfer-Encoding: 7bit”);
client.println();
String body = “<html lang=“en”>” + message + “”;
// String body = message;
client.println(body);
client.println(”.");
if (!AwaitSMTPResponse(client, “250”)) {
_error = “Sending message error”;
return false;
}
client.println(“QUIT”);
if (!AwaitSMTPResponse(client, “221”)) {
_error = “SMTP QUIT error”;
return false;
}

return true;
}

Gsender.h

/* Gsender class helps send e-mails from Gmail account

  • using Arduino core for ESP32 WiFi chip
  • by jubaid hossain
  • 4.9.2018
  • you can copy and paste full code , here i am using Gsender library from boris
    */
    #ifndef G_SENDER
    #define G_SENDER
    #define GS_SERIAL_LOG_1 // Print to Serial only server responce
    //#define GS_SERIAL_LOG_2 // Print to Serial client commands and server responce
    #include <WiFiClientSecure.h>

class Gsender
{
protected:
Gsender();
private:
const int SMTP_PORT = 465;
const char* SMTP_SERVER = “smtp.gmail.com”;
const char* EMAILBASE64_LOGIN = “xxxxxxxxxxxxxxxxxxxxxxxxx”;//64 bit encoded email address name
const char* EMAILBASE64_PASSWORD = “xxxxxxxxxxxxxxx”;//64 bit encoded email password
const char* FROM = “xxxxxxxx”;//email
const char* _error = nullptr;
char* _subject = nullptr;
String _serverResponce;
static Gsender* _instance;
bool AwaitSMTPResponse(WiFiClientSecure &client, const String &resp = “”, uint16_t timeOut = 60000);

public:
static Gsender* Instance();
Gsender* Subject(const char* subject);
Gsender* Subject(const String &subject);
bool Send(const String &to, const String &message);
String getLastResponce();
const char* getError();
};
#endif // G_SENDER

[i hunt you]

Are you going to do a version that supports both ESP32 and ESP8266??

// Select processor options
#ifdef ARDUINO_ARCH_ESP32
  #include <WiFi.h>
  #include "Gsender.h"
  #include <WiFiClientSecure.h>
#endif
#ifdef ARDUINO_ARCH_ESP8266
  #include <ESP8266WiFi.h>
  #include "Gsender.h"
  #include <WiFiClientSecure.h>
#endif

looks like issue in ESP32 is a EXTRA * on first line....

and I needed to comment out // main code

*/* Arduino core for ESP32 WiFi chip SMTP Gmail sender

Can multiple recipients be set up? I need the email to go to 3 different addresses.

Try to add separated addresses within the quotes by inserting ";" to see if that works. I've not tried it yet.

for example:

Send("mail1@gmail.com;mail2@gmail.com;mail3@gmail.com", "hi here is testing email"))

[b]Simple Mail Transfer Protocol[/b]

https://tools.ietf.org/html/rfc2821

[b][iurl=https://tools.ietf.org/html/rfc2821#section-4.1.1.3][/iurl][/b]

4.1.1.3 RECIPIENT (RCPT)

This command is used to identify an individual recipient of the mail
data; multiple recipients are specified by multiple use of this
command.

So you or your library have to use multiple of this

RCPT TO: 505myphone#@vtext.com

Hi,
I tried this code on ESP32, and its not working.
Can any one confirm that.
Regards

@ zoomx was right.

I fixed the libraries and sketch to allow for both single and multiple email recipients.

This is for ESP32, but the same changes to sketch, .cpp and .h files should work.

String address[] = {"email_1", "email_2"};

/*if (gsender->Subject(subject)->Send("to_email_address", "ESP32 Test Email!")) //for one recipients
  {
    Serial.println("Message send.");
  }*/

  if (gsender->Subject(subject)->Send(2, address, "ESP32 Test Email!")) //for multiple recipients
  {
    Serial.println("Message send.");
   }

There is a second "Send" function in .cpp now

bool Gsender::Send(int num, const String to[], const String &message)

...and the .h file

bool Send(const String &to, const String &message);
bool Send(int num, const String to[], const String &message);

So now in the sketch you can send an array of email addresses as recipients.