➿ E-Mail senden mit CURL

Begonnen von Torxgewinde, 17 Februar 2025, 20:31:24

Vorheriges Thema - Nächstes Thema

Torxgewinde

Hallo Robert,
Klar, dieser Snippet sollte nun die Dinge alle beinhalten. Ich habe auch eine AbortFn() für den Fall eines Timeouts hinzugefügt. Danke für die Hinweise:


defmod sendMail dummy
attr sendMail readingList message password
attr sendMail setList message:textField-long password
attr sendMail userReadings state:message:[\s\S]* {\
my $emailTo   = 'you@example.com';;\
my $emailFrom = 'fhem@example.org';;\
my $emailServer = 'mail.smtpserver.de';;\
\
# Passwort aus getKeyValue abrufen\
my ($err, $emailPass) = getKeyValue("${name}_password");;\
if ($err || !defined $emailPass) {\
return "Error retrieving password: $err";;\
}\
\
my $message = ReadingsVal($name, 'message', '???');;\
my $subject = "$name: FHEM Nachricht";;\
\
# Betreff extrahieren und aus der Nachricht entfernen\
if ($message =~ s/(?:Subject|Betreff)=["'](.*?)["']//) {\
$subject = $1;;\
}\
\
# Empfänger extrahieren und aus der Nachricht entfernen\
if ($message =~ s/(?:To|An)=["'](.*?)["']//) {\
$emailTo = $1;;\
}\
\
#Dateianhänge bestimmen\
my @attachments;;\
while ($message =~ s/(?:Attachment|Anhang)=["'](.*?)["']//) {\
my $file = $1;;\
return ">>$file<< not found, not sending email" unless (-e $file);;\
push (@attachments, $file);;\
}\
\
#der curl Befehl wird hier aufgebaut:\
my $cmd = "curl -m 19 --noproxy '*' --no-progress-meter --ssl-reqd smtps://$emailServer:465 ";;\
$cmd .= "--user '$emailFrom:$emailPass' --mail-from '$emailFrom' --mail-rcpt '$emailTo' ";;\
$cmd .= "--write-out 'Email sent with status %{http_code}\n' ";;\
$cmd .= "-H 'Subject: $subject' ";;\
$cmd .= "-H 'From: $emailFrom' ";;\
\
#multipart/alternative für Text und HTML EMail Body\
$cmd .= "-F '=(;;type=multipart/alternative' ";;\
\
# Leerzeichen und <br> bzw <br \> am Anfang entfernen:\
$message =~ s/^(\s|<br(?:[ \/]+)>)+//;;\
# Leerzeichen und <br> bzw <br \> am Ende entfernen:\
$message =~ s/(\s|<br(?:[ \/]+)>)+$//;;\
\
#Plaintext E-Mail Inhalt an cURL:\
$cmd .= "-F \"=$message;;type=text/plain;; charset=UTF-8\" ";;\
#ersetze \n bzw. \r\n durch ein HTML-tag <br />:\
$message =~ s/\r?\n/<br \/>/g;;\
\
#HTML E-Mail Inhalt an cURL:\
$cmd .= "-F '= <body>$message</body>;;type=text/html;; charset=UTF-8' ";;\
$cmd .= "-F '=)' ";;\
\
#jetzt alle Attachments (0..N) anhängen:\
foreach my $file (@attachments) {\
$cmd .= "-F '=@".$file.";;encoder=base64' ";;\
}\
\
#stderr auch mit in den output sammeln:\
$cmd .= " 2>&1";;\
\
#Blockierender Aufruf von cURL in dieser Funktion via BlockingCall:\
if (!defined &sendMailfunc1) {\
*sendMailfunc1 = sub ($) {\
my ($param) = @_;;\
my $result;;\
$result = qx/$param/;;\
$result = MIME::Base64::encode_base64($result);;\
$result =~ s/\n//g;;\
return $result;;\
}\
}\
\
#Rückgabe über diese Funktion,\
#anzeigen in dem reading dieses UserReadings:\
if (!defined &sendMailfunc2) {\
*sendMailfunc2 = sub ($) {\
my ($result) = @_;;\
my $hash = $defs{$name};;\
$result = MIME::Base64::decode_base64($result);;\
readingsSingleUpdate($hash, $reading, $result, 1);;\
}\
}\
\
#funktion falls BlockingCall abgebrochen wird:\
if (!defined &sendMailfunc3) {\
*sendMailfunc3 = sub ($) {\
my ($result) = @_;;\
my $hash = $defs{$name};;\
readingsSingleUpdate($hash, $reading, $result, 1);;\
}\
}\
\
BlockingCall("sendMailfunc1", $cmd, "sendMailfunc2", 20, "sendMailfunc3", "Error: timeout");;\
\
return "started cURL command...";;\
},\
state:password:.* {\
# Passwort speichern\
my $ret = setKeyValue("${name}_password", ReadingsVal($name, 'password', undef)) // "password stored";;\
\
#password wieder aus der Variablen rausnehmen, soll nicht sichtbar bleiben:\
#\
# Hinweis: das Password taucht beim Setzen hierüber im Event-Log auf!\
# Alternativ: { setKeyValue("sendMail_password", "geheimesPasswort") }\
readingsBulkUpdate($hash, "password", "****");;\
\
return "$ret";;\
}

