From 7b2c55df6ec4c463f2b45b2ee6be5ea8124e1b56 Mon Sep 17 00:00:00 2001 From: suwatchai Date: Wed, 7 Aug 2019 01:58:34 +0700 Subject: [PATCH] Add debug, fix errors --- README.md | 37 +- examples/Receive_email/Receive_email.ino | 6 +- keywords.txt | 1 + library.properties | 2 +- src/ESP32_MailClient.cpp | 838 ++++++++++++++--------- src/ESP32_MailClient.h | 52 +- src/HTTPClientESP32Ex.cpp | 15 +- src/HTTPClientESP32Ex.h | 4 +- src/WiFiClientSecureESP32.cpp | 7 +- src/WiFiClientSecureESP32.h | 6 +- src/ssl_client32.cpp | 278 +++++++- src/ssl_client32.h | 7 +- 12 files changed, 885 insertions(+), 368 deletions(-) diff --git a/README.md b/README.md index ea8146f..4da8501 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mail Client Arduino Library for ESP32 v 1.2.0 +# Mail Client Arduino Library for ESP32 v 1.2.1 This library allows ESP32 to send Email with/without attachment and receive Email with/without attachment download via SMTP and IMAP servers. @@ -108,6 +108,14 @@ smtpData.setLogin("smtp.gmail.com", 587, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_E imapData.setLogin("imap.gmail.com", 993, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_EMAIL_PASSWORD"); +//8. To debug for SMTP or IMAP data + +smtpData.setDebug(true); + +imapData.setDebug(true); + + + ``` @@ -345,6 +353,20 @@ void setSTARTTLS(bool starttls); + +**Set debug print to serial.** + +param *`debug`* - bool flag to enable debug + +```C++ +void setDebug(bool debug); +``` + + + + + + **Set the mailbox folder to search or fetch.** param *`folderName`* - Known mailbox folder. Default value is INBOX @@ -1184,6 +1206,19 @@ void setSTARTTLS(bool starttls); +**Set debug print to serial.** + +param *`debug`* - bool flag to enable debug + +```C++ +void setDebug(bool debug); +``` + + + + + + **Set Sender info** param *`fromName`* - Sender's name diff --git a/examples/Receive_email/Receive_email.ino b/examples/Receive_email/Receive_email.ino index 7f45639..299077b 100644 --- a/examples/Receive_email/Receive_email.ino +++ b/examples/Receive_email/Receive_email.ino @@ -149,15 +149,15 @@ void readEmail() Serial.println(); Serial.println("Read Email..."); - imapData.setFechUID("10"); + imapData.setFetchUID("10"); imapData.setSearchCriteria(""); MailClient.readMail(http, imapData); - imapData.setFechUID("11"); + imapData.setFetchUID("11"); imapData.setSearchCriteria(""); MailClient.readMail(http, imapData); - imapData.setFechUID("12"); + imapData.setFetchUID("12"); imapData.setSearchCriteria(""); MailClient.readMail(http, imapData); } diff --git a/keywords.txt b/keywords.txt index 332a20f..c483b14 100644 --- a/keywords.txt +++ b/keywords.txt @@ -31,6 +31,7 @@ sdBegin KEYWORD2 setLogin KEYWORD2 setSTARTTLS KEYWORD2 +setDebug KEYWORD2 setFolder KEYWORD2 setMessageBufferSize KEYWORD2 setAttachmentSizeLimit KEYWORD2 diff --git a/library.properties b/library.properties index 10ceef1..d57fb94 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=ESP32 Mail Client -version=1.2.0 +version=1.2.1 author=Mobizt diff --git a/src/ESP32_MailClient.cpp b/src/ESP32_MailClient.cpp index dc78a17..5b9f315 100644 --- a/src/ESP32_MailClient.cpp +++ b/src/ESP32_MailClient.cpp @@ -1,7 +1,7 @@ /* - *Mail Client Arduino Library for ESP32, version 1.2.0 + *Mail Client Arduino Library for ESP32, version 1.2.1 * - * August 6, 2019 + * August 7, 2019 * * This library allows ESP32 to send Email with/without attachment and receive Email with/without attachment download through SMTP and IMAP servers. * @@ -71,6 +71,7 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) bool res = false; bool _res = false; bool starttls = imapData._starttls; + bool connected = false; int bufSize = 50; @@ -83,6 +84,14 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) int count = 0; + http.setDebugCallback(NULL); + + if(imapData._debug) { + ESP32MailDebug(FPSTR("INFO: connecting to IMAP server...")); + ESP32MailDebug(imapData._host.c_str()); + ESP32MailDebug(String(imapData._port).c_str()); + } + if (WiFi.status() != WL_CONNECTED) WiFi.reconnect(); @@ -112,6 +121,8 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("ERROR: could not connect to internet")); goto out; } @@ -123,15 +134,15 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } - + if (imapData._debug) + http.setDebugCallback(ESP32MailDebug); - if (imapData._rootCA.size() > 0) + if (imapData._rootCA.size() > 0) http.http_begin(imapData._host.c_str(), imapData._port, ESP32_MAIL_STR_202, (const char *)imapData._rootCA.front()); else http.http_begin(imapData._host.c_str(), imapData._port, ESP32_MAIL_STR_202, (const char *)NULL); - while (!http.http_connected() && count < 10) { @@ -149,6 +160,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "),false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(),true); + } } else { @@ -161,6 +177,10 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) goto out; } + + + connected = true; + client = http.http_getStreamPtr(); if (imapData._readCallback) @@ -171,6 +191,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: server connected")); + //Don't expect handshake from some servers dataTime = millis(); @@ -191,6 +214,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: send imap command LOGIN")); + client->print(ESP32_MAIL_STR_130); client->print(imapData._loginEmail.c_str()); client->print(ESP32_MAIL_STR_131); @@ -206,6 +232,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } goto out; } @@ -224,6 +255,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: send imap command LIST")); + client->println(ESP32_MAIL_STR_133); if (!waitIMAPResponse(http, imapData, imapData._cbData, IMAP_COMMAND_TYPE::LIST)) { @@ -235,6 +269,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } imapData._cbData.empty(); } @@ -245,6 +284,8 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); + + for (size_t i = 0; i < imapData._folders.size(); i++) { imapData._cbData._info = imapData._folders[i]; @@ -260,6 +301,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) } } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: send imap command EXAMINE")); + client->print(ESP32_MAIL_STR_135); client->print(imapData._currentFolder.c_str()); client->println(ESP32_MAIL_STR_136); @@ -273,6 +317,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } goto out; } @@ -336,6 +385,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) if (imapData._searchCriteria != "") { + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: search message")); + if (imapData._searchCriteria.find(ESP32_MAIL_STR_137) != std::string::npos) { imapData._uidSearch = true; @@ -386,6 +438,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } goto out; } @@ -457,6 +514,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) for (int i = 0; i < imapData._msgNum.size(); i++) { + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: fetch message")); + if (imapData._readCallback) { @@ -526,6 +586,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } goto out; } @@ -701,6 +766,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } } } else if (imapData._messageDataInfo[mailIndex][j]._disposition == ESP32_MAIL_STR_153 && _sdOk) @@ -737,6 +807,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } } delay(1); @@ -788,6 +863,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: send imap command LOGOUT")); + if (http.http_connected()) while (client->available()) client->read(); @@ -804,6 +882,11 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._cbData._success = false; imapData._readCallback(imapData._cbData); } + if (imapData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(imapErrorReasonStr().c_str(), true); + } goto out; } @@ -815,6 +898,9 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) imapData._readCallback(imapData._cbData); } + if (imapData._debug) + ESP32MailDebug(FPSTR("INFO: message fetch completed")); + if (http.http_connected()) { while (client->available()) @@ -837,12 +923,15 @@ bool ESP32_MailClient::readMail(HTTPClientESP32Ex &http, IMAPData &imapData) out: +if(connected) +{ if (http.http_connected()) { while (client->available()) client->read(); client->stop(); } +} imapData._cbData.empty(); delete[] _val; @@ -905,6 +994,8 @@ bool ESP32_MailClient::sdTest() return true; } + + bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) { @@ -913,8 +1004,11 @@ bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) std::string buf2; int bufSize = 50; bool starttls = smtpData._starttls; + bool connected = false; char *_val = new char[bufSize]; + http.setDebugCallback(NULL); + WiFiClient *client; if (smtpData._sendCallback) @@ -924,6 +1018,12 @@ bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) smtpData._sendCallback(smtpData._cbData); } + if(smtpData._debug) { + ESP32MailDebug(FPSTR("INFO: connecting to SMTP server...")); + ESP32MailDebug(smtpData._host.c_str()); + ESP32MailDebug(String(smtpData._port).c_str()); + } + if (WiFi.status() != WL_CONNECTED) WiFi.reconnect(); @@ -952,10 +1052,13 @@ bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } + if(smtpData._debug) + ESP32MailDebug(FPSTR("ERROR: could not connect to internet")); goto failed; } - + if(smtpData._debug) http.setDebugCallback(ESP32MailDebug); + if (smtpData._rootCA.size() > 0) http.http_begin(smtpData._host.c_str(), smtpData._port, ESP32_MAIL_STR_202, (const char *)smtpData._rootCA.front()); else @@ -965,7 +1068,6 @@ bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) starttls = true; - if (!http.http_connect(starttls)) { _smtpStatus = SMTP_STATUS_SERVER_CONNECT_FAILED; @@ -975,446 +1077,542 @@ bool ESP32_MailClient::sendMail(HTTPClientESP32Ex &http, SMTPData &smtpData) smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } + + if (smtpData._debug){ + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } goto failed; } - client = http.http_getStreamPtr(); + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: smtp server connected")); - if (!starttls) - { + connected = true; - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_121; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } + client = http.http_getStreamPtr(); - if (waitSMTPResponse(http) != 220) - { - _smtpStatus = SMTP_STATUS_SMTP_RESPONSE_FAILED; - if (smtpData._sendCallback) + if (!starttls) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } - goto failed; - } - } - - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_122; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_121; + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } - client->println(ESP32_MAIL_STR_5); + if (waitSMTPResponse(http, smtpData) != 220) + { + _smtpStatus = SMTP_STATUS_SMTP_RESPONSE_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } + } - if (waitSMTPResponse(http) != 250) - { - _smtpStatus = SMTP_STATUS_IDENTIFICATION_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_122; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } - + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: send smtp HELO command")); - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_123; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } + client->println(ESP32_MAIL_STR_5); - client->println(ESP32_MAIL_STR_4); + if (waitSMTPResponse(http, smtpData) != 250) + { + _smtpStatus = SMTP_STATUS_IDENTIFICATION_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } - if (waitSMTPResponse(http) != 334) - { - _smtpStatus = SMTP_STATUS_AUTHEN_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_123; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_124; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: send smtp AUTH LOGIN command")); - client->println(base64_encode_string((const unsigned char *)smtpData._loginEmail.c_str(), smtpData._loginEmail.length()).c_str()); + client->println(ESP32_MAIL_STR_4); - if (waitSMTPResponse(http) != 334) - { - _smtpStatus = SMTP_STATUS_USER_LOGIN_FAILED; - if (smtpData._sendCallback) + if (waitSMTPResponse(http, smtpData) != 334) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); + _smtpStatus = SMTP_STATUS_AUTHEN_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; } - goto failed; - } - - client->println(base64_encode_string((const unsigned char *)smtpData._loginPassword.c_str(), smtpData._loginPassword.length()).c_str()); - if (waitSMTPResponse(http) != 235) - { - _smtpStatus = SMTP_STATUS_PASSWORD_LOGIN_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_124; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: log in with username and password")); - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_125; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } - - if (smtpData._priority > 0 && smtpData._priority <= 5) - { - memset(_val, 0, bufSize); - itoa(smtpData._priority, _val, 10); - - buf2 += ESP32_MAIL_STR_17; - buf2 += _val; - buf2 += ESP32_MAIL_STR_34; + client->println(base64_encode_string((const unsigned char *)smtpData._loginEmail.c_str(), smtpData._loginEmail.length()).c_str()); - if (smtpData._priority == 1) + if (waitSMTPResponse(http, smtpData) != 334) { - buf2 += ESP32_MAIL_STR_18; - buf2 += ESP32_MAIL_STR_21; - } - else if (smtpData._priority == 3) - { - buf2 += ESP32_MAIL_STR_19; - buf2 += ESP32_MAIL_STR_22; - } - else if (smtpData._priority == 5) - { - buf2 += ESP32_MAIL_STR_20; - buf2 += ESP32_MAIL_STR_23; + _smtpStatus = SMTP_STATUS_USER_LOGIN_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; } - } - - buf2 += ESP32_MAIL_STR_10; - - if (smtpData._fromName.length() > 0) - buf2 += smtpData._fromName; - buf2 += ESP32_MAIL_STR_14; - buf2 += smtpData._senderEmail; - buf2 += ESP32_MAIL_STR_15; - buf2 += ESP32_MAIL_STR_34; + client->println(base64_encode_string((const unsigned char *)smtpData._loginPassword.c_str(), smtpData._loginPassword.length()).c_str()); - buf += ESP32_MAIL_STR_8; - buf += ESP32_MAIL_STR_14; - buf += smtpData._senderEmail; - buf += ESP32_MAIL_STR_15; - client->println(buf.c_str()); + if (waitSMTPResponse(http, smtpData) != 235) + { + _smtpStatus = SMTP_STATUS_PASSWORD_LOGIN_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } - if (waitSMTPResponse(http) != 250) - { - _smtpStatus = SMTP_STATUS_SEND_HEADER_SENDER_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_125; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } - for (uint8_t i = 0; i < smtpData._recipient.size(); i++) - { - if (i == 0) - { - buf2 += ESP32_MAIL_STR_11; - buf2 += ESP32_MAIL_STR_14; - buf2 += smtpData._recipient[i]; - buf2 += ESP32_MAIL_STR_15; - } - else + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: send email header")); + + if (smtpData._priority > 0 && smtpData._priority <= 5) { - buf2 += ESP32_MAIL_STR_13; - buf2 += smtpData._recipient[i]; - buf2 += ESP32_MAIL_STR_15; - } + memset(_val, 0, bufSize); + itoa(smtpData._priority, _val, 10); - if (i == smtpData._recipient.size() - 1) + buf2 += ESP32_MAIL_STR_17; + buf2 += _val; buf2 += ESP32_MAIL_STR_34; - buf.clear(); + if (smtpData._priority == 1) + { + buf2 += ESP32_MAIL_STR_18; + buf2 += ESP32_MAIL_STR_21; + } + else if (smtpData._priority == 3) + { + buf2 += ESP32_MAIL_STR_19; + buf2 += ESP32_MAIL_STR_22; + } + else if (smtpData._priority == 5) + { + buf2 += ESP32_MAIL_STR_20; + buf2 += ESP32_MAIL_STR_23; + } + } + + buf2 += ESP32_MAIL_STR_10; + + if (smtpData._fromName.length() > 0) + buf2 += smtpData._fromName; + + buf2 += ESP32_MAIL_STR_14; + buf2 += smtpData._senderEmail; + buf2 += ESP32_MAIL_STR_15; + buf2 += ESP32_MAIL_STR_34; - buf += ESP32_MAIL_STR_9; + buf += ESP32_MAIL_STR_8; buf += ESP32_MAIL_STR_14; - buf += smtpData._recipient[i]; + buf += smtpData._senderEmail; buf += ESP32_MAIL_STR_15; - client->println(buf.c_str()); + - if (waitSMTPResponse(http) != 250) + if (waitSMTPResponse(http, smtpData) != 250) { - _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; + _smtpStatus = SMTP_STATUS_SEND_HEADER_SENDER_FAILED; if (smtpData._sendCallback) { smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } goto failed; } - } - - for (uint8_t i = 0; i < smtpData._cc.size(); i++) - { - if (i == 0) + for (uint8_t i = 0; i < smtpData._recipient.size(); i++) { - buf2 += ESP32_MAIL_STR_12; - buf2 += ESP32_MAIL_STR_14; - buf2 += smtpData._cc[i]; - buf2 += ESP32_MAIL_STR_15; + if (i == 0) + { + buf2 += ESP32_MAIL_STR_11; + buf2 += ESP32_MAIL_STR_14; + buf2 += smtpData._recipient[i]; + buf2 += ESP32_MAIL_STR_15; + } + else + { + buf2 += ESP32_MAIL_STR_13; + buf2 += smtpData._recipient[i]; + buf2 += ESP32_MAIL_STR_15; + } + + if (i == smtpData._recipient.size() - 1) + buf2 += ESP32_MAIL_STR_34; + + buf.clear(); + + buf += ESP32_MAIL_STR_9; + buf += ESP32_MAIL_STR_14; + buf += smtpData._recipient[i]; + buf += ESP32_MAIL_STR_15; + + client->println(buf.c_str()); + + + if (waitSMTPResponse(http, smtpData) != 250) + { + _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } } - else + + for (uint8_t i = 0; i < smtpData._cc.size(); i++) { - buf2 += ESP32_MAIL_STR_13; - buf2 += smtpData._cc[i]; - buf2 += ESP32_MAIL_STR_15; - } - if (i == smtpData.ccCount() - 1) - buf2 += ESP32_MAIL_STR_34; + if (i == 0) + { + buf2 += ESP32_MAIL_STR_12; + buf2 += ESP32_MAIL_STR_14; + buf2 += smtpData._cc[i]; + buf2 += ESP32_MAIL_STR_15; + } + else + { + buf2 += ESP32_MAIL_STR_13; + buf2 += smtpData._cc[i]; + buf2 += ESP32_MAIL_STR_15; + } - buf.clear(); + if (i == smtpData.ccCount() - 1) + buf2 += ESP32_MAIL_STR_34; - buf += ESP32_MAIL_STR_9; - buf += ESP32_MAIL_STR_14; - buf += smtpData._cc[i]; - buf += ESP32_MAIL_STR_15; - client->println(buf.c_str()); + buf.clear(); - if (waitSMTPResponse(http) != 250) - { - _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; - if (smtpData._sendCallback) + buf += ESP32_MAIL_STR_9; + buf += ESP32_MAIL_STR_14; + buf += smtpData._cc[i]; + buf += ESP32_MAIL_STR_15; + client->println(buf.c_str()); + + + if (waitSMTPResponse(http, smtpData) != 250) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); + _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; } - goto failed; } - } - for (uint8_t i = 0; i < smtpData._bcc.size(); i++) - { - buf.clear(); - buf += ESP32_MAIL_STR_9; - buf += ESP32_MAIL_STR_14; - buf += smtpData._bcc[i]; - buf += ESP32_MAIL_STR_15; - client->println(buf.c_str()); - - if (waitSMTPResponse(http) != 250) + for (uint8_t i = 0; i < smtpData._bcc.size(); i++) { - _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; - if (smtpData._sendCallback) + buf.clear(); + buf += ESP32_MAIL_STR_9; + buf += ESP32_MAIL_STR_14; + buf += smtpData._bcc[i]; + buf += ESP32_MAIL_STR_15; + client->println(buf.c_str()); + + + if (waitSMTPResponse(http, smtpData) != 250) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); + _smtpStatus = SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; } - goto failed; } - } - - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_126; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } - - client->println(ESP32_MAIL_STR_16); - if (waitSMTPResponse(http) != 354) - { - _smtpStatus = SMTP_STATUS_SEND_BODY_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_126; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } - client->print(buf2.c_str()); + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: send email body")); + + client->println(ESP32_MAIL_STR_16); + + if (waitSMTPResponse(http, smtpData) != 354) + { + _smtpStatus = SMTP_STATUS_SEND_BODY_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } - client->print(ESP32_MAIL_STR_24); - client->println(smtpData._subject.c_str()); - client->print(ESP32_MAIL_STR_3); - client->print(ESP32_MAIL_STR_1); - client->print(ESP32_MAIL_STR_2); - client->print(ESP32_MAIL_STR_35); + client->print(buf2.c_str()); - buf.clear(); + client->print(ESP32_MAIL_STR_24); + client->println(smtpData._subject.c_str()); + client->print(ESP32_MAIL_STR_3); + client->print(ESP32_MAIL_STR_1); + client->print(ESP32_MAIL_STR_2); + client->print(ESP32_MAIL_STR_35); - set_message_header(buf, smtpData._message, smtpData._htmlFormat); + buf.clear(); - client->print(buf.c_str()); + set_message_header(buf, smtpData._message, smtpData._htmlFormat); - if (smtpData._attach._index > 0) - { - smtpData._cbData._info = ESP32_MAIL_STR_127; - smtpData._cbData._success = false; - if (smtpData._sendCallback) - smtpData._sendCallback(smtpData._cbData); - } + client->print(buf.c_str()); - for (uint8_t i = 0; i < smtpData._attach._index; i++) - { - if (smtpData._attach._type[i] == 0) + if (smtpData._attach._index > 0) { - - smtpData._cbData._info = smtpData._attach._filename[i]; + smtpData._cbData._info = ESP32_MAIL_STR_127; smtpData._cbData._success = false; if (smtpData._sendCallback) smtpData._sendCallback(smtpData._cbData); - - buf.clear(); - set_attachment_header(i, buf, smtpData._attach); - client->print(buf.c_str()); - send_base64_encode_data(client, smtpData._attach._buf[i].front(), smtpData._attach._size[i]); - client->print(ESP32_MAIL_STR_34); + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: send attachment...")); } - else - { - if (!_sdOk) + for (uint8_t i = 0; i < smtpData._attach._index; i++) + { + if (smtpData._attach._type[i] == 0) { - if (smtpData._storageType == MailClientStorageType::SD) - _sdOk = sdTest(); - else if (smtpData._storageType == MailClientStorageType::SPIFFS) - _sdOk = SPIFFS.begin(true); - } - - if (!_sdOk) - continue; - bool file_existed = false; - if (smtpData._storageType == MailClientStorageType::SD) - file_existed = SD.exists(smtpData._attach._filename[i].c_str()); - else if (smtpData._storageType == MailClientStorageType::SPIFFS) - file_existed = SPIFFS.exists(smtpData._attach._filename[i].c_str()); - - if (file_existed) - { smtpData._cbData._info = smtpData._attach._filename[i]; smtpData._cbData._success = false; if (smtpData._sendCallback) smtpData._sendCallback(smtpData._cbData); + if (smtpData._debug) + ESP32MailDebug(smtpData._attach._filename[i].c_str()); buf.clear(); set_attachment_header(i, buf, smtpData._attach); client->print(buf.c_str()); + send_base64_encode_data(client, smtpData._attach._buf[i].front(), smtpData._attach._size[i]); + client->print(ESP32_MAIL_STR_34); + } + else + { + + if (!_sdOk) + { + if (smtpData._storageType == MailClientStorageType::SD) + _sdOk = sdTest(); + else if (smtpData._storageType == MailClientStorageType::SPIFFS) + _sdOk = SPIFFS.begin(true); + } - File file; + if (!_sdOk) + continue; + + bool file_existed = false; if (smtpData._storageType == MailClientStorageType::SD) - file = SD.open(smtpData._attach._filename[i].c_str(), FILE_READ); + file_existed = SD.exists(smtpData._attach._filename[i].c_str()); else if (smtpData._storageType == MailClientStorageType::SPIFFS) - file = SPIFFS.open(smtpData._attach._filename[i].c_str(), FILE_READ); + file_existed = SPIFFS.exists(smtpData._attach._filename[i].c_str()); - send_base64_encode_file(client, file); - client->print(ESP32_MAIL_STR_34); + if (file_existed) + { + smtpData._cbData._info = smtpData._attach._filename[i]; + smtpData._cbData._success = false; + if (smtpData._sendCallback) + smtpData._sendCallback(smtpData._cbData); + + if (smtpData._debug) + ESP32MailDebug(smtpData._attach._filename[i].c_str()); + + buf.clear(); + set_attachment_header(i, buf, smtpData._attach); + client->print(buf.c_str()); + + File file; + if (smtpData._storageType == MailClientStorageType::SD) + file = SD.open(smtpData._attach._filename[i].c_str(), FILE_READ); + else if (smtpData._storageType == MailClientStorageType::SPIFFS) + file = SPIFFS.open(smtpData._attach._filename[i].c_str(), FILE_READ); + + send_base64_encode_file(client, file); + client->print(ESP32_MAIL_STR_34); + } } } - } - client->print(ESP32_MAIL_STR_33); - client->print(ESP32_MAIL_STR_2); - client->print(ESP32_MAIL_STR_33); - client->print(ESP32_MAIL_STR_37); + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: finalize...")); - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_128; - smtpData._cbData._success = false; - smtpData._sendCallback(smtpData._cbData); - } + client->print(ESP32_MAIL_STR_33); + client->print(ESP32_MAIL_STR_2); + client->print(ESP32_MAIL_STR_33); + client->print(ESP32_MAIL_STR_37); - if (waitSMTPResponse(http) != 250) - { - _smtpStatus = SMTP_STATUS_SEND_BODY_FAILED; if (smtpData._sendCallback) { - smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._info = ESP32_MAIL_STR_128; smtpData._cbData._success = false; smtpData._sendCallback(smtpData._cbData); } - goto failed; - } - if (smtpData._sendCallback) - { - smtpData._cbData._info = ESP32_MAIL_STR_129; - smtpData._cbData._success = true; - smtpData._sendCallback(smtpData._cbData); - } + if (waitSMTPResponse(http, smtpData) != 250) + { + _smtpStatus = SMTP_STATUS_SEND_BODY_FAILED; + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_53 + smtpErrorReasonStr(); + smtpData._cbData._success = false; + smtpData._sendCallback(smtpData._cbData); + } + if (smtpData._debug) + { + ESP32MailDebugLine(FPSTR("ERROR: "), false); + ESP32MailDebugLine(smtpErrorReasonStr().c_str(), true); + } + goto failed; + } - if (http.http_connected()) - { - client->stop(); - } + if (smtpData._sendCallback) + { + smtpData._cbData._info = ESP32_MAIL_STR_129; + smtpData._cbData._success = true; + smtpData._sendCallback(smtpData._cbData); + } - client->flush(); + if (smtpData._debug) + ESP32MailDebug(FPSTR("INFO: email sent successfully")); - client->~WiFiClient(); + if (http.http_connected()) + { + client->stop(); + } - smtpData._cbData.empty(); + client->flush(); - std::string().swap(buf); - std::string().swap(buf2); - delete[] _val; + client->~WiFiClient(); - return true; + smtpData._cbData.empty(); -failed: + std::string().swap(buf); + std::string().swap(buf2); + delete[] _val; - if (http.http_connected()) - { - client->stop(); - } + return true; - client->flush(); + failed: - client->~WiFiClient(); + if (connected) + { + if (http.http_connected()) + { + client->stop(); + } - smtpData._cbData.empty(); - std::string().swap(buf); - std::string().swap(buf2); - delete[] _val; - return false; + client->flush(); + + client->~WiFiClient(); + } + + smtpData._cbData.empty(); + std::string().swap(buf); + std::string().swap(buf2); + delete[] _val; + return false; } String ESP32_MailClient::smtpErrorReason() @@ -1593,7 +1791,7 @@ void ESP32_MailClient::set_attachment_header(uint8_t index, std::string &header, std::string().swap(filename); } -int ESP32_MailClient::waitSMTPResponse(HTTPClientESP32Ex &http) +int ESP32_MailClient::waitSMTPResponse(HTTPClientESP32Ex &http, SMTPData &smtpData) { long dataTime = millis(); @@ -1637,6 +1835,8 @@ int ESP32_MailClient::waitSMTPResponse(HTTPClientESP32Ex &http) if (p1 != std::string::npos) resCode = atoi(lineBuf.substr(0, p1).c_str()); } + if (smtpData._debug) + ESP32MailDebug(lineBuf.c_str()); lineBuf.clear(); lfCount++; } @@ -1848,6 +2048,9 @@ bool ESP32_MailClient::waitIMAPResponse(HTTPClientESP32Ex &http, IMAPData &imapD if (lfCount == 0) { + if (imapData._debug) + ESP32MailDebug(lineBuf.c_str()); + if (imapCommandType == IMAP_COMMAND_TYPE::FETCH_BODY_TEXT || imapCommandType == IMAP_COMMAND_TYPE::FETCH_BODY_MIME || imapCommandType == IMAP_COMMAND_TYPE::FETCH_BODY_HEADER || @@ -3107,6 +3310,11 @@ void IMAPData::setSTARTTLS(bool starttls) _starttls = starttls; } +void IMAPData::setDebug(bool debug) +{ + _debug = debug; +} + void IMAPData::setFolder(const String &folderName) { _currentFolder.clear(); @@ -3465,6 +3673,8 @@ String IMAPData::getMessage(uint16_t messageIndex, bool htmlFormat) return std::string().c_str(); } + + String IMAPData::getHTMLMessgaeCharset(uint16_t messageIndex) { if (messageIndex < _msgNum.size()) @@ -3903,6 +4113,11 @@ void SMTPData::setSTARTTLS(bool starttls) _starttls = starttls; } +void SMTPData::setDebug(bool debug) +{ + _debug = debug; +} + void SMTPData::setSender(const String &fromName, const String &senderEmail) { @@ -4191,6 +4406,7 @@ void SMTPData::setSendCallback(sendStatusCallback sendCallback) _sendCallback = std::move(sendCallback); } + ReadStatus::ReadStatus() { } diff --git a/src/ESP32_MailClient.h b/src/ESP32_MailClient.h index 578c2f6..266368f 100644 --- a/src/ESP32_MailClient.h +++ b/src/ESP32_MailClient.h @@ -1,7 +1,7 @@ /* - *Mail Client Arduino Library for ESP32, version 1.2.0 + *Mail Client Arduino Library for ESP32, version 1.2.1 * - * August 6, 2019 + * August 7, 2019 * * This library allows ESP32 to send Email with/without attachment and receive Email with/without attachment download through SMTP and IMAP servers. * @@ -437,10 +437,11 @@ class ESP32_MailClient std::string base64_encode_string(const unsigned char *src, size_t len); void send_base64_encode_data(WiFiClient *tcp, const unsigned char *src, size_t len); void send_base64_encode_file(WiFiClient *tcp, File file); - int waitSMTPResponse(HTTPClientESP32Ex &http); + int waitSMTPResponse(HTTPClientESP32Ex &http, SMTPData &smtpData); bool waitIMAPResponse(HTTPClientESP32Ex &http, IMAPData &imapData, ReadStatus &cbData, uint8_t imapCommandType = 0, int maxChar = 0, int mailIndex = -1, int messageDataIndex = -1, std ::string part = ""); void createDirs(std::string dirs); bool sdTest(); + }; class messageBodyData @@ -529,6 +530,16 @@ class IMAPData */ void setSTARTTLS(bool starttls); + + /* + + Set debug print to serial + + @param debug - bool flag to enable debug + + */ + void setDebug(bool debug); + /* Set the mailbox folder to search or fetch. @@ -1182,8 +1193,9 @@ class IMAPData friend ESP32_MailClient; private: - String - getMessage(uint16_t messageIndex, bool htmlFormat); + String getMessage(uint16_t messageIndex, bool htmlFormat); + + size_t _totalMessage = 0; std::string _host = ""; uint16_t _port = 993; @@ -1215,6 +1227,7 @@ class IMAPData uint16_t _emailNumMax = 20; int _searchCount; bool _starttls = false; + bool _debug = false; readStatusCallback _readCallback = NULL; std::vector _date = std::vector(); @@ -1273,6 +1286,15 @@ class SMTPData */ void setSTARTTLS(bool starttls); + + /* + + Set debug print to serial + + @param debug - bool flag to enable debug + + */ + void setDebug(bool debug); /* Set Sender info @@ -1673,6 +1695,7 @@ class SMTPData string _message = ""; bool _htmlFormat = false; bool _starttls = false; + bool _debug = false; sendStatusCallback _sendCallback = NULL; std::vector _recipient = std::vector(); @@ -1681,8 +1704,27 @@ class SMTPData attachmentData _attach; SendStatus _cbData; std::vector _rootCA = std::vector(); + }; + static void __attribute__((used)) ESP32MailDebug(const char* msg) { + + Serial.print(FPSTR("[DEBUG] - ")); + Serial.println(msg); + +} + +static void __attribute__((used)) ESP32MailDebugLine(const char *msg, bool newline) +{ + if (!newline) + Serial.print(FPSTR("[DEBUG] - ")); + + if (newline) + Serial.println(msg); + else + Serial.print(msg); +} + extern ESP32_MailClient MailClient; #endif \ No newline at end of file diff --git a/src/HTTPClientESP32Ex.cpp b/src/HTTPClientESP32Ex.cpp index 76bfba2..c2634f1 100644 --- a/src/HTTPClientESP32Ex.cpp +++ b/src/HTTPClientESP32Ex.cpp @@ -2,7 +2,7 @@ * Customized version of ESP32 HTTPClient Library. * Allow custom header and payload with STARTTLS support * - * v 1.1.0 + * v 1.1.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -46,7 +46,7 @@ class TransportTraits } virtual bool - verify(WiFiClient &client, const char *host, bool starttls) + verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb) { return true; } @@ -62,13 +62,14 @@ class TLSTraits : public TransportTraits return std::unique_ptr(new WiFiClientSecureESP32()); } - bool verify(WiFiClient &client, const char *host, bool starttls) override + bool verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb) override { WiFiClientSecureESP32 &wcs = static_cast(client); wcs.setCACert(_cacert); wcs.setCertificate(_clicert); wcs.setPrivateKey(_clikey); wcs.setSTARTTLS(starttls); + wcs.setDebugCB(cb); return true; } @@ -152,7 +153,7 @@ bool HTTPClientESP32Ex::http_connect(void) _tcp = http_transportTraits->create(); - if (!http_transportTraits->verify(*_tcp, _host, false)) + if (!http_transportTraits->verify(*_tcp, _host, false, _debugCallback)) { _tcp->stop(); return false; @@ -179,7 +180,7 @@ bool HTTPClientESP32Ex::http_connect(bool starttls) _tcp = http_transportTraits->create(); - if (!http_transportTraits->verify(*_tcp, _host, starttls)) + if (!http_transportTraits->verify(*_tcp, _host, starttls, _debugCallback)) { _tcp->stop(); return false; @@ -191,4 +192,8 @@ bool HTTPClientESP32Ex::http_connect(bool starttls) return http_connected(); } + +void HTTPClientESP32Ex::setDebugCallback(DebugMsgCallback cb){ + _debugCallback = std::move(cb); +} #endif diff --git a/src/HTTPClientESP32Ex.h b/src/HTTPClientESP32Ex.h index f8e0349..61b50c2 100644 --- a/src/HTTPClientESP32Ex.h +++ b/src/HTTPClientESP32Ex.h @@ -2,7 +2,7 @@ * Customized version of ESP32 HTTPClient Library. * Allow custom header and payload with STARTTLS support * - * v 1.1.0 + * v 1.1.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -88,10 +88,12 @@ class HTTPClientESP32Ex : public HTTPClient uint16_t tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT; bool http_connect(void); bool http_connect(bool starttls); + void setDebugCallback(DebugMsgCallback cb); protected: TransportTraitsPtr http_transportTraits; std::unique_ptr _tcp; + DebugMsgCallback _debugCallback = NULL; char _host[200]; char _uri[200]; diff --git a/src/WiFiClientSecureESP32.cpp b/src/WiFiClientSecureESP32.cpp index fb31283..a19a7c7 100644 --- a/src/WiFiClientSecureESP32.cpp +++ b/src/WiFiClientSecureESP32.cpp @@ -1,5 +1,5 @@ /* - *Customized WiFiClientSecure.cpp to support STARTTLS protocol, version 1.0.0 + *Customized WiFiClientSecure.cpp to support STARTTLS protocol, version 1.0.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -380,4 +380,9 @@ void WiFiClientSecureESP32::setHandshakeTimeout(unsigned long handshake_timeout) void WiFiClientSecureESP32::setSTARTTLS(bool starttls) { sslclient->starttls = starttls; +} + +void WiFiClientSecureESP32::setDebugCB(DebugMsgCallback cb) +{ + sslclient->_debugCallback = std::move(cb); } \ No newline at end of file diff --git a/src/WiFiClientSecureESP32.h b/src/WiFiClientSecureESP32.h index cc4e0ad..950dbb1 100644 --- a/src/WiFiClientSecureESP32.h +++ b/src/WiFiClientSecureESP32.h @@ -1,6 +1,6 @@ /* - *Customized WiFiClientSecure.h to support STARTTLS protocol, version 1.0.0 + *Customized WiFiClientSecure.h to support STARTTLS protocol, version 1.0.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -51,6 +51,8 @@ #include #include "ssl_client32.h" +typedef void (*DebugMsgCallback)(const char* msg); + class WiFiClientSecureESP32 : public WiFiClient { protected: @@ -64,6 +66,7 @@ class WiFiClientSecureESP32 : public WiFiClient const char *_private_key; const char *_pskIdent; // identity for PSK cipher suites const char *_psKey; // key in hex for PSK cipher suites + DebugMsgCallback _debugCallback = NULL; public: WiFiClientSecureESP32 *next; @@ -99,6 +102,7 @@ class WiFiClientSecureESP32 : public WiFiClient bool verify(const char* fingerprint, const char* domain_name); void setHandshakeTimeout(unsigned long handshake_timeout); void setSTARTTLS(bool starttls); + void setDebugCB(DebugMsgCallback cb); operator bool() { diff --git a/src/ssl_client32.cpp b/src/ssl_client32.cpp index e24e84f..846ff20 100644 --- a/src/ssl_client32.cpp +++ b/src/ssl_client32.cpp @@ -1,5 +1,5 @@ /* - *Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.0 + *Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -74,6 +74,10 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t char buf[512]; int ret, flags; int enable = 1; + + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: starting socket")); + log_v("Free internal heap before TLS %u", ESP.getFreeHeap()); log_v("Starting socket"); @@ -82,6 +86,8 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ssl_client->socket < 0) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: opening socket")); log_e("ERROR opening socket"); return ssl_client->socket; } @@ -89,6 +95,8 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t IPAddress srv((uint32_t)0); if (!WiFiGenericClass::hostByName(host, srv)) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: could not get ip from host")); return -1; } @@ -98,6 +106,9 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t serv_addr.sin_addr.s_addr = srv; serv_addr.sin_port = htons(port); + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: connecting to Server...")); + if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) { if (timeout <= 0) @@ -108,23 +119,35 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: server connected")); } else { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: connect to Server failed!")); log_e("Connect to Server failed!"); return -1; } fcntl(ssl_client->socket, F_SETFL, fcntl(ssl_client->socket, F_GETFL, 0) | O_NONBLOCK); - if (ssl_client->starttls){ - if ((ret = starttlsHandshake(ssl_client->socket)) != 0) + if (ssl_client->starttls && (port == 25 || port == 587 || port == 143)) + { + + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: begin STARTTLS handshake")); + + if ((ret = starttlsHandshake(ssl_client, port)) != 0) { log_e("STARTTLS failed!"); return -1; } } - + + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: seeding the random number generator")); log_v("Seeding the random number generator"); mbedtls_entropy_init(&ssl_client->entropy_ctx); @@ -133,9 +156,23 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t &ssl_client->entropy_ctx, (const unsigned char *)pers32, strlen(pers32)); if (ret < 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } + return handle_error(ret); } + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: setting up the SSL/TLS structure...")); + log_v("Setting up the SSL/TLS structure..."); if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf, @@ -143,6 +180,16 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } return handle_error(ret); } @@ -151,6 +198,8 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t if (rootCABuff != NULL) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: loading CA cert")); log_v("Loading CA cert"); mbedtls_x509_crt_init(&ssl_client->ca_cert); mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); @@ -159,15 +208,29 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); if (ret < 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } return handle_error(ret); } } else if (pskIdent != NULL && psKey != NULL) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: setting up PSK")); log_v("Setting up PSK"); // convert PSK from hex to binary if ((strlen(psKey) & 1) != 0 || strlen(psKey) > 2 * MBEDTLS_PSK_MAX_LEN) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: pre-shared key not valid hex or too long")); log_e("pre-shared key not valid hex or too long"); return -1; } @@ -197,33 +260,63 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t psk[j / 2] |= c; } // set mbedtls config + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: set mbedtls config")); ret = mbedtls_ssl_conf_psk(&ssl_client->ssl_conf, psk, psk_len, (const unsigned char *)pskIdent, strlen(pskIdent)); if (ret != 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } log_e("mbedtls_ssl_conf_psk returned %d", ret); return handle_error(ret); } } else { + mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); log_i("WARNING: Use certificates for a more secure communication!"); } if (cli_cert != NULL && cli_key != NULL) { + mbedtls_x509_crt_init(&ssl_client->client_cert); mbedtls_pk_init(&ssl_client->client_key); + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: loading CRT cert")); + log_v("Loading CRT cert"); ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1); if (ret < 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } return handle_error(ret); } + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: loading private key")); + log_v("Loading private key"); ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0); @@ -235,40 +328,66 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key); } + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: setting hostname for TLS session...")); + log_v("Setting hostname for TLS session..."); // Hostname set here should match CN in server certificate if ((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } return handle_error(ret); } - /* - - ssl_client->server_fd.fd = ssl_client->socket; - - if ((ret = mbedtls_net_connect(&ssl_client->server_fd, host, String(port).c_str(), MBEDTLS_NET_PROTO_TCP)) != 0) - { - return handle_error(ret); - } - - */ - mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx); if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } + return handle_error(ret); } mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL); + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: performing the SSL/TLS handshake...")); + log_v("Performing the SSL/TLS handshake..."); unsigned long handshake_start_time = millis(); while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + if (ssl_client->_debugCallback) + { + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + } return handle_error(ret); } if ((millis() - handshake_start_time) > ssl_client->handshake_timeout) @@ -281,6 +400,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t log_d("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { + log_d("Record expansion is %d", ret); } else @@ -289,18 +409,25 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t } } + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: verifying peer X.509 certificate...")); + log_v("Verifying peer X.509 certificate..."); if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { bzero(buf, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: failed to verify peer certificate!")); log_e("Failed to verify peer certificate! verification info: %s", buf); stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. return handle_error(ret); } else { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: certificate verified")); log_v("Certificate verified."); } @@ -326,6 +453,8 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t void stop_ssl_socket(sslclient_context32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: cleaning SSL connection")); log_v("Cleaning SSL connection."); if (ssl_client->socket >= 0) @@ -349,6 +478,18 @@ int data_to_read(sslclient_context32 *ssl_client) //log_e("RES: %i",res); //for low level debug if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { + if (ssl_client->_debugCallback) + { + char *buf = new char[512]; + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, FPSTR("ERROR: ")); + mbedtls_strerror(ret, error_buf, 100); + strcat(buf, error_buf); + ssl_client->_debugCallback(buf); + delete[] error_buf; + delete[] buf; + } return handle_error(ret); } @@ -357,6 +498,7 @@ int data_to_read(sslclient_context32 *ssl_client) int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t len) { + log_v("Writing HTTP request..."); //for low level debug int ret = -1; @@ -375,6 +517,7 @@ int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length) { + //log_d( "Reading HTTP response..."); //for low level debug int ret = -1; @@ -450,12 +593,16 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con } if (pos > len - 2) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: fingerprint too short")); log_d("pos:%d len:%d fingerprint too short", pos, len); return false; } uint8_t high, low; if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos + 1], &low)) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: invalid hex sequence")); log_d("pos:%d len:%d invalid hex sequence: %c%c", pos, len, fp[pos], fp[pos + 1]); return false; } @@ -468,6 +615,8 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con if (!crt) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: could not fetch peer certificate")); log_d("could not fetch peer certificate"); return false; } @@ -483,6 +632,8 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con // Check if fingerprints match if (memcmp(fingerprint_local, fingerprint_remote, 32)) { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: fingerprint doesn't match")); log_d("fingerprint doesn't match"); return false; } @@ -542,7 +693,7 @@ bool verify_ssl_dn(sslclient_context32 *ssl_client, const char *domain_name) return false; } -int starttlsHandshake(int s) +int starttlsHandshake(sslclient_context32 *ssl_client, int port) { int ret = 0; @@ -558,62 +709,115 @@ int starttlsHandshake(int s) struct timeval tv; FD_ZERO(&readset); - FD_SET(s, &readset); + FD_SET(ssl_client->socket, &readset); FD_ZERO(&writeset); - FD_SET(s, &writeset); + FD_SET(ssl_client->socket, &writeset); FD_ZERO(&errset); - FD_SET(s, &errset); + FD_SET(ssl_client->socket, &errset); tv.tv_sec = 1; tv.tv_usec = 0; - ret = lwip_select(s, &readset, &writeset, &errset, &tv); + ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv); if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: waiting incoming data failed!")); + goto starttls_exit; + } - ret = read(s, buf, bufLen); + ret = read(ssl_client->socket, buf, bufLen); if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: reading incoming data failed!")); goto starttls_exit; + } + else + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(buf); + } - memset(hMsg, 0, msgLen); - strcpy_P(hMsg, FPSTR("EHLO DUDE\r\n")); + if (port == 587 || port == 25) + { - ret = lwip_write(s, hMsg, strlen(hMsg)); + memset(hMsg, 0, msgLen); + strcpy_P(hMsg, FPSTR("EHLO DUDE\r\n")); + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("INFO: send SMTP command extended HELO")); + ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg)); - if (ret < 0) - goto starttls_exit; + if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: send SMTP command failed!")); + goto starttls_exit; + } - ret = lwip_select(s, &readset, &writeset, &errset, &tv); + ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv); - if (ret < 0) - goto starttls_exit; + if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: waiting incoming data failed!")); + goto starttls_exit; + } - memset(buf, 0, bufLen); - ret = lwip_read(s, buf, bufLen); + memset(buf, 0, bufLen); + ret = lwip_read(ssl_client->socket, buf, bufLen); - if (ret < 0) - goto starttls_exit; + if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: reading incoming data failed!")); + goto starttls_exit; + } + else + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(buf); + } + } memset(hMsg, 0, msgLen); strcpy_P(hMsg, FPSTR("STARTTLS\r\n")); - - ret = lwip_write(s, hMsg, strlen(hMsg)); + ssl_client->_debugCallback(FPSTR("INFO: send STARTTLS protocol command")); + ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg)); if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: send STARTTLS protocol command failed!")); goto starttls_exit; + } - ret = lwip_select(s, &readset, &writeset, &errset, &tv); + ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv); if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: waiting incoming data failed!")); goto starttls_exit; + } memset(buf, 0, bufLen); - ret = lwip_read(s, buf, bufLen); + ret = lwip_read(ssl_client->socket, buf, bufLen); if (ret < 0) + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(FPSTR("ERROR: reading incoming data failed!")); goto starttls_exit; + } + else + { + if (ssl_client->_debugCallback) + ssl_client->_debugCallback(buf); + } delete[] buf; delete[] hMsg; diff --git a/src/ssl_client32.h b/src/ssl_client32.h index dd3b5df..218fdc9 100644 --- a/src/ssl_client32.h +++ b/src/ssl_client32.h @@ -1,5 +1,5 @@ /* - *Customized ssl_client.h to support STARTTLS protocol, version 1.0.0 + *Customized ssl_client.h to support STARTTLS protocol, version 1.0.1 * * The MIT License (MIT) * Copyright (c) 2019 K. Suwatchai (Mobizt) @@ -37,6 +37,8 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" +typedef void (*DebugMsgCallback)(const char* msg); + typedef struct sslclient_context32 { int socket; bool starttls; @@ -50,6 +52,7 @@ typedef struct sslclient_context32 { mbedtls_x509_crt ca_cert; mbedtls_x509_crt client_cert; mbedtls_pk_context client_key; + DebugMsgCallback _debugCallback; unsigned long handshake_timeout; } sslclient_context32; @@ -63,5 +66,5 @@ int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length); bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char* fp, const char* domain_name); bool verify_ssl_dn(sslclient_context32 *ssl_client, const char* domain_name); -int starttlsHandshake(int s); +int starttlsHandshake(sslclient_context32 *ssl_client, int port); #endif