FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Kharim am 25 September 2025, 08:04:43

Titel: SendMail(Curl) aus Notify heraus funktioniert nicht
Beitrag von: Kharim am 25 September 2025, 08:04:43
Hi,

kurz formuliert: Warum erhalte ich ein "Passwort falsch", wenn ich SendMail(Curl) aus einer Notify heraus triggere?

SendMail
state:message:[\s\S]* {
    my $emailTo   = 'xxx';
    my $emailFrom = 'yyy';
    my $emailServer = 'smtp.zzz.de';
   
    #erzeuge Datumsangabe konform zu RFC-5322:
    my @emailDateArray = split(' ', strftime("%w %d %m %Y %H:%M:%S %z", localtime));
    $emailDateArray[0] = (qw[Sun Mon Tue Wed Thu Fri Sat])[$emailDateArray[0]] . ',';
    $emailDateArray[2] = (qw[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec])[$emailDateArray[2]-1];
    my $emailDate = join(' ', @emailDateArray);
   
    # 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}' ";
    $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";
}

Ausschnitt aus 99_myUtils.pm
sub
backup_mail()
{
fhem("set sendMail message Betreff='RaspiBackup' Sicherung durchgeführt!");
}

Ausschnitt Notify
mqtt_listener:.* {
my $nachricht=ReadingsVal("mqtt_listener","state","unbekannt");
...
if(substr($nachricht,0,18) eq "RaspiBackup Fertig")
{
#fhem("set sendMail message Betreff='RaspiBackup' Sicherung durchgeführt!");
backup_mail();
       }

Rückmeldung (Funktion ok) bei Verwendung "backup_mail()"
Email sent with status 250
Rückmeldung (Fehler) bei Verwendung "fhem set"
curl: (67) Login denied Email sent with status 535
Ein direktes Eingeben des "fhem set" Befehls in FHEM funktioniert natürlich.
Der Effekt tritt nur aus der Notify heraus auf.

Danke
Kharim
Titel: Aw: SendMail(Curl) aus Notify heraus funktioniert nicht
Beitrag von: betateilchen am 25 September 2025, 08:48:11
Vorschlag: Du baust einfach mal eine Debug Ausgabe ein, die $cmd ins Logfile schreibt. Damit kannst Du dann in den unterschiedlichen Situationen beim Aufruf (direkter Funktionsaufruf vs. Aufruf aus notify) sehen, was $cmd tatsächlich enthält.


    $cmd .= " 2>&1";
    Debug $cmd;   
    #Blockierender Aufruf von cURL in dieser Funktion via BlockingCall:


Mein Bauchgefühl läßt mich ein escaping-Problem bei irgendeinem speziellen Zeichen vermuten. Das könnte beispielsweise der Doppelpunkt zwischen user und password sein - aber es ist nur ein Gefühl.