Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[N001] Use a non-TLS client for SMTP on port 25 #5238

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/source/Notify/N001.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ From the *Notifications* page, press *Edit* on an available *Nr* option. Next, C
* SMTP Server Settings

* **Domain :** Mail provider domain.
* **Server :** Mail server address (DNS or IP number). Must support non-secure SMTP.
* **Server :** Mail server address (DNS or IP number).
* **Port :** Server port number. (see note below)
* **Timeout :** Maximum allowed time for server reply. Increase value if server timeouts occur.

Expand Down Expand Up @@ -114,6 +114,8 @@ ESP8266 simply doesn't have enough free memory available to setup a SSL connecti

Only SSL port 465 is supported, as for using port 587 (typically named "TLS") extra steps are required to make a connection.
This may be added later.

ESP32: (With TLS enabled in the build) To use the basic SMTP protocol (not SMTPS), configure port ``25`` or ``2525``. For other port numbers, a secure SMTP connection will be attempted.
|

Email Server Requirements with SSL
Expand Down
73 changes: 45 additions & 28 deletions src/src/NotifierStructs/N001_data_struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,48 @@

bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, String& subject, String& body)
{
bool myStatus = false;
bool failFlag = false;
bool myStatus = false;
bool failFlag = false;
bool deleteClient = true;

WiFiClient *client = nullptr;

# if FEATURE_EMAIL_TLS

// values are based on the NPLUGIN_001_PKT_SZ
BearSSL::WiFiClientSecure_light client(4096, 4096);
client.setUtcTime_fcn(getUnixTime);
client.setCfgTime_fcn(get_build_unixtime);
client.setTrustAnchor(Tasmota_TA, Tasmota_TA_size);

client.setInsecure();
BearSSL::WiFiClientSecure_light secureClient(4096, 4096);
tonhuisman marked this conversation as resolved.
Show resolved Hide resolved

// Port 25 or 2525 is a standard WiFiClient, all else is a secure client...
if ((notificationsettings.Port != 25) && (notificationsettings.Port != 2525)) {
secureClient.setUtcTime_fcn(getUnixTime);
secureClient.setCfgTime_fcn(get_build_unixtime);
secureClient.setTrustAnchor(Tasmota_TA, Tasmota_TA_size);
secureClient.setInsecure();
client = &secureClient;
deleteClient = false;
} else {
client = new (std::nothrow) WiFiClient();

if (!client) { return false; }
}

# else // if FEATURE_EMAIL_TLS

// Use WiFiClient class to create TCP connections
WiFiClient client;
client = new (std::nothrow) WiFiClient();

if (!client) { return false; }
# endif // if FEATURE_EMAIL_TLS

tonhuisman marked this conversation as resolved.
Show resolved Hide resolved
# ifdef MUSTFIX_CLIENT_TIMEOUT_IN_SECONDS

// See: https://github.com/espressif/arduino-esp32/pull/6676
client.setTimeout((notificationsettings.Timeout_ms + 500) / 1000); // in seconds!!!!
Client *pClient = &client;
client->setTimeout((notificationsettings.Timeout_ms + 500) / 1000); // in seconds!!!!
Client *pClient = client;
pClient->setTimeout(notificationsettings.Timeout_ms);
# else // ifdef MUSTFIX_CLIENT_TIMEOUT_IN_SECONDS
client.setTimeout(notificationsettings.Timeout_ms); // in msec as it should be!
client->setTimeout(notificationsettings.Timeout_ms); // in msec as it should be!
# endif // ifdef MUSTFIX_CLIENT_TIMEOUT_IN_SECONDS

# ifndef BUILD_NO_DEBUG
Expand All @@ -61,14 +76,14 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
}
# endif // ifndef BUILD_NO_DEBUG

if (!connectClient(client, notificationsettings.Server, notificationsettings.Port, notificationsettings.Timeout_ms)) {
if (!connectClient(*client, notificationsettings.Server, notificationsettings.Port, notificationsettings.Timeout_ms)) {
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
# if FEATURE_EMAIL_TLS
addLog(LOG_LEVEL_ERROR, strformat(
F("Email: Error connecting to %s:%u Error code: %d"),
notificationsettings.Server,
notificationsettings.Port,
client.getLastError()));
secureClient.getLastError()));