moskito

Hallo Torxgewinde,
nachdem mein Email-Client Probleme beim Anzeigen der mit deiner Lösung versendeten Emails hatte (Abrufzeit vom Server statt Zeitpunkt der Emailversendung), habe ich den Email Header um das Feld "Date:" erweitert. Sind nur zwei Zeilen (suche nach emailDate) und funktioniert bei mir optimal.

state:message:[\s\S]* {
        my $emailTo   = 'you@example.com';
my $emailFrom = 'fhem@example.org';
my $emailServer = 'mail.smtpserver.de';
my $emailDate = strftime "%a, %d %b %Y %H:%M:%S %z", localtime;


# Passwort aus getKeyValue abrufen
my ($err, $emailPass) = getKeyValue("${name}_password");
if ($err || !defined $emailPass) {
return "Error retrieving password: $err";
}

my $message = ReadingsVal($name, 'message', '???');
my $subject = "$name: FHEM Meldung";

# Betreff extrahieren und aus der Nachricht entfernen
if ($message =~ s/(?:Subject|Betreff)=["'](.*?)["']//) {
$subject = $1;
}

# Empfänger extrahieren und aus der Nachricht entfernen
if ($message =~ s/(?:To|An)=["'](.*?)["']//) {
$emailTo = $1;
}

#Dateianhänge bestimmen
my @attachments;
while ($message =~ s/(?:Attachment|Anhang)=["'](.*?)["']//) {
my $file = $1;
return ">>$file<< not found, not sending email" unless (-e $file);
push (@attachments, $file);
}

#der curl Befehl wird hier aufgebaut:
my $cmd = "curl -m 19 --noproxy '*' --no-progress-meter --ssl-reqd smtps://$emailServer:465 ";
$cmd .= "--user '$emailFrom:$emailPass' --mail-from '$emailFrom' --mail-rcpt '$emailTo' ";
$cmd .= "--write-out 'Email sent with status %{http_code}\n' ";
$cmd .= "-H 'Subject: $subject' ";
$cmd .= "-H 'From: $emailFrom' ";
$cmd .= "-H 'Date: $emailDate' ";

#multipart/alternative für Text und HTML EMail Body
$cmd .= "-F '=(;type=multipart/alternative' ";

# Leerzeichen und <br> bzw <br \> am Anfang entfernen:
$message =~ s/^(\s|<br(?:[ \/]+)>)+//;
# Leerzeichen und <br> bzw <br \> am Ende entfernen:
$message =~ s/(\s|<br(?:[ \/]+)>)+$//;

#Plaintext E-Mail Inhalt an cURL:
$cmd .= "-F \"=$message;type=text/plain; charset=UTF-8\" ";
#ersetze \n bzw. \r\n durch ein HTML-tag <br />:
$message =~ s/\r?\n/<br \/>/g;

#HTML E-Mail Inhalt an cURL:
$cmd .= "-F '= <body>$message</body>;type=text/html; charset=UTF-8' ";
$cmd .= "-F '=)' ";

#jetzt alle Attachments (0..N) anhängen:
foreach my $file (@attachments) {
$cmd .= "-F '=@".$file.";encoder=base64' ";
}

#stderr auch mit in den output sammeln:
$cmd .= " 2>&1";

#Blockierender Aufruf von cURL in dieser Funktion via BlockingCall:
if (!defined &sendMailfunc1) {
*sendMailfunc1 = sub ($) {
my ($param) = @_;
my $result;
$result = qx/$param/;
$result = MIME::Base64::encode_base64($result);
$result =~ s/\n//g;
return $result;
}
}

#Rückgabe über diese Funktion,
#anzeigen in dem reading dieses UserReadings:
if (!defined &sendMailfunc2) {
*sendMailfunc2 = sub ($) {
my ($result) = @_;
my $hash = $defs{$name};
$result = MIME::Base64::decode_base64($result);
readingsSingleUpdate($hash, $reading, $result, 1);
}
}

#funktion falls BlockingCall abgebrochen wird:
if (!defined &sendMailfunc3) {
*sendMailfunc3 = sub ($) {
my ($result) = @_;
my $hash = $defs{$name};
readingsSingleUpdate($hash, $reading, $result, 1);
}
}

BlockingCall("sendMailfunc1", $cmd, "sendMailfunc2", 20, "sendMailfunc3", "Error: timeout");

return "started cURL command...";
},
state:password:.* {
# Passwort speichern
my $ret = setKeyValue("${name}_password", ReadingsVal($name, 'password', undef)) // "password stored";

#password wieder aus der Variablen rausnehmen, soll nicht sichtbar bleiben:
#
# Hinweis: das Password taucht beim Setzen hierüber im Event-Log auf!
# Alternativ: { setKeyValue("sendMail_password", "geheimesPasswort") }
readingsBulkUpdate($hash, "password", "****");

return "$ret";
}
 

Gruß
Danny
FHEM auf Intel NUC/Proxmox & Debian 12 + HM-CFG-USB + zigbee2mqtt + Zwave + Enocean

Torxgewinde

Hi,
Danke für die Ergänzung, das finde ich gut! Ich habe es auch im Wiki ergänzt.
 
Als komplettes Device für die Freunde von Copy & Paste:
defmod sendMail dummy
attr sendMail readingList message password
attr sendMail setList message:textField-long password
attr sendMail userReadings state:message:[\s\S]* {\
my $emailTo   = 'du@example.com';;\
my $emailFrom = 'fhem@example.de';;\
my $emailServer = 'mail.your-server.de';;\
my $emailDate = strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time()));;\
\
# Passwort aus getKeyValue abrufen\
my ($err, $emailPass) = getKeyValue("${name}_password");;\
if ($err || !defined $emailPass) {\
return "Error retrieving password: $err";;\
}\
\
my $message = ReadingsVal($name, 'message', '???');;\
my $subject = "$name: FHEM Nachricht";;\
\
# Betreff extrahieren und aus der Nachricht entfernen\
if ($message =~ s/(?:Subject|Betreff)=["'](.*?)["']//) {\
$subject = $1;;\
}\
\
# Empfänger extrahieren und aus der Nachricht entfernen\
if ($message =~ s/(?:To|An)=["'](.*?)["']//) {\
$emailTo = $1;;\
}\
\
#Dateianhänge bestimmen\
my @attachments;;\
while ($message =~ s/(?:Attachment|Anhang)=["'](.*?)["']//) {\
my $file = $1;;\
return ">>$file<< not found, not sending email" unless (-e $file);;\
    push (@attachments, $file);;\
}\
\
#der curl Befehl wird hier aufgebaut:\
my $cmd = "curl -m 19 --noproxy '*' --no-progress-meter --ssl-reqd smtps://$emailServer:465 ";;\
$cmd .= "--user '$emailFrom:$emailPass' --mail-from '$emailFrom' --mail-rcpt '$emailTo' ";;\
$cmd .= "--write-out 'Email sent with status %{http_code}\n' ";;\
$cmd .= "-H 'Subject: $subject' ";;\
$cmd .= "-H 'From: $emailFrom' ";;\
$cmd .= "-H 'Date: $emailDate' ";;\
\
#multipart/alternative für Text und HTML EMail Body\
$cmd .= "-F '=(;;type=multipart/alternative' ";;\
\
# Leerzeichen und <br> bzw <br \> am Anfang entfernen:\
$message =~ s/^(\s|<br(?:[ \/]+)>)+//;;\
# Leerzeichen und <br> bzw <br \> am Ende entfernen:\
$message =~ s/(\s|<br(?:[ \/]+)>)+$//;;\
\
#Plaintext E-Mail Inhalt an cURL:\
$cmd .= "-F \"=$message;;type=text/plain;; charset=UTF-8\" ";;\
#ersetze \n bzw. \r\n durch ein HTML-tag <br />:\
$message =~ s/\r?\n/<br \/>/g;;\
\
#HTML E-Mail Inhalt an cURL:\
$cmd .= "-F '= <body>$message</body>;;type=text/html;; charset=UTF-8' ";;\
$cmd .= "-F '=)' ";;\
\
#jetzt alle Attachments (0..N) anhängen:\
foreach my $file (@attachments) {\
    $cmd .= "-F '=@".$file.";;encoder=base64' ";;\
}\
\
#stderr auch mit in den output sammeln:\
$cmd .= " 2>&1";;\
\
#Blockierender Aufruf von cURL in dieser Funktion via BlockingCall:\
if (!defined &sendMailfunc1) {\
*sendMailfunc1 = sub ($) {\
my ($param) = @_;;\
my $result;;\
$result = qx/$param/;;\
$result = MIME::Base64::encode_base64($result);;\
$result =~ s/\n//g;;\
return $result;;\
}\
}\
\
#Rückgabe über diese Funktion,\
#anzeigen in dem reading dieses UserReadings:\
if (!defined &sendMailfunc2) {\
*sendMailfunc2 = sub ($) {\
my ($result) = @_;;\
my $hash = $defs{$name};;\
$result = MIME::Base64::decode_base64($result);;\
readingsSingleUpdate($hash, $reading, $result, 1);;\
}\
}\
\
#funktion falls BlockingCall abgebrochen wird:\
if (!defined &sendMailfunc3) {\
*sendMailfunc3 = sub ($) {\
my ($result) = @_;;\
my $hash = $defs{$name};;\
readingsSingleUpdate($hash, $reading, $result, 1);;\
}\
}\
\
BlockingCall("sendMailfunc1", $cmd, "sendMailfunc2", 20, "sendMailfunc3", "Error: timeout");;\
\
return "started cURL command...";;\
},\
state:password:.* {\
# Passwort speichern\
my $ret = setKeyValue("${name}_password", ReadingsVal($name, 'password', undef)) // "password stored";;\
\
#password wieder aus der Variablen rausnehmen, soll nicht sichtbar bleiben:\
#\
# Hinweis: das Password taucht beim Setzen hierüber im Event-Log auf!\
# Alternativ: { setKeyValue("sendMail_password", "geheimesPasswort") }\
readingsBulkUpdate($hash, "password", "****");;\
\
return "$ret";;\
}

MiWe58

Hallo,
nach einem fatalen Crash bin ich dabei, meine umfangreich gewachsene, aber über 10 Jahre alte fhem-Installation komplett neu aufzubauen. Unter anderem möchte ich vom alten debian "SendMail" auf die "curl"-Variante umsteigen, wie sie hier diskutiert und entwickelt wird/wurde.

Orientiert habe ich mich dabei an der Beschreibung im fhem wiki und diesem Thread.
Leider bekomme ich beim Versenden einer Nachricht die folgende Fehlermeldung im Status des "sendMail-dummys" angezeigt:

Error evaluating sendMail userReading state: Experimental aliasing via reference not enabled at (eval 393989) line 1.
Damit kann ich leider nichts anfangen und bin entsprechend aufgeschmissen. Im Web habe ich nur Hinweise gefunden, dass es möglicherweise mit der Verwendung von Pearl-Befehlen im Code zusammenhängen könnte.

Wie beschrieben, habe ich den gesamten Raspberry V komplett neu aufgesetzt. Es sollten von jeder Komponente die aktuellste Version installiert sein.

Hat Jemand einen Ansatz zur Problembeseitigung?
Vielen Dank
Devices: RasPi V, HomeMatic, PICCU, Modbus, Heliotherm-Wärmepumpe, SMA PV-Anlage, Easee Laderoboter
Steuerung: Rollos, Beleuchtung, Heizung-Heliotherm, Heizung-Heizkreise, PV-Anlage-Eigenverbrauch, Alarm, Zugang, Wasser

bertl

Ich gehe davon aus, dass es ein Backslash Problem ist!

Du hast wahrscheinlich beim Copy/Paste irgendwo einen Backslash zuviel in deinem Code.

Poste mal das list von sendMail

bertl

Hallo Torxgewinde,

manche Email-Programme stören sich daran, wenn der Absender im Header nicht eingetragen ist (als Spam behandelt oder als BCC abgelegt).

Um dein sendMail noch universeller zu machen, könnte man dieses Detail wie folgt ergänzen:

  $cmd .= "-H 'To: $emailTo' ";
Gruß Robert

MiWe58

Hallo:

Zitat von: bertl am 25 April 2025, 13:17:49Ich gehe davon aus, dass es ein Backslash Problem ist!

Du hast wahrscheinlich beim Copy/Paste irgendwo einen Backslash zuviel in deinem Code.

Poste mal das list von sendMail


Anbei der eingefügte Code:
state:message:[\s\S]* {\ my $emailTo = 'mxxx@xxx.de';\ my $emailFrom = 'mxxx@xxx.de';\ my $emailServer = 'securesmtp.t-online.de';\ my $emailDate = strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time()));\ \ # Passwort aus getKeyValue abrufen\ my ($err, $emailPass) = getKeyValue("${name}_password");\ if ($err || !defined $emailPass) {\ return "Error retrieving password: $err";\ }\ \ my $message = ReadingsVal($name, 'message', '???');\ my $subject = "$name: FHEM Nachricht";\ \ # Betreff extrahieren und aus der Nachricht entfernen\ if ($message =~ s/(?:Subject|Betreff)=["'](.*?)["']//) {\ $subject = $1;\ }\ \ # Empfänger extrahieren und aus der Nachricht entfernen\ if ($message =~ s/(?:To|An)=["'](.*?)["']//) {\ $emailTo = $1;\ }\ \ #Dateianhänge bestimmen\ my @attachments;\ while ($message =~ s/(?:Attachment|Anhang)=["'](.*?)["']//) {\ my $file = $1;\ return ">>$file<< not found, not sending email" unless (-e $file);\ push (@attachments, $file);\ }\ \ #der curl Befehl wird hier aufgebaut:\ my $cmd = "curl -m 19 --noproxy '*' --no-progress-meter --ssl-reqd smtps://$emailServer:465 ";\ $cmd .= "--user '$emailFrom:$emailPass' --mail-from '$emailFrom' --mail-rcpt '$emailTo' ";\ $cmd .= "--write-out 'Email sent with status %{http_code}\n' ";\ $cmd .= "-H 'Subject: $subject' ";\ $cmd .= "-H 'From: $emailFrom' ";\ $cmd .= "-H 'Date: $emailDate' ";\ \ #multipart/alternative für Text und HTML EMail Body\ $cmd .= "-F '=(;type=multipart/alternative' ";\ \ # Leerzeichen und <br> bzw <br \> am Anfang entfernen:\ $message =~ s/^(\s|<br(?:[ \/]+)>)+//;\ # Leerzeichen und <br> bzw <br \> am Ende entfernen:\ $message =~ s/(\s|<br(?:[ \/]+)>)+$//;\ \ #Plaintext E-Mail Inhalt an cURL:\ $cmd .= "-F \"=$message;type=text/plain; charset=UTF-8\" ";\ #ersetze \n bzw. \r\n durch ein HTML-tag <br />:\ $message =~ s/\r?\n/<br \/>/g;\ \ #HTML E-Mail Inhalt an cURL:\ $cmd .= "-F '= <body>$message</body>;type=text/html; charset=UTF-8' ";\ $cmd .= "-F '=)' ";\ \ #jetzt alle Attachments (0..N) anhängen:\ foreach my $file (@attachments) {\ $cmd .= "-F '=@".$file.";encoder=base64' ";\ }\ \ #stderr auch mit in den output sammeln:\ $cmd .= " 2>&1";\ \ #Blockierender Aufruf von cURL in dieser Funktion via BlockingCall:\ if (!defined &sendMailfunc1) {\ *sendMailfunc1 = sub ($) {\ my ($param) = @_;\ my $result;\ $result = qx/$param/;\ $result = MIME::Base64::encode_base64($result);\ $result =~ s/\n//g;\ return $result;\ }\ }\ \ #Rückgabe über diese Funktion,\ #anzeigen in dem reading dieses UserReadings:\ if (!defined &sendMailfunc2) {\ *sendMailfunc2 = sub ($) {\ my ($result) = @_;\ my $hash = $defs{$name};\ $result = MIME::Base64::decode_base64($result);\ readingsSingleUpdate($hash, $reading, $result, 1);\ }\ }\ \ #funktion falls BlockingCall abgebrochen wird:\ if (!defined &sendMailfunc3) {\ *sendMailfunc3 = sub ($) {\ my ($result) = @_;\ my $hash = $defs{$name};\ readingsSingleUpdate($hash, $reading, $result, 1);\ }\ }\ \ BlockingCall("sendMailfunc1", $cmd, "sendMailfunc2", 20, "sendMailfunc3", "Error: timeout");\ \ return "started cURL command...";\ },\ state:password:.* {\ # Passwort speichern\ my $ret = setKeyValue("${name}_password", ReadingsVal($name, 'password', undef)) // "password stored";\ \ #password wieder aus der Variablen rausnehmen, soll nicht sichtbar bleiben:\ #\ # Hinweis: das Password taucht beim Setzen hierüber im Event-Log auf!\ # Alternativ: { setKeyValue("sendMail_password", "geheimesPasswort") }\ readingsBulkUpdate($hash, "password", "****");\ \ return "$ret";\ }

Ich hatte die Meldung unabhängig davon, ob ich aus dem fhem wiki oder hier aus dem Thread kopiert habe.
Devices: RasPi V, HomeMatic, PICCU, Modbus, Heliotherm-Wärmepumpe, SMA PV-Anlage, Easee Laderoboter
Steuerung: Rollos, Beleuchtung, Heizung-Heliotherm, Heizung-Heizkreise, PV-Anlage-Eigenverbrauch, Alarm, Zugang, Wasser

bertl

Die Frage ist nicht von wo du es kopiert hast, sonder wohin du es eingefügt hast!

Den Code von Torxgewinde muss man unter "Raw definition" einfügen, dann klappt das auch.
Siehe: https://wiki.fhem.de/wiki/Import_von_Code_Snippets

MiWe58

Zitat von: bertl am 25 April 2025, 16:41:43Die Frage ist nicht von wo du es kopiert hast, sonder wohin du es eingefügt hast!

Den Code von Torxgewinde muss man unter "Raw definition" einfügen, dann klappt das auch.
Siehe: https://wiki.fhem.de/wiki/Import_von_Code_Snippets


SUPER, Danke
Wieder etwas gelernt!
Devices: RasPi V, HomeMatic, PICCU, Modbus, Heliotherm-Wärmepumpe, SMA PV-Anlage, Easee Laderoboter
Steuerung: Rollos, Beleuchtung, Heizung-Heliotherm, Heizung-Heizkreise, PV-Anlage-Eigenverbrauch, Alarm, Zugang, Wasser

