Replies: 8 comments 9 replies
-
You asked the same question as on Arduino forum that I already answered. There are misunderstanding in your usage and library concept when I look at your providing code. If you read all comments in examples and test it enough to see how search and fetch examples work, you can adapt both of them to your code easily. Library works with IMAP command to make request and parsing response which a task can be a combination of multiple IMAP commands which need to be done sequentially. It is recommended that you should read the RFC standard related to IMAP/SMTP commands for using this library properly. Instead of asking here, you should check my latest reply with code that works based on your requirement in Arduino forum. Library provides a method for accessing the message in user mailbox via Library provides the 3 classes for transportation and data that passed to readMail funcion, ie.e. There are two IMAP commands that mainly used in this library which have different purposes i.e. SEARCH and FETCH. The SEARCH command will be used for searching the messages with some criteria which IMAP server returns only UID (if UID prodided in search criteria) or messages sequence number (if no UID keyword provided) in the response. Library will perform some additional operations by parsing that search result for UID or message number and collect them in atrray and fetching the message by its UID or number one by one (using FETCH command). Only message header will be fetched for faster operation and minimum memory usage as brief information of messages header only stored in the result i.e. message items data (list). You will see the debugging message about the searching operation when you test with search example. To determine which types of operation is being perform, call To read entire message content (header and body) of the message items returns from search operation, you need to store the UID or sequence number of messages in an array and iterate fetching the message by UID or number in that array one by one. The FETCH command will be used when you know which message to read or fetch. Library will perform fetch when one of these options are set. Now look at your code. When you use this line for searching, It will perform searching only when the function I see you are trying to print irrelevant information of search count in the function ESP_MAIL_PRINTF("Search Criteria Found: %d\n", sFolder.searchCount()); Using In the loop, you are trying to fetch message by providing the message number to The message number you provide is the count-down/count-up value initiated from total messages in your mailbox (using This will fetch whole messages in your opened mailbox one by one, then the debug info will be something like this in case only two messages stored in your mailbox. #### Fetch message 1, Number: 2
..
..
#### Fetch message 2, Number: 1
..
..
#### Fetch message 3, Number: 1
..
..
#### Fetch message 4, Number: 2
..
..
#### Fetch message 5, Number: 1
..
..
#### Fetch message 6, Number: 1
..
..
#### Fetch message 7, Number: 2
..
..
If your mailbox contains 100 messages, the debug message will show Number: 100 to Number: 1 during count down and Number: 1 to Number: 100 during count up. Based on your needs, do something like this is not make sense as search does not perform and You should start with search, then store the UID or number of messages from search result. ( Once you keep the UID or message number of your messages result into array already, now you can iterate fetching that message to get the whole message data later. Here is the code that I modified from my latest post in Arduino forum based on your needs. In this code we work with message UID instead of message number. #include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT esp_mail_imap_port_993
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void imapCallback(IMAP_Status status);
void printMessageData();
IMAPSession imap;
// Max messages in the search result
int max_result = 10;
// Array to store the UID of messages in search result
int msg_uid[10];
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();
MailClient.networkReconnect(true);
imap.debug(1);
imap.callback(imapCallback);
Session_Config config;
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
IMAP_Data imap_data;
// 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 = 2048;
imap_data.limit.attachment_size = 1024 * 1024 * 5;
if (!imap.connect(&config, &imap_data))
return;
if (!imap.selectFolder(F("INBOX")))
return;
// We search the messages first to get its UID and stored in msg_uid.
imap_data.search.criteria = F("SEARCH SUBJECT ardudi@gmail.com");
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();
// 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 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();
}
Finally, you can't use If you define it here in your code, it will be seen only in your sketch. Library can't see this definition. This macro is already defined globally here. Library will look for definitions in library provided ESP_Mail_FS.h or Custom_ESP_Mail_FS.h you created. Edit: |
Beta Was this translation helpful? Give feedback.
-
I'm not quite sure that what information you used to justify that you can't get unread message from search or fetch examples. If you mean Info of the selected folder
Total Messages: 2
UID Validity: 1
Predicted next UID: 138
Search Criteria Found: 0
Unseen Message Index: 0
Highest Modification Sequence: 20759
Flags: \Answered, \Flagged, \Draft, \Deleted, \Seen, $NotPhishing, $Phishing The above information is the properties of selected (opened) mailbox and is not related to searching or fetching operation. The Unseen Message Index from method The default value of unseen index is 0 which means no unread messages in selected mailbox, or all messages have been read. The valid index of unseen message is 1 to total messages stored in selected mailbox. |
Beta Was this translation helpful? Give feedback.
-
Thank you so much for your explanation above, As you may understand, I am not so strong in C++ and actually didn't understand in deep the IMAP procedure. Your above code and your explanation were made perfectly. Now the code performs exactly what I want. |
Beta Was this translation helpful? Give feedback.
-
Great. I'll give a try. Thanks again. I do ecellant support! |
Beta Was this translation helpful? Give feedback.
-
Very well. I'll wait. I also saw another issue. When I used msg.deleteMessages for a specific email in gmail using msg.UID or message number, although I got indication that the message was removed, nothing happend in my Gmail inbox. I am working on this... |
Beta Was this translation helpful? Give feedback.
-
Please see my partial code vs. its consule monitor. I made a kinf of 'correction' to the CR+LF extra characters that were added to the message text:
Consule output: Reading messages...Finished reading EmailNumber: 1 --->>> Message Text (UID = 136) is wrong, remove message... Open the mailbox folder...Deleting message(s)...Message 1 deleted Connecting to IMAP server...IMAP server connectedChecking the capability...Logging in...Send client identification...Open the mailbox folder...Fetch message 1, UID: 136Get Flags...Reading messages...Finished reading EmailNumber: 1 --->>> Message Text (UID = 136) is wrong, remove message... Open the mailbox folder...Deleting message(s)...Message 1 deleted Fetch message 2, UID: 142Get Flags...Finished reading Email |
Beta Was this translation helpful? Give feedback.
-
The line break issue fixed in v3.1.12. |
Beta Was this translation helpful? Give feedback.
-
Thanks.🙏 I'll give a try. |
Beta Was this translation helpful? Give feedback.
-
I use Wemos D1 mini as an IoT device. The device should receive once in a time an email with few parameters which are contained in the message body. Message subject line also composed of specific text.
I have modified Read_Single_Email_Loop example to reduce memory usage and consumption of the device.
My email Inbox contains only 2 unread emails. Surprisingly, the example I use doesn't return and indication for unread emails (return unseen=0). Also I define a search criteria to search sublect line content but always return 0. I am attching here my modified code. You may see that I defined ENABLE_ERROR_STRING, imap_data.search.criteria = F("SUBJECT ardudi@gmail.com") and added ESP_MAIL_PRINTF("Search Criteria Found: %d\n", sFolder.searchCount());
As you may see, I also captured the serial consule output during runtime. Would appreciate any comment on this.
Modified_Read_Single_Email_Loop2.zip
Modified_Read_Single_Email_Loop2 - consule.txt
Beta Was this translation helpful? Give feedback.
All reactions