Skip to content

Commit

Permalink
Add IMAP sendCustomData function and add IMAP append message example.
Browse files Browse the repository at this point in the history
  • Loading branch information
mobizt committed Jun 16, 2022
1 parent 79926b5 commit 2b1454c
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/compile_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
matrix:
example:
- "examples/IMAP/Copy_Messages/Copy_Messsages.ino"
- "examples/IMAP/Custom_Command/Append_Message/Append_Message.ino"
- "examples/IMAP/Custom_Command/Basic_Auth/Basic_Auth.ino"
- "examples/IMAP/Custom_Command/Custom_Auth/Custom_Auth.ino"
- "examples/IMAP/DataStreamCallback/DataStreamCallback.ino"
Expand Down Expand Up @@ -90,6 +91,7 @@ jobs:
matrix:
example:
- "examples/IMAP/Copy_Messages/Copy_Messsages.ino"
- "examples/IMAP/Custom_Command/Append_Message/Append_Message.ino"
- "examples/IMAP/Custom_Command/Basic_Auth/Basic_Auth.ino"
- "examples/IMAP/Custom_Command/Custom_Auth/Custom_Auth.ino"
- "examples/IMAP/DataStreamCallback/DataStreamCallback.ino"
Expand Down
177 changes: 177 additions & 0 deletions examples/IMAP/Custom_Command/Append_Message/Append_Message.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/**
* This example shows how to append new message to mailbox using the custom IMAP command.
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2022 mobizt
*
*/

/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/

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

// Other Client defined here
// To use custom Client, define ENABLE_CUSTOM_CLIENT in src/ESP_Mail_FS.h.
// See the example Custom_Client.ino for how to use.

#endif

#include <ESP_Mail_Client.h>

// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.h.

#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"

/** For Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
*
* Some Gmail user still not able to sign in using account password even above options were set up,
* for this case, use "App Password" to sign in instead.
* About Gmail "App Password", go to https://support.google.com/accounts/answer/185833?hl=en
*
* For Yahoo mail, log in to your yahoo mail in web browser and generate app password by go to
* https://login.yahoo.com/account/security/app-passwords/add/confirm?src=noSrc
*
* To use Gmai and Yahoo's App Password to sign in, define the AUTHOR_PASSWORD with your App Password
* and AUTHOR_EMAIL with your account email.
*/

/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
#define IMAP_HOST "<host>"

/** The imap port e.g.
* 143 or esp_mail_imap_port_143
* 993 or esp_mail_imap_port_993
*/
#define IMAP_PORT 993

/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"

/* The IMAP Session object used for Email reading */
IMAPSession imap;

void customCommandCallback(IMAP_Response res)
{
// The server responses will included tagged and/or untagged data.

// Tagged data is the status which begins with command identifier (tag) i.e. "A01" in this case.
// Tagged status responses included OK, NO, BAD, PREAUTH and BYE.

// Untagged data is the information or result of the request which begins with *

// When you send multiple commands with different tag simultaneously,
// tag will be used as command identifier.

Serial.print("> C: TAG ");
Serial.println(res.tag.c_str());
Serial.print("< S: ");
Serial.println(res.text.c_str());

if (res.completed)
{
Serial.print("> C: Response finished with status ");
Serial.println(res.status.c_str());
Serial.println();
}
}

void setup()
{

Serial.begin(115200);

#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
Serial.println();
Serial.println("**** Custom built WiFiNINA firmware need to be installed.****\nTo install firmware, read the instruction here, https://github.com/mobizt/ESP-Mail-Client#install-custom-built-wifinina-firmware");

#endif

Serial.println();

Serial.print("Connecting to AP");

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(200);
}

Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();

/* Declare the session config data */
ESP_Mail_Session session;

/* Set the session config */
session.server.host_name = IMAP_HOST;
session.server.port = IMAP_PORT;

/* Connect to server with the session and config */
if (!imap.customConnect(&session, customCommandCallback, F("A01") /* tag */))
return;

String cmd = F("LOGIN ");
cmd += AUTHOR_EMAIL;
cmd += F(" ");
cmd += AUTHOR_PASSWORD;

// You can also assign tag to the begining of the command e.g. "A01 FETCH 1 UID"
// Do not assign tag to command when you assign tag to the last parameter of function.

imap.sendCustomCommand(cmd, customCommandCallback, F("A02") /* tag */);

imap.sendCustomCommand(F("SELECT \"INBOX\""), customCommandCallback, F("A03") /* tag */);

imap.sendCustomCommand(F("LIST \"\" *"), customCommandCallback, F("A04") /* tag */);

String appendMsg = "Date: Thu, 16 Jun 2022 12:30:25 -0800 (PST)\r\n";

appendMsg += "From: Jack <jack@host.com>\r\n";

appendMsg += "Subject: Greeting from ESP Mail\r\n";

appendMsg += "To: joe@host.com\r\n";

appendMsg += "Message-Id: <jack@host.com>\r\n";

appendMsg += "MIME-Version: 1.0\r\n";

appendMsg += "Content-Type: text/plain; charset=\"us-ascii\"\r\n";

appendMsg += "Content-transfer-encoding: 7bit\r\n";

appendMsg += "\r\n";

appendMsg += "Hello Joe, this is the append message\r\n";

String appendMsgCmd = "APPEND INBOX {" + String(appendMsg.length()) + "}";

imap.sendCustomCommand(appendMsgCmd, customCommandCallback, F("A05") /* tag */);

imap.sendCustomData(appendMsg, true /* flag states the last data to send */);
}

void loop()
{
}
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ESP Mail Client",
"version": "2.4.2",
"version": "2.4.3",
"keywords": "communication, email, imap, smtp, esp32, esp8266, samd, arduino",
"description": "Arduino E-Mail Client Library to send, read and get incoming email notification for ESP32, ESP8266 and SAMD21 devices. The library also supported other Arduino Devices using Clients interfaces e.g. WiFiClient, EthernetClient, and GSMClient.",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=ESP Mail Client

version=2.4.2
version=2.4.3

author=Mobizt

Expand Down
34 changes: 33 additions & 1 deletion src/ESP_Mail_Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/**
* Mail Client Arduino Library for Espressif's ESP32 and ESP8266 and SAMD21 with u-blox NINA-W102 WiFi/Bluetooth module
*
* Created June 13, 2022
* Created June 16, 2022
*
* This library allows Espressif's ESP32, ESP8266 and SAMD devices to send and read Email through the SMTP and IMAP servers.
*
Expand Down Expand Up @@ -1067,6 +1067,9 @@ class ESP_Mail_Client
// Send data
size_t imapSend(IMAPSession *imap, int data, bool newline = false);

// Send data
size_t imapSend(IMAPSession *imap, uint8_t *data, size_t size);

// Log out
bool imapLogout(IMAPSession *imap);

Expand Down Expand Up @@ -1368,6 +1371,28 @@ class IMAPSession
template <typename T1 = const char *, typename T2 = const char *>
bool sendCustomCommand(T1 cmd, imapResponseCallback callback, T2 tag = "") { return mSendCustomCommand(toStringPtr(cmd), callback, toStringPtr(tag)); }

/** Send the custom IMAP command data string.
*
* @param data The string data.
* @param last The flag represents the last data to send (optional).
* @return The boolean value which indicates the success of operation.
*
* @note Should be used after calling sendCustomCommand("APPEND xxxxxx");
*/
template <typename T = const char *>
bool sendCustomData(T data, bool lastData = false) { return mSendData(toStringPtr(data), lastData); }

/** Send the custom IMAP command data.
*
* @param data The byte data.
* @param size The data size.
* @param lastData The flag represents the last data to send (optional).
* @return The boolean value which indicates the success of operation.
*
* @note Should be used after calling ssendCustomCommand("APPEND xxxxxx");
*/
bool sendCustomData(uint8_t *data, size_t size, bool lastData = false) { return mSendData(data, size, lastData); }

/** Copy the messages to the defined mailbox folder.
*
* @param toCopy The pointer to the MessageListList class that contains the
Expand Down Expand Up @@ -1506,6 +1531,12 @@ class IMAPSession
// Send custom command
bool mSendCustomCommand(MB_StringPtr cmd, imapResponseCallback callback, MB_StringPtr tag);

// Send data after sending APPEND command
bool mSendData(MB_StringPtr data, bool lastData);

// Send data after sending APPEND command
bool mSendData(uint8_t *data, size_t size, bool lastData);

// Delete folder
bool mDeleteFolder(MB_StringPtr folderName);

Expand Down Expand Up @@ -1543,6 +1574,7 @@ class IMAPSession
MB_VECTOR<struct esp_mail_message_header_t> _headers;

esp_mail_imap_command _imap_cmd = esp_mail_imap_command::esp_mail_imap_cmd_login;
MB_String _cmd;
MB_VECTOR<struct esp_mail_imap_multipart_level_t> _multipart_levels;
int _rfc822_part_count = 0;
bool _unseen = false;
Expand Down
2 changes: 1 addition & 1 deletion src/ESP_Mail_Client_Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

#ifndef ESP_MAIL_VERSION

#define ESP_MAIL_VERSION "2.4.2"
#define ESP_MAIL_VERSION "2.4.3"

#endif
Loading

0 comments on commit 2b1454c

Please sign in to comment.