Skip to content

Commit

Permalink
Merge pull request #5238 from tonhuisman/bugfix/N001-use-SMTP-for-por…
Browse files Browse the repository at this point in the history
…t-25

[N001] Use a non-TLS client for SMTP on port 25
  • Loading branch information
TD-er authored Feb 1, 2025
2 parents 6a95d04 + 3a07319 commit 45c4d74
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 29 deletions.
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);

// 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

# 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

0 comments on commit 45c4d74

Please sign in to comment.