# else // if FEATURE_EMAIL_TLS
addLog(LOG_LEVEL_ERROR, strformat(
Expand Down Expand Up @@ -176,7 +191,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
}

# if FEATURE_EMAIL_TLS
client.setDomainName(notificationsettings.Domain);
secureClient.setDomainName(notificationsettings.Domain);

# endif // if FEATURE_EMAIL_TLS

Expand All @@ -201,7 +216,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
// exit using break;
// However this is way too complex using both a failFlag and break
// and not even consistently.
if (!NPlugin_001_MTA(client, EMPTY_STRING, 220, clientTimeout)) {
if (!NPlugin_001_MTA(*client, EMPTY_STRING, 220, clientTimeout)) {
# ifndef BUILD_NO_DEBUG

if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
Expand All @@ -220,7 +235,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
const String astr = strformat(F("EHLO %s"), notificationsettings.Domain);

if (!NPlugin_001_MTA(
client,
*client,
astr,
250,
clientTimeout)) {
Expand All @@ -239,12 +254,12 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St

bool done = false;

while (client.available() && !done) {
while (client->available() && !done) {
if (timeOutReached(timer)) {
failFlag = true;
break;
}
done = safeReadStringUntil(client, replyStr, '\n', NPLUGIN_001_PKT_SZ);
done = safeReadStringUntil(*client, replyStr, '\n', NPLUGIN_001_PKT_SZ);
catStr += replyStr;
}

Expand All @@ -269,7 +284,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
}
# endif // ifndef BUILD_NO_DEBUG

if (!NPlugin_001_Auth(client, notificationsettings.User, notificationsettings.Pass, clientTimeout)) {
if (!NPlugin_001_Auth(*client, notificationsettings.User, notificationsettings.Pass, clientTimeout)) {
# ifndef BUILD_NO_DEBUG

addLog(LOG_LEVEL_DEBUG, F("Email: User/Pass Fail"));
Expand All @@ -286,7 +301,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St

const String astr = strformat(F("MAIL FROM:<%s>"), email_address.c_str());

if (!NPlugin_001_MTA(client, astr, 250, clientTimeout)) {
if (!NPlugin_001_MTA(*client, astr, 250, clientTimeout)) {
# ifndef BUILD_NO_DEBUG
addLog(LOG_LEVEL_DEBUG, F("Email: Addr Fail"));
# endif // ifndef BUILD_NO_DEBUG
Expand All @@ -313,7 +328,7 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
addLog(LOG_LEVEL_INFO, concat(F("Email: To "), emailTo));
}

if (!NPlugin_001_MTA(client, strformat(F("RCPT TO:<%s>"), emailTo.c_str()), 250, clientTimeout))
if (!NPlugin_001_MTA(*client, strformat(F("RCPT TO:<%s>"), emailTo.c_str()), 250, clientTimeout))
{
break;
}
Expand All @@ -323,14 +338,14 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
}

if (!failFlag) {
if (!NPlugin_001_MTA(client, F("DATA"), 354, clientTimeout)) {
if (!NPlugin_001_MTA(*client, F("DATA"), 354, clientTimeout)) {
failFlag = true;
break;
}
}

if (!failFlag) {
if (!NPlugin_001_MTA(client, strformat(F("%s%s\r\n.\r\n"), mailheader.c_str(), body.c_str()), 250, clientTimeout)) {
if (!NPlugin_001_MTA(*client, strformat(F("%s%s\r\n.\r\n"), mailheader.c_str(), body.c_str()), 250, clientTimeout)) {
failFlag = true;
break;
}
Expand All @@ -341,22 +356,24 @@ bool NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, St
myStatus = true;
}

NPlugin_001_MTA(client, F("QUIT"), 221, clientTimeout); // Sent successfully, close SMTP protocol, ignore failure
NPlugin_001_MTA(*client, F("QUIT"), 221, clientTimeout); // Sent successfully, close SMTP protocol, ignore failure
break;
}
}

// client.PR_9453_FLUSH_TO_CLEAR();
client.stop();

if (myStatus == true) {
if (myStatus) {
addLog(LOG_LEVEL_INFO, F("Email: Connection Closed Successfully"));
} else {
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
addLogMove(LOG_LEVEL_ERROR, concat(F("Email: Connection Closed With Error. Used header: "), mailheader));
}
}
}

client->stop();

if (deleteClient) { delete client; }

return myStatus;
}

Expand Down