Forum: PC-Programmierung E-Mail via Code versenden


von Würstel (Gast)


Lesenswert?

Hallo,
ich würde gerne programmatisch Mails versenden. Der Einfachheit halber 
habe ich mich dazu für Python entschieden:
1
import smtplib
2
from email.mime.text import MIMEText
3
4
msg = MIMEText(message)
5
msg['Subject'] = 'Hello world'
6
msg['From'] = 'foo@bar.com'
7
msg['To'] = 'foo@bar.com'
8
9
with smtplib.SMTP('smtp.strato.de:465') as server:
10
  server.ehlo()
11
  server.starttls()
12
  server.login(username, password)
13
  server.sendmail(sender, receiver, msg)
14
  server.quit()
15
  
16
  print("Mail successfully sent")

Leider kappt das nicht so ganz. Entweder bleibt der Code komplett hängen 
(wenn ich SLL verwende, nach 10 Minuten habe ich abgebrochen), oder es 
fliegt eine nichtssagende Exception (wenn ich TLS verwende, 
"smtplib.SMTPServerDisconnected: Connection unexpectedly closed")...

Kann mir jemand einen Tipp geben, wie ich via Python bei Strato eine 
Mail rausschicken kann?

von Heiner (Gast)


Lesenswert?

Zu den genauen Verhältnissen beim Versand über Strato kann ich nichts 
sagen, aber:

Würstel schrieb:
> with smtplib.SMTP('smtp.strato.de:465') as server:

Würstel schrieb:
> server.starttls()

Ich hätte die akute Vermutung, dass es dort nicht zulässig ist, die 
Verbindung ungesichert aufzubauen und zu TLS aufzusteigen. Ich würde 
also statt der SMTP-Klasse lieber SMTP_SSL verwenden.

Würstel schrieb:
> server.ehlo()

Das ist in 99 von 100 Fällen unnötig. Wenn es erforderlich ist, ein EHLO 
zu senden, passiert das von alleine. Ist aber wahrscheinlich nicht das 
Problem.

Würstel schrieb:
> oder es
> fliegt eine nichtssagende Exception

Bei welcher Anweisung? Und ansonsten verfügt SMTP bzw. SMTP_SSL über die 
immens nützliche Methode set_debuglevel.

von mark space (Gast)


Lesenswert?

unter linux gibt es dafür das Programm "sendmail". Damit habe ich vor 
langer Zeit die Konten der berüchtigten Gebrüder Schmidlein zu gespammt.

von Hmmm (Gast)


Lesenswert?

Würstel schrieb:
> with smtplib.SMTP('smtp.strato.de:465') as server:
>   server.ehlo()
>   server.starttls()

Nimm mal Port 587, der ist für Plaintext-SMTP mit anschliessendem 
STARTTLS da.

von Heiner (Gast)


Lesenswert?

Hmmm schrieb:
> Nimm mal Port 587, der ist für Plaintext-SMTP mit anschliessendem
> STARTTLS da.

Wenn ich den roten Hinweis hier ...

https://www.strato.de/faq/mail/wie-kann-ich-meine-e-mails-ueber-eine-gesicherte-verbindung-ssl-oder-tls-versenden-und-empfangen/

... richtig deute, ist das höchstens noch für alte Postfächer von 2013 
und früher möglich. Es würde mich nicht wundern - das ist heute einfach 
nicht mehr Stand der Technik.

von Hmmm (Gast)


Lesenswert?

Heiner schrieb:
> Wenn ich den roten Hinweis hier ...
>
> 
https://www.strato.de/faq/mail/wie-kann-ich-meine-e-mails-ueber-eine-gesicherte-verbindung-ssl-oder-tls-versenden-und-empfangen/
>
> ... richtig deute, ist das höchstens noch für alte Postfächer von 2013
> und früher möglich.

Nein, der Hinweis bezieht sich auf komplett unverschlüsselte 
Verbindungen.

Heiner schrieb:
> Es würde mich nicht wundern - das ist heute einfach
> nicht mehr Stand der Technik.

Du verstehst da etwas falsch. Auf Port 587 wird man zwar mit normalem 
Plaintext-SMTP begrüsst, schaltet dann aber per STARTTLS-Kommando auf 
TLS um. Das ist also nicht weniger sicher, solange erst nach dem 
STARTTLS eine Authentifizierung angeboten wird.

Der Unterschied auf Port 465 ist, dass dort sofort TLS gesprochen wird. 
Allerdings ist diese Variante eher unüblich und wird in RFC4609 nicht 
mal erwähnt.

von Manfred (Gast)


Lesenswert?

Hmmm schrieb:
> schaltet dann aber per STARTTLS-Kommando auf TLS um.

Ich würde mal einen Blick nehmen wollen, welche TLS-Version die 
Sendersoftware verwendet. Ich hatte hier einigen Ärger mit älteren 
Tools, weil viele Provider seit ein paar Monaten TLS 1.0 stumpf 
abweisen. Die Fehlermeldungen sind im Allgemeinen nichtssagend, 
Rätselraten.

von Heiner (Gast)


Lesenswert?

Hmmm schrieb:
> Du verstehst da etwas falsch. Auf Port 587 wird man zwar mit normalem
> Plaintext-SMTP begrüsst, schaltet dann aber per STARTTLS-Kommando auf
> TLS um. Das ist also nicht weniger sicher, solange erst nach dem
> STARTTLS eine Authentifizierung angeboten wird.

Das ist mir alles bekannt. Es ist trotzdem nicht mehr Stand der Technik, 
RFC 8314.

Du hast trotzdem Recht: Der blaue Hinweis über dem roten deutet darauf 
hin, dass es bei Strato wohl weiterhin STARTTLS gibt, und wenn man das 
verwenden möchte, soll man Port 587 nutzen. Warum man das aber bei neuen 
Lösungen tun sollte, erschließt sich mir überhaupt nicht, deshalb bleibe 
ich bei meiner Empfehlung: SMTP_TLS mit der gleichen Konfiguration, ohne 
das starttls() und ehlo(). Und mit debuglevel(1). Und dann mal sehen, 
was passiert.

von Hmmm (Gast)


Lesenswert?

Manfred schrieb:
> Die Fehlermeldungen sind im Allgemeinen nichtssagend,
> Rätselraten.

Die OpenSSL-Fehlermeldungen sagen schon halbwegs etwas aus, was bloss 
leider nicht hilft, wenn die Software nur "geht nicht" weitergibt.

Heiner schrieb:
> Das ist mir alles bekannt. Es ist trotzdem nicht mehr Stand der Technik,
> RFC 8314.

Das ist allerdings erst ein "proposed standard". Wobei wir uns beim 
wesentlichen Punkt einig sind: Mailversand ohne Verschlüsselung ist 
lange überholt, implicit vs. explicit TLS hingegen ist nur ein Detail.

Heiner schrieb:
> Warum man das aber bei neuen
> Lösungen tun sollte, erschließt sich mir überhaupt nicht

Wenn es mit beliebigen Mailservern funktionieren soll, sollte man am 
besten beide Varianten implementieren.

von Jemand (Gast)


Lesenswert?

Würstel schrieb:
>
1
> with smtplib.SMTP('smtp.strato.de:465') as server:
2
3
server.set_debuglevel(2)
4
5
>   server.ehlo()
6
>

Nur so eine Idee, HTH.

von No N. (web_dev)


Lesenswert?

Nutze smtplib.SMTP_SSL und setze notfalls den debug level hoch. Die 
Ausgabe kannst du hier ja noch einmal posten.

von bluppdidupp (Gast)


Lesenswert?

Hmmm schrieb:
> Nimm mal Port 587, der ist für Plaintext-SMTP mit anschliessendem
> STARTTLS da.

Ich denke auch das einfach der falsche Port verwendet wird und da 587 
stehen müsste. Für Port 465 müsste eher smtplib.SMTP_SSL() statt 
smtplib.SMTP() verwendet werden.

von Würstel (Gast)


Lesenswert?

Hallo und danke an alle.
Mittlerweile habe ich's hinbekommen :-)

Für die Nachwelt hier der funktionierende Code:
1
# Globals
2
address = '...'
3
username = '...'
4
password = '...'
5
host = 'smtp.strato.de:465'
6
7
message = """\
8
Subject: My Subject
9
My message"""
10
11
12
# Sends an E-Mail
13
def sendMail(sender, receiver):
14
    print("Sending E-Mail")
15
    try:
16
        with smtplib.SMTP_SSL(host) as server:
17
            server.login(username, password)
18
            server.sendmail(sender, receiver, message)
19
            server.quit()
20
            print("Mail successfully sent")
21
    except:
22
        print("Sending the E-Mail failed")

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.