SendMail(Curl) aus Notify heraus funktioniert nicht

Begonnen von Kharim, 25 September 2025, 08:04:43

Vorheriges Thema - Nächstes Thema

Kharim

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
Raspberry Pi 2 + Minibian + 2x MAX Cube CUN (868/433Mhz) + Thermostate + Fensterkontakte + Taster+RGB-LED Band über pigpiod + TFA Sensoren 30.3169/3125
Raspberry Pi 2 + Minibian +Z-Wave (USB) + Bewegungsmelder + Fensterkontakt + Sirene + SMS Steuer-/Benachrichtigung (ohne Internet)

betateilchen

#1
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.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!