ESP Mail Client sample code generating errors when added to working sketch for ESP8266

I have a simple sketch that creates as AP, gets initial WiFi Credentials, saves them to EEPROM and then connects to the network and starts sending temperature settings to a webpage via AJAX - all that works fine.

I have used the ESP_Mail_Client.h library and successfully compiled and used the sample code.

I then added the elements from the sample code for the ESP Mail Client with the intention of sending an email to an email confirming the IP address of the sensor.
Now the code fails with the following error message:

c:/users/jonat/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\jonat\AppData\Local\arduino\sketches\45BE1717CFE693B94CD9D796FEFD6A57\sketch\objs.a(test3.ino.cpp.o): in function _ZN12SMTP_MessageD2Ev': C:\Users\jonat\Documents\Arduino\libraries\ESP_Mail_Client\src/ESP_Mail_Client.h:456: undefined reference to _Z12smtpCallback11SMTP_Status'
collect2.exe: error: ld returned 1 exit status
Multiple libraries were found for "SD.h"
Used: C:\Users\jonat\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\SD
Not used: C:\Users\jonat\AppData\Local\Arduino15\libraries\SD
exit status 1

Compilation error: exit status 1

I have tried copying all the libraries used in my code to the sample Mail Client code and it still compiles fine. The board is the same in both sets of code.

I can't understand what is generating the errors - if it was a libary clash then I would expect it to happen when I added the other libraries to the ESP_Mail_Client sample.

Can anyone please shed any light on this ?

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP_Mail_Client.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <EEPROM.h>
#include <Hash.h>
  
HTTPClient sender; 

/*#define PIN_WiFi D5
#define PIN_HighTemp D7
#define PIN_LowTemp D6
#define PIN_Power D8
#define PIN_Buzzer D1
#define PIN_PowerFail D0
*/

#define oneWireBus D4
const int EEPROM_SIZE = 554; // intergers are 4 bytes - so 16, strings are 16+32+50+3 bytes for string length - so 

/** 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 */
// deleted the content below !!
#define AUTHOR_EMAIL "deleted@gmail.com"
#define AUTHOR_PASSWORD "deleted"
/* Recipient's email*/
#define RECIPIENT_EMAIL "deleted@gmail.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);

// define addresses for eeprom
byte ssidadd=1;
byte passwordadd=17;
byte emailadd=50;
byte mintempadd=101;
byte maxtempadd=106;
byte minbetweenadd=111;
byte minbeforeadd=116;
byte engemailadd= 121;
byte alexaadd= 172;
byte dnameadd= 223;
byte locadd = 254;
bool myconfigured = false;
int Alarm = LOW;

String html_1;
String html_2;
String html_3;
String html_4;
String html_5;
String htmlMsg;

// load default values for EEPROM

char ssid[16] = "";
char password[32] = "";
char alertEmail[50] = "";
int minTempAlert = -1;
int maxTempAlert = 5;
int minutesBetweenAlerts = 30;
int minutesBeforeAlert = 5;
char engEmail[50] = "";
char alexa[50] = "";
char dname[30] = "";
char loc[300] = "";

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);


void saveSettings() {
  // save settings back to EEPROM
    EEPROM.begin(EEPROM_SIZE);
    delay(200);
    EEPROM.put(mintempadd, minTempAlert);
    EEPROM.put(maxtempadd, maxTempAlert);
    EEPROM.put(minbetweenadd, minutesBetweenAlerts);
    EEPROM.put(minbeforeadd, minutesBeforeAlert);
    EEPROM.put(emailadd, alertEmail);
    EEPROM.put(engemailadd, engEmail);
    EEPROM.put(alexaadd, alexa);
    EEPROM.put(dnameadd, dname);
    EEPROM.put(locadd, loc);
    Serial.println("Data loaded to EEPROM");
    EEPROM.end();
    delay(700);
}

void loadSettings() {
// load settings from EEPROM
    EEPROM.begin(EEPROM_SIZE);
    EEPROM.get(ssidadd, ssid);
    EEPROM.get(passwordadd, password);
    EEPROM.get(mintempadd, minTempAlert);
    EEPROM.get(maxtempadd, maxTempAlert);
    EEPROM.get(minbetweenadd, minutesBetweenAlerts);
    EEPROM.get(minbeforeadd, minutesBeforeAlert);
    EEPROM.get(emailadd, alertEmail);
    EEPROM.get(engemailadd, engEmail);
    EEPROM.get(alexaadd, alexa);
    EEPROM.get(dnameadd, dname);
    EEPROM.get(locadd, loc);
    EEPROM.end();    
}

ESP8266WebServer server(80);

void saveCredentials(String newSsid, String newPass, String email) {
    // save settings from AP set up in EEPROM
    EEPROM.begin(EEPROM_SIZE);
    delay(200);
     EEPROM.put(ssidadd, newSsid);
     EEPROM.put(passwordadd, newPass);
     EEPROM.put(emailadd, email);  
     EEPROM.put(0,true); // defines the initial configuration is complete and EEPROM can be trusted.
    EEPROM.end();
    delay(500);
}

void loadCredentials() {
    //load saved WiFoi Credentials from EEPROM
    EEPROM.begin(EEPROM_SIZE);
      EEPROM.get(ssidadd, ssid);
      EEPROM.get(passwordadd, password);
    EEPROM.end();
}

void handleRoot() {
  String html = "<!DOCTYPE html>";
  html += "<html lang='en'>";
  html += "<head>";
  // deleted additional html code
  html += "            margin: 5px 0;"; 
  html += "</html>";
  server.send(200, "text/html", html);
}

void handleSaveWifi() {
    if (server.hasArg("ssid") && server.hasArg("password")) {
        String newSsid = server.arg("ssid");
        String newPass = server.arg("password");
        String newEmail = server.arg("email");
        server.arg("email").toCharArray(alertEmail, 50);       
        saveCredentials(newSsid, newPass, newEmail);
        String html = "<h1 style='text-align: center;'><span style='color: #3366ff;'>Settings saved!</span></h1>";
          html += "<h1 style='text-align: center;'>Sensor is now restarting and connecting to WiFi network" + newSsid + ".</h1>";
          html += "<h1 style='text-align: center;'>When connected Email with address will be sent to "+ String(newEmail) +".</h1>";
          html += "<p style='text-align: center;'>&nbsp;</p>";
        server.send(200, "text/html", html);
        saveSettings();
        delay(2000);
        ESP.restart();
    } else {
        server.send(400, "text/html", "<h3>Invalid Request</h3>");
    }
}

void startAccessPoint() {
    WiFi.mode(WIFI_AP);
    WiFi.softAP("Fridge_Sensor", "password");
    server.on("/", handleRoot);
    server.on("/save", HTTP_POST, handleSaveWifi);
    server.begin();
    Serial.println("Soft AP started");
    Serial.print("IP Address: ");
    Serial.println(WiFi.softAPIP());
}

void handleMain() {
  String html = "<!DOCTYPE html>";
  html += "<html lang='en'>";
  // deleted the rest as it just builds an html string
  html += "</body>";
  html += "</html>"; 
  server.send(200, "text/html", html);
}

/** Web Page for contacts **/

void handleSettings() {
  String html = "<!DOCTYPE html>";
  html += "<html lang='en'>";
  // deleted the rest as it just builds an html string
  html += "</html>";
  server.send(200, "text/html", html);
}

/** Web Page for temperatures **/

void handletemp() {
  String htmlt = "<!DOCTYPE html>";
  htmlt += "<html lang='en'>";
  // deleted the rest as it just builds an html string
  htmlt += "</html>";
  server.send(200, "text/html", htmlt);
}

void handleSavetemp() {
  if (server.hasArg("lowTemp") && server.hasArg("highTemp") && server.hasArg("alertDelay") && server.hasArg("alertFreq")) {
    minTempAlert = server.arg("lowTemp").toInt();
    maxTempAlert = server.arg("highTemp").toInt();
    minutesBetweenAlerts = server.arg("alertFreq").toInt();
    minutesBeforeAlert = server.arg("alertDelay").toInt();
    saveSettings();
    String html = "<h1 style='text-align: center;'>Settings saved successfully</h1>";
    html += "<h1 style='text-align: center;'>Click <a href='/index'>Here</a> to return to front page</h1>";
    html += "<p>&nbsp;</p>";
    server.send(200, "text/html", html);
  } else {
    String html = "<h1 style='text-align: center;'><span style='color: #ff0000;'>Something went wrong.</span></h1>";
    html += "<h1 style='text-align: center;'>Click <a href='/index'>Here</a> to return to front page</h1>";
    html += "<p>&nbsp;</p>";
    server.send(400, "text/html", "<h3>Invalid Request</h3>");
  }
}

void handleSaveadd() {
  Serial.println(server.hasArg("alertEmail"));
  Serial.println("Save request received");
  if (server.hasArg("alertEmail") && server.hasArg("alexaAlert") && server.hasArg("engineerEmail") && server.hasArg("deviceName") && server.hasArg("deviceAddress")) {
    server.arg("alertEmail").toCharArray(alertEmail, 50);
    server.arg("alexaAlert").toCharArray(alexa, 50);
    server.arg("engineerEmail").toCharArray(engEmail, 50);
    server.arg("deviceName").toCharArray(dname, 30);
    server.arg("deviceAddress").toCharArray(loc, 300);
    saveSettings();
    String html = "<h1 style='text-align: center;'>Settings saved successfully</h1>";
    html += "<h1 style='text-align: center;'>Click <a href='/index'>Here</a> to return to front page</h1>";
    html += "<p>&nbsp;</p>";
    server.send(200, "text/html", html);
  } else {
    String html = "<h1 style='text-align: center;'><span style='color: #ff0000;'>Something went wrong.</span></h1>";
    html += "<h1 style='text-align: center;'>Click <a href='/index'>Here</a> to return to front page</h1>";
    html += "<p>&nbsp;</p>";
    server.send(400, "text/html", "<h3>Invalid Request</h3>");
  }
}


void handleRoot2() 
{
  String webpage = "<!DOCTYPE html>";
  webpage += "<html lang='en'>";
  // deleted the rest as it just builds an html string
  webpage += "</html>";
  server.send(200, "text/html", webpage);
}

void sensor_data() 
// sends temp to webpage
{
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);
  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }

  String sensor_value = String(tempC);
  server.send(200, "text/plane", sensor_value);
}

void state() 
// sends status to webpage
{
  String state = "All good";
  server.send(200, "text/plane", state);
}

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize gpio Pins
  /*pinMode(PIN_HighTemp, OUTPUT);
  pinMode(PIN_WiFi, OUTPUT);
  pinMode(PIN_LowTemp, OUTPUT);
  pinMode(PIN_Power, OUTPUT);
  pinMode(PIN_Buzzer, OUTPUT);
  pinMode(PIN_PowerFail, INPUT);
*/
  // Start the Serial Monitor
  Serial.begin(115200);

  // Start the DS18B20 sensor
  sensors.begin();

  // get saved WiFo credentials from EEPROM
  EEPROM.begin(EEPROM_SIZE);
  EEPROM.get(ssidadd, ssid);
  EEPROM.get(passwordadd, password);
  EEPROM.get(0, myconfigured);
  delay(200);
  EEPROM.end();
  delay(200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to Wi-Fi...");
  int retries = 0;
  while (WiFi.status() != WL_CONNECTED && retries < 20) {
    delay(500);
    Serial.print(".");
    retries++;
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Connected!");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());
    if (myconfigured) {
        
      //  connected to internet !!
      loadSettings();
      Serial.println("Loading configuration");
      // send sample email (test)
      /*  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(0);
      /* 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 = 3;
      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 = "Hello World! - Sent from ESP board";
      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());


    } else {
      Serial.println("Failed to connect, starting AP mode...");
      startAccessPoint();
    }


  }
  else{
    Serial.println("Skipping Configuration as going to AP mode");
     }

  // Start the server   
  server.on("/", handleMain);     
  server.on("/index", handleMain);
  server.on("/settings", handleSettings);
  server.on("/temps", handletemp);
  server.on("/saveadd", HTTP_POST, handleSaveadd);
  server.on("/savetemp", HTTP_POST, handleSavetemp);
  server.on("/current-status", handleRoot2);
  server.on("/state", state);
  server.on("/adcread", sensor_data);
  server.begin();
 
  }
// the loop function runs over and over again forever
void loop() {

server.handleClient();

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.