Email senden per smtplib - verwendung T-online, SSL

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Hartmannsgruber
User
Beiträge: 89
Registriert: Mittwoch 15. Januar 2014, 22:30
Wohnort: Bad Kötzting
Kontaktdaten:

Servus liebes Forum,

mich quält wieder ein Problem, zu dem ich im Internet keine Lösung finden kann.
Grundproblem: Ich möchte mit smtplib eine Email aus einem Skript versenden.
Da ich keinen lokalen SMTP Server auf meinem Rechner laufen habe wollte ich den von T-online verwenden.
In den Internetvideos die ich gesehen hatte wurde entweder ein lokaler Server, oder der von gmail verwendet.
Da ich beides nicht besitze sondern ein t-online Konto verwenden, wäre es doch einfach dies zu verwenden.

Code: Alles auswählen

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg.set_content = ("Hallo Welt")
msg["Subject"] = "Test Email"
msg["From"] = "xyz.xyz@t-online.de"
msg["To"] = "abc.abc@t-online.de"

server = smtplib.SMTP_SSL("securesmtp.t-online.de", 465)
server.connect()
Wenn das Skript zur Zeile mit server.connect() kommt erhalte ich folgenden Fehler:
ConnectionRefusedError: [WinError 10061] Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte.

an was liegt das?
Wie gesagt, im Internet konnte ich leider keine Lösung hierzu finden.

Lg
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Du musst dich authentifizieren. Das kannst du über die SMTP-Session mittels login()-Methode machen. Für das Session-Objekt selbst solltest du mit dem with-Statement arbeiten, damit die Session im Anschluss auch wieder sauber beendet wird.
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sls: Dazu muss man aber erst einmal eine Verbindung haben. Wenn das `connect()` schon nicht funktioniert, kann man danach schlecht ein `login()` machen. 😉
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Hartmannsgruber
User
Beiträge: 89
Registriert: Mittwoch 15. Januar 2014, 22:30
Wohnort: Bad Kötzting
Kontaktdaten:

Vielen Dank für eure Antworten.
Ich habe den Fehler zufällig gefunden.
Die connect() funktion benötigt noch als Parameter den STMP Server, in diesem Fall securesmtp.t-online.de.

Hier wäre nochmal die überarbeitete Funktion zum senden von Emails mit t-online als smtp-server.

Code: Alles auswählen

#! /usr/bin/python3

import smtplib
from email.message import EmailMessage

nachricht = EmailMessage()
nachricht.set_content("Text der in Email steht")

nachricht["Subject"] = "Betreff der Email"
nachricht["From"] = "Absender"
nachricht["To"] = "Empfänger"

try:
    #Versenden der Nachricht über den gesicherten T-online SMTP Server
    server = smtplib.SMTP_SSL("securesmtp.t-online.de", 465)

    #Verbindung zum Server herstellen
    server.connect("securesmtp.t-online.de")

    #Am Server mit seinen persönlichen Zugangsdaten anmelden
    server.login("xyz.xyz@t-online.de", "passwort")

    #?
    server.ehlo()

    # Versenden der Nachricht
    server.send_message(nachricht)

    print("Email wurde erfolgreich versendet")

except:
    print("Senden der Email fehlgeschlagen")
kurze Frage was macht die Funktion .ehlo() die habe ich auf die schnelle nicht gefunden.

Liebe Grüße und vielen Dank!!!
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hartmannsgruber: Die Methode `connect()` musst/solltest Du überhaupt gar nicht aufrufen — zumindest nicht wenn Du den Host schon beim erstellen des `SMTP_SSL`-Objektes angibst. Dann wird dabei nämlich bereits `connect()` aufgerufen.

Zu ehlo: https://cr.yp.to/smtp/ehlo.html
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

__blackjack__ hat geschrieben: Mittwoch 2. Oktober 2019, 15:08 @sls: Dazu muss man aber erst einmal eine Verbindung haben. Wenn das `connect()` schon nicht funktioniert, kann man danach schlecht ein `login()` machen. 😉
Wenn das aus der Windows-Fehlermeldung von ihm hervorgeht, ist das wohl so. Ich bekomme auch einen ConnectionRefusedError, allerdings sieht der Fehlercode unter Linux anders aus.

Ich habe mir aber die Mühe gemacht, was er tat, auch zu tun. Und der Zielhost sowie Port sind einwandfrei, es handelt sich also um einen Authentifizierungsfehler.


Code: Alles auswählen

>>> with smtplib.SMTP_SSL("securesmtp.t-online.de", 465) as session:
...     session.ehlo()
... 
(250, b'fwd16.t-online.de ready.\nSIZE 52428800\n8BITMIME\nAUTH=LOGIN PLAIN\nAUTH LOGIN PLAIN\nENHANCEDSTATUSCODES\nHELP')

Code: Alles auswählen

>>> with smtplib.SMTP_SSL("securesmtp.t-online.de", 465) as session:
...     session.login(<invalider_benutzer>, <invalides_passwort>)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.7/smtplib.py", line 730, in login
    raise last_exception
  File "/usr/lib/python3.7/smtplib.py", line 721, in login
    initial_response_ok=initial_response_ok)
  File "/usr/lib/python3.7/smtplib.py", line 642, in auth
    raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'5.7.0 Authentication rejected / Connection-failure. Username or password incorrect. Please be aware, that the e-mail password is mandatory here. E-Mail-Adresse oder Passwort ungueltig! Bitte beachten Sie, dass hier das E-Mail-Passwort notwendig ist: www.t-online.de/email-passwort')
When we say computer, we mean the electronic computer.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sls: Es war schon ein Verbindungsfehler. Nämlich bei einer zweiten, unnötigen, Verbindung den Host nicht anzugeben. Dann wird 'localhost' angenommen, und wenn da kein SMTP-Server läuft, dann gibt's den Verbindungsfehler den der OP sieht.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

@__blackjack__: dass er im Grunde zwei mal das gleiche macht und beim zweiten Mal noch falsch habe ich ignoriert. Du hast recht :-D
When we say computer, we mean the electronic computer.
Hartmannsgruber
User
Beiträge: 89
Registriert: Mittwoch 15. Januar 2014, 22:30
Wohnort: Bad Kötzting
Kontaktdaten:

Guten Abend,

ich hätte nun das Skript nochmals überarbeitet und hoffe die restlichen Fehler ausgebessert zu haben.
Die Ausführung des Skripts funktioniert ohne Fehler.

Code: Alles auswählen

#! /usr/bin/python3

import smtplib
from email.message import EmailMessage

nachricht = EmailMessage()
nachricht.set_content("Text der in Email steht")

nachricht["Subject"] = "Betreff der Email"
nachricht["From"] = "Absender"
nachricht["To"] = "Empfänger"

try:
    #Versenden der Nachricht über den gesicherten T-online SMTP Server
    server = smtplib.SMTP_SSL("securesmtp.t-online.de", 465)

    #Am Server mit seinen persönlichen Zugangsdaten anmelden
    server.login("xyz.xyz@t-online.de", "passwort")

    # Versenden der Nachricht
    server.send_message(nachricht)

    print("Email wurde erfolgreich versendet")

except:
    print("Senden der Email fehlgeschlagen")
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nackte excepts sind eine ganz schlechte idee, weil du Programmierfehler so unter den Tisch fallen lässt. Spar dir einfach die Ausnahmebehandlung. Wenn was schief geht ist die Fehlermeldung besser als dein Satz, und du bekommst noch nen vernünftigen Exitcode obendrauf.
Hartmannsgruber
User
Beiträge: 89
Registriert: Mittwoch 15. Januar 2014, 22:30
Wohnort: Bad Kötzting
Kontaktdaten:

Habe nun nochmals die Try - Anweisung überarbeitet.
Es macht wirklich wenig Sinn eine solch "aussagekräftige" Anweisung bei einem Fehler ausgeben zu lassen.
Da ist wirklich die Fehlermeldung besser!

Code: Alles auswählen

#! /usr/bin/python3

import smtplib
from email.message import EmailMessage
import socket

nachricht = EmailMessage()
nachricht.set_content("Text der in Email steht")

nachricht["Subject"] = "Betreff der Email"
nachricht["From"] = "Benutzername@t-online.de"
nachricht["To"] = "Empfänger der Nachricht"

try:
    #Versenden der Nachricht über den gesicherten T-online SMTP Server
    server = smtplib.SMTP_SSL("securesmtp.t-online.de", 465)

    #Am Server mit seinen persönlichen Zugangsdaten anmelden
    server.login("Benutzername@t-online.de", "Passwort")

    #Versenden der Nachricht
    server.send_message(nachricht)

    print("Email wurde erfolgreich versendet")
    

except smtplib.SMTPAuthenticationError:
    print("Fehler beim einloggen am SMTP-Server.")
    print("Benutzername, oder Passwort falsch!")

except ConnectionRefusedError:
    print("Die Verbindung zum SMTP-Server konnte hergestellt werden.")
    print("Bitte prüfen Sie den SMTP-Server und die Portnummer auf Fehler")

except socket.gaierror:
    print("Fehlerhafte Angabe des SMTP-Servers.")
    print("Nachricht konnte nicht versendet werden.")
Machen die Except-Blöcke nun Sinn, oder wie wird am Besten eine solche Fehlermeldung geschrieben?
Hatte soetwas noch nie gemacht :-(
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Meldungen sind doch jetzt viel besser zu verstehen. Falls in der Fehlermeldung noch interessante Information wäre, könnte man sie noch mit ausgeben.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hartmannsgruber: Wonach hast Du denn genau *die* Ausnahmen ausgewählt? Das ist ja nur ein kleiner Bruchteil der möglichen Ausnahmen die auftreten können und sind Spezialisierungen von allgemeineren Ausnahmen, es gibt da also ”Geschwister” die nicht behandelt werden. Zum Beispiel beim `ConnectionRefusedError` ist das ja allgemein ein `ConnectionError` und es könte auch ein `BrokenPipeError, `ConnectionAbortedError`, oder `ConnectionResetError` sein. Und beim `SMTPAuthenticationError` wären die nicht behandelten Geschwister `SMTPConnectError`, `SMTPDataError`, `SMTPHeloError`, und `SMTPSenderRefused`. Die alle ein `SMTPResponseException` sind, was wiederum von `SMTPException` abgeleitet ist.

Bei Ausnahmen die von irgendwoher standardisierte Fehlercodes und Texte von anderen Diensten bekommen, würde ich auch immer diese noch mindestens zusätzlich ausgeben. Also zum Beispiel beim `SMTPResponseException` und den abgeleiteten Klassen gibt es den SMTP-Fehlercode und die Textrückmeldung vom Server in der Ausnahme — das kann wichtig zur Fehlersuche sein.

Und alles was von `OSError` abstammt, also auch `ConnectionError` und `socket.gaierror`, hat eine Fehlernummer und eine Fehlermeldung dazu. Auch die würde ich nicht verschweigen, denn danach kann man prima im Netz suchen wenn es nicht funktioniert.

Irgendentwas mit SSL behandelst Du überhaupt nicht.

Hier mal der relevante Ausschnitt aus der Ausnahmehierarchie, mit den Ausnahmen markiert, die Du behandelst:

Code: Alles auswählen

builtins.OSError
    builtins.ConnectionError
        builtins.BrokenPipeError
        builtins.ConnectionAbortedError
        builtins.ConnectionRefusedError      ***
        builtins.ConnectionResetError
    smtplib.SMTPException
        smtplib.SMTPNotSupportedError
        smtplib.SMTPRecipientsRefused
        smtplib.SMTPResponseException
            smtplib.SMTPAuthenticationError  ***
            smtplib.SMTPConnectError
            smtplib.SMTPDataError
            smtplib.SMTPHeloError
            smtplib.SMTPSenderRefused
        smtplib.SMTPServerDisconnected
    socket.gaierror                          ***
    socket.herror
    socket.timeout
    ssl.SSLError
        ssl.SSLEOFError
        ssl.SSLSyscallError
        ssl.SSLWantReadError
        ssl.SSLWantWriteError
        ssl.SSLZeroReturnError
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten