Library (v3.1.16) crashes when WiFi connection is lost while fetching messages
dkalliv opened this issue · 2 comments
Build tool used:
- Arudino
- Platformio (Visual Studio Code plugin)
- Platformio CLI
- Other
Board used (ESP32/ESP8266/Arudino):
- ESP8266-based
- ESP32-based
Other Libraries That are used:
Description of problem:
As it is possible that my project will be used with weak WiFi connections, I am conducting stability tests by deliberately interrupting the WiFi connection at various execution stages. I noticed, that the application will crash, when the connection is interrupted while fetching messages. I used the Search_And_Read.ino example (only added my WiFi and IMAP credentials) to reproduce the issue. While my application will recover after the reboot, it would be nice, if the library would catch the exception and fail gracefully. I've included the serial log and backtrace below:
Share code snippet to reproduce the issue:
/**
* This example shows how to search the unread messages and read them.
*
* To get the incoming mail notification, see Mailbox_Changes_Notification.ino.
*
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*
*/
/**
* To use library in silent mode (no debug printing and callback), please define this macro in src/ESP_Mail_FS.h.
* #define SILENT_MODE
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#else
#endif
#include <ESP_Mail_Client.h>
#include <extras/SDHelper.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT 993
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void imapCallback(IMAP_Status status);
void printAllMailboxesInfo(IMAPSession &imap);
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
void printMessageData();
IMAPSession imap;
Session_Config config;
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
// Max messages in the search result
int max_result = 5;
// Array to store the UID of messages in search result
int msg_uid[5];
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
Serial.println();
Serial.println("**** Custom built WiFiNINA firmware need to be installed.****\n");
Serial.println("To install firmware, read the instruction here, https://github.com/mobizt/ESP-Mail-Client#install-custom-build-wifinina-firmware");
#endif
Serial.println();
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
multi.addAP(WIFI_SSID, WIFI_PASSWORD);
multi.run();
#else
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#endif
Serial.print("Connecting to Wi-Fi");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
if (millis() - ms > 10000)
break;
#endif
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
/** 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
*/
imap.debug(1);
/* Set the callback function to get the reading results */
imap.callback(imapCallback);
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
// Clear all these fetch options to perform search
imap_data.fetch.uid.clear();
imap_data.fetch.number.clear();
imap_data.fetch.sequence_set.string.clear();
imap_data.search.unseen_msg = true;
// Don't download all to filesystem
imap_data.download.header = false;
imap_data.download.text = false;
imap_data.download.html = false;
imap_data.download.attachment = false;
imap_data.download.inlineImg = false;
// Store html/text message body in IMAPSession object
imap_data.enable.html = true;
imap_data.enable.text = true;
imap_data.enable.recent_sort = true;
// Max messages in the search result
imap_data.limit.search = max_result;
imap_data.limit.msg_size = 128;
if (!imap.connect(&config, &imap_data))
{
ESP_MAIL_PRINTF("Connection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
printAllMailboxesInfo(imap);
if (!imap.selectFolder(F("INBOX")))
{
ESP_MAIL_PRINTF("Folder selection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
printSelectedMailboxInfo(imap.selectedFolder());
// We search the unseen messages first to get its UID and stored in msg_uid.
imap_data.search.criteria = F("SEARCH UNSEEN");
MailClient.readMail(&imap, false /* keep session open for fetching message in opened mailbox later */);
// We already get the search result message, fetch it
// Fetch the messages using UID stored in msg_uid one by one
for (int i = 0; i < max_result; i++)
{
imap_data.search.criteria.clear();
// Mark this message as read
MailClient.addFlag(&imap, msg_uid[i], F("\\Seen"), false /* Close session */, false /* Ignore response */);
// Now Fech message by UID stored in msg_uid
imap_data.fetch.uid = msg_uid[i];
MailClient.readMail(&imap, false /* keep session open for fetching message in opened mailbox later */);
}
imap.closeSession();
imap.empty();
}
void loop()
{
}
void imapCallback(IMAP_Status status)
{
Serial.println(status.info());
if (status.success())
{
// If this is the search result (imap contains only header info),
// store the message UID that we can fetch for its body later.
if (imap.headerOnly())
{
max_result = imap.data().msgItems.size();
for (size_t i = 0; i < imap.data().msgItems.size(); i++)
msg_uid[i] = imap.data().msgItems[i].UID;
}
else
{
// This is the fetch result, print the whole message (header + body)
printMessageData();
}
imap.empty();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
FoldersCollection folders;
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
FolderInfo folderInfo = folders.info(i);
ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
ESP_MAIL_PRINTF("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
ESP_MAIL_PRINTF("UID Validity: %d\n", sFolder.uidValidity());
ESP_MAIL_PRINTF("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
ESP_MAIL_PRINTF("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
ESP_MAIL_PRINTF("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
ESP_MAIL_PRINTF("Highest Modification Sequence: %d\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printMessageData()
{
IMAP_MSG_Item msg = imap.data().msgItems[0]; // msgItems contains only one message from fetch
Serial.println("****************************");
ESP_MAIL_PRINTF("Number: %d\n", msg.msgNo);
ESP_MAIL_PRINTF("UID: %d\n", msg.UID);
ESP_MAIL_PRINTF("Messsage-ID: %s\n", msg.ID);
ESP_MAIL_PRINTF("Flags: %s\n", msg.flags);
ESP_MAIL_PRINTF("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
if (strlen(msg.acceptLang))
ESP_MAIL_PRINTF("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
ESP_MAIL_PRINTF("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
ESP_MAIL_PRINTF("From: %s\n", msg.from);
if (strlen(msg.sender))
ESP_MAIL_PRINTF("Sender: %s\n", msg.sender);
if (strlen(msg.to))
ESP_MAIL_PRINTF("To: %s\n", msg.to);
if (strlen(msg.cc))
ESP_MAIL_PRINTF("CC: %s\n", msg.cc);
if (strlen(msg.date))
{
ESP_MAIL_PRINTF("Date: %s\n", msg.date);
ESP_MAIL_PRINTF("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
ESP_MAIL_PRINTF("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
ESP_MAIL_PRINTF("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
ESP_MAIL_PRINTF("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
ESP_MAIL_PRINTF("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
ESP_MAIL_PRINTF("References: %s\n", msg.references);
if (strlen(msg.comments))
ESP_MAIL_PRINTF("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
ESP_MAIL_PRINTF("Keywords: %s\n", msg.keywords);
if (strlen(msg.text.content))
ESP_MAIL_PRINTF("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
ESP_MAIL_PRINTF("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
ESP_MAIL_PRINTF("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
ESP_MAIL_PRINTF("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
ESP_MAIL_PRINTF("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
ESP_MAIL_PRINTF("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
Serial.println();
}
Additional information and things you've tried:
Info of the selected folder
Total Messages: 88
UID Validity: 402270099
Predicted next UID: 4644
First Unseen Message Number: 2
Flags: \Answered, \Flagged, \Deleted, \Seen, \Draft, $MDNSent, $Hidden, $Media, $Forwarded, Junk, $Label1, $Label2, $Label3
Permanent Flags: \Answered, \Flagged, \Deleted, \Seen, \Draft, $MDNSent, $Hidden, $Media, $Forwarded, Junk, $Label1, $Label2, $Label3
#### Searching messages...
> C: searching messages
[ 7169][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 20 bytes...
[ 7174][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
> C: [# ] 9 %
> C: [## ] 14 %
> C: [### ] 19 %
> C: [#### ] 25 %
> C: [##### ] 35 %
> C: [###### ] 40 %
> C: [####### ] 45 %
> C: [######## ] 50 %
> C: [######### ] 60 %
> C: [########## ] 65 %
> C: [########### ] 70 %
> C: [############ ] 75 %
> C: [############# ] 85 %
> C: [############## ] 90 %
> C: [############### ] 95 %
> C: [################] 100 %
#### Search limit: 128
Found 88 messages
Show 88 messages
#### Fetch message 1, UID: 4641
> C: send IMAP command, FETCH
> C: fetch message header
[ 7567][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 233 bytes...
[ 7571][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
#### Get Flags...
> C: get Flags
[ 8186][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 22 bytes...
[ 8189][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
> C: Free Heap: 198416
#### Fetch message 2, UID: 4640
> C: send IMAP command, FETCH
> C: fetch message header
[ 8530][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 233 bytes...
[ 8539][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
#### Get Flags...
> C: get Flags
[ 8911][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 22 bytes...
[ 8914][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
> C: Free Heap: 197680
#### Fetch message 3, UID: 4639
> C: send IMAP command, FETCH
> C: fetch message header
[ 9145][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 233 bytes...
[ 9153][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
#### Get Flags...
> C: get Flags
[ 9506][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 22 bytes...
[ 9508][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
> C: Free Heap: 196768
#### Fetch message 4, UID: 4638
> C: send IMAP command, FETCH
> C: fetch message header
[ 9759][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 233 bytes...
[ 9767][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
#### Get Flags...
> C: get Flags
[ 9976][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 22 bytes...
[ 9980][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
> C: Free Heap: 196336
#### Fetch message 5, UID: 4636
> C: send IMAP command, FETCH
> C: fetch message header
[ 10302][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 233 bytes...
[ 10310][V][ESP32_SSL_Client.cpp:534] send_ssl_data(): Writing request with 2 bytes...
[ 18865][V][WiFiGeneric.cpp:362] _arduino_event_cb(): STA Disconnected: SSID: Rotten Apple II, BSSID: 4a:67:36:f2:af:11, Reason: 200
[ 18867][D][WiFiGeneric.cpp:1035] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
[ 18874][W][WiFiGeneric.cpp:1057] _eventCallback(): Reason: 200 - BEACON_TIMEOUT
[ 18882][D][WiFiGeneric.cpp:1081] _eventCallback(): WiFi AutoReconnect Running
> C: cleaning SSL connection[ 18890][V][WiFiGeneric.cpp:97] set_esp_interface_ip(): Configuring Station static IP: 0.0.0.0, MASK: 0.0.0.0, GW: 0.0.0.0
[ 18912][V][ESP32_SSL_Client.cpp:503] stop_tcp_connection(): Cleaning SSL connection.
#### Error, connection closed
! E: connection closed
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d2dea PS : 0x00060330 A0 : 0x800d2e3f A1 : 0x3ffb1d00
A2 : 0x000000dc A3 : 0x00000014 A4 : 0x00000000 A5 : 0x3ffd99d0
A6 : 0x3f41dfd1 A7 : 0x00000000 A8 : 0x00000012 A9 : 0x3ffb1cd0
A10 : 0x3ffb1d18 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000017 EXCCAUSE: 0x0000001c
EXCVADDR: 0x000000e0 LBEG : 0x4008a6a1 LEND : 0x4008a6b1 LCOUNT : 0xfffffffb
Backtrace: 0x400d2de7:0x3ffb1d00 0x400d2e3c:0x3ffb1d20 0x400d2e72:0x3ffb1d40 0x400dc115:0x3ffb1d60 0x400e31c2:0x3ffb1da0 0x400e5f92:0x3ffb20d0 0x400d3c69:0x3ffb21a0 0x400ee206:0x3ffb2290
and here is the decoded backtrace:
Decoding stack results
0x400d2de7: MB_String::_reserve(unsigned int, bool) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/extras/MB_String.h line 1785
0x400d2e3c: MB_String::copy(char const*, unsigned int) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/extras/MB_String.h line 1766
0x400d2e72: MB_String::operator=(char const*) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/extras/MB_String.h line 972
0x400dc115: ESP_Mail_Client::reconnect(IMAPSession*, unsigned long, bool) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/ESP_Mail_IMAP.h line 2641
0x400e31c2: ESP_Mail_Client::handleIMAPResponse(IMAPSession*, int, bool) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/ESP_Mail_IMAP.h line 2731
0x400e5f92: ESP_Mail_Client::readMail(IMAPSession*, bool) at /home/dkal/Arduino/libraries/ESP_Mail_Client/src/ESP_Mail_IMAP.h line 683
0x400d3c69: setup() at /home/dkal/Arduino/Search_And_Read_test/Search_And_Read_test.ino line 182
0x400ee206: loopTask(void*) at /home/dkal/.arduino15/packages/esp32/hardware/esp32/2.0.9/cores/esp32/main.cpp line 42
Thank you for fixing this, works very well!