mabula

#24
Durch Umzug auf neue Hardware und Bookworm bin ich auch auf das Problem mit sendmail gestoßen. Der Umstieg auf curl hat noch seine Tücken. Für welche e-mail Provider ist der wiki Code getestet worden? Mit meinen FREENET Konto gibt es Probleme. SSL/TLS kann zwar eingestellt werden, allerdings muss das Passwort "normal" (Thunderbird) übertragen werden, also unverschlüsselt? Bisher habe ich noch keine passende --login-option gefunden, oder drehe ich an der falschen Stelle.
Fehlermeldung: curl: (28) Operation timed out after 19000 milliseconds with 0 bytes received Email sent with status 000

Grüße Hans-Jörg

Mit -v

* Trying 195.4.92.210:465...
* Connected to mx.freenet.de (195.4.92.210) port 465 (#0)
* Operation timed out after 19001 milliseconds with 0 bytes received
* Closing connection 0 curl: (28) Operation timed out after 19001 milliseconds with 0 bytes received Email sent with status 000
FHEM auf RPI mit FS20, Homematic, ELERO, Zigbee, Eigenbau z.B. Heizölsensor auf Basis Arduino, Anemometer; Sprachsteuerung offline über vosk/Python

moskito

Nach einigem suchen fand ich ein Problem mit curl und freenet, welches mit der zusätzlichen Option "--sasl-ir" behoben werden konnte. Probier das doch mal aus. Wobei mir die Timeout Fehlermeldung in diesem Zusammenhang ungewöhnlich erscheint. In meinem Thunderbird ist ebenfalls Passwort "normal" definiert, und sendMail funktioniert wie hier angegeben.

Gruß
Danny
FHEM auf Intel NUC/Proxmox & Debian 12 + HM-CFG-USB + zigbee2mqtt + Zwave + Enocean

mabula

#26
Danke Danny,
diesen Hinweis habe ich auch schon getestet. Mit -v erhalte ich diese Meldungen:
*   Trying 195.4.92.210:465...
* Connected to mx.freenet.de (195.4.92.210) port 465 (#0)
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [6 bytes data]
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
{ [325 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [4641 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [392 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
} [8 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate:
*  subject: C=DE; ST=Hamburg; L=Hamburg; O=freenet.de GmbH; CN=*.freenet.de
*  start date: Feb 18 08:35:54 2025 GMT
*  expire date: Feb 22 23:59:59 2026 GMT
*  subjectAltName: host "mx.freenet.de" matched cert's "*.freenet.de"
*  issuer: C=DE; O=Deutsche Telekom Security GmbH; CN=Telekom Security ServerID OV Class 2 CA
*  SSL certificate verify ok.
{ [5 bytes data]
< 220 sub4.mail.fnrz.de ESMTP Exim 4.96 Sat, 26 Apr 2025 23:44:26 +0200
} [5 bytes data]
> EHLO Home
{ [5 bytes data]
< 250-sub4.mail.fnrz.de Hello ip-046-223-247-227.um13.pools.vodafone-ip.de [xxxxxxxxx]
< 250-SIZE 209715200
< 250-8BITMIME
< 250-AUTH LOGIN PLAIN
< 250-SMTPUTF8
< 250 HELP
} [5 bytes data]
> AUTH PLAIN AGJyZXltYXllckBmdkusbmV0LmRlACoqKio=
{ [5 bytes data]
< 535 Incorrect authentication data
* Closing connection 0
} [5 bytes data]
* TLSv1.3 (OUT), TLS alert, close notify (256):
} [2 bytes data]
curl: (67) Login denied
Email sent with status 535

Gruß Hans-Jörg
FHEM auf RPI mit FS20, Homematic, ELERO, Zigbee, Eigenbau z.B. Heizölsensor auf Basis Arduino, Anemometer; Sprachsteuerung offline über vosk/Python

moskito

Jetzt gibt es immerhin eine Verbindung zum Server mit Details.
Ich kann jetzt allerdings auch nur mit "try and error" weiterhelfen:
  • Mit Port 587 probieren: smtps://$emailserver:587
  • andere "--login-options" durchprobieren, wobei das in deiner Ausgabe angezeigte "250-AUTH LOGIN PLAIN / > AUTH PLAIN" schon richtig ist
  • Zur Sicherheit nochmal User/Password überprüfen

Hier eine Seite wo der Ablauf der Kommunikation beschrieben wird:
https://www.samlogic.net/articles/smtp-commands-reference-auth.htm

Gruß
Danny
FHEM auf Intel NUC/Proxmox & Debian 12 + HM-CFG-USB + zigbee2mqtt + Zwave + Enocean

mabula

Danke Danny, werde ich testen. Können Sonderzeichen im Passwort bei curl Probleme machen?

Gruß Hans-Jörg
FHEM auf RPI mit FS20, Homematic, ELERO, Zigbee, Eigenbau z.B. Heizölsensor auf Basis Arduino, Anemometer; Sprachsteuerung offline über vosk/Python

mabula

Nochmals Danke an Danny.
Habe das Passwort geändert, lag wohl an den Sonderzeichen.

Gruß Hans-Jörg
FHEM auf RPI mit FS20, Homematic, ELERO, Zigbee, Eigenbau z.B. Heizölsensor auf Basis Arduino, Anemometer; Sprachsteuerung offline über vosk/Python