Forum: PC-Programmierung smtplib? Mit Python Mail versenden


von nix_Pythonisch (Gast)


Lesenswert?

Hallo,
ich möchte mir ein ganz ganz einfaches Skript bauen um aus der shell 
raus Emails zu versenden.
Dachte mir das könnte mit Python gut gehen.
1
#!/usr/bin/python
2
import sys
3
TO_ = sys.argv[1]
4
CC_ = sys.argv[2]
5
BETREF = sys.argv[3]
6
MESSAGE = sys.argv[4]
7
8
print TO_
9
print CC_
10
print BETREF
11
print MESSAGE
12
13
14
15
import smtplib
16
from email.MIMEMultipart import MIMEMultipart
17
from email.MIMEText import MIMEText
18
19
senderEmail = "blablub@gmail.com"
20
empfangsEmail = "xxxx@gmail.com"
21
msg = MIMEMultipart()
22
msg['From'] = senderEmail
23
msg['To'] = TO_
24
msg['To'] = CC_
25
msg['Subject'] = BETREF
26
27
emailText = MESSAGE
28
msg.attach(MIMEText(emailText, 'html'))
29
30
server = smtplib.SMTP('smtp.gmail.com', 587) # Die Server Daten
31
server.starttls()
32
server.login(senderEmail, "xJpPMUfWwOY") # Das Passwort
33
text = msg.as_string()
34
server.sendmail(senderEmail, empfangsEmail, text)
35
server.quit()

Das Prinzip funktioniert aber leider kommen die beim Cc die Mails nicht 
an.
Es wird immder Bcc versand obwohl ich nicht angebe.
Könnt Ihr mir sagen wo ich gute Doku zu diesem smtplib gibt.
Oder einen Tipp geben was ich falsch mache
Danke

Ach ja noch bevor ich es vergesse ich habe es auf einem Rasberry mit 
Bullseys  probiert.

von Hmmm (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Das Prinzip funktioniert aber leider kommen die beim Cc die Mails nicht
> an.

Bei der Mailzustellung sind nicht die Header ausschlaggebend, sondern 
die Envelope-Adressen, die der Server per SMTP mitgeteilt bekommt.

Du musst also herausfinden, wie Du die Library dazu bringst, mehrere 
RCPT TO zu senden.

von A. S. (rava)


Lesenswert?

hab ich noch nicht gemacht, aber vielleicht hilft das weiter?

https://stackoverflow.com/questions/1546367/python-how-to-send-mail-with-to-cc-and-bcc


empfangsEmail muss eine Liste mit allen empfängern sein

: Bearbeitet durch User
von nix_Pythonisch (Gast)


Lesenswert?

Sorry ich habe es auch mit Cc ausprobiert.
Aber irgendwie kommt nur die To und Bcc die ich gar nicht definiert habe 
an.
1
senderEmail = "blablub@gmail.com"
2
empfangsEmail = "xxxx@gmail.com"
3
msg = MIMEMultipart()
4
msg['From'] = senderEmail
5
msg['To'] = TO_
6
msg['Cc'] = CC_
7
msg['Subject'] = BETREF

von Hmmm (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Sorry ich habe es auch mit Cc ausprobiert.

Wozu?

nix_Pythonisch schrieb:
> server.sendmail(senderEmail, empfangsEmail, text)

Da geht die Mail hin, egal was im Header steht.

von nix_Pythonisch (Gast)


Lesenswert?

Hmmm schrieb:
> nix_Pythonisch schrieb:
>> Sorry ich habe es auch mit Cc ausprobiert.
>
> Wozu?
>
> nix_Pythonisch schrieb:
>> server.sendmail(senderEmail, empfangsEmail, text)
>
> Da geht die Mail hin, egal was im Header steht.

Hallo Danke für deine Hilfe.
Wie kann ich der Funktion


server.sendmail(senderEmail, empfangsEmail, text)
anstelle von "empfangsEmail" die eingegebenen Daten von "msg" übergeben?

Danke für die Hilfe.

von Hmmm (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Wie kann ich der Funktion
>
> server.sendmail(senderEmail, empfangsEmail, text)
> anstelle von "empfangsEmail" die eingegebenen Daten von "msg" übergeben?

Weiter oben wurde doch ein Beispiel verlinkt. Einfach statt des 
einzelnen Strings eine "List", wie das offenbar in Python heisst, 
übergeben.

Steht auch in der Dokumentation:

> The required arguments are an RFC 822 from-address string, a list of RFC
> 822 to-address strings (a bare string will be treated as a list with
> 1 address), and a message string.

Beitrag #6909355 wurde von einem Moderator gelöscht.
von Hmmm (Gast)


Lesenswert?

Cartman schrieb im Beitrag #6909355:
> (SMTP-)Mails zu versenden ist ja schon mit netcat nur ein Einzeiler.

Wie hältst Du da das Timing ein und fängst Fehler ab?

von nix_Pythonisch (Gast)


Lesenswert?

Cartman schrieb im Beitrag #6909355:
> Wozu Python?
>
> (SMTP-)Mails zu versenden ist ja schon mit netcat nur ein Einzeiler.
> Oder verstehst du das Prinzip dahinter nicht?

Dachte mir das ist das einfachste.

Hmmm schrieb:
> Cartman schrieb:
>> (SMTP-)Mails zu versenden ist ja schon mit netcat nur ein Einzeiler.
>
> Wie hältst Du da das Timing ein und fängst Fehler ab?

Also das Ergebnis meines Skript das ich weiter oben veröffentlicht habe 
ist im Bild ersichtlich.
Also wenn ich mir in meinen Gmail Konto das gesendete Mail ansehe kommt 
das sieht man das das Mail fehlerfrei raus ist.
Jedoch kommt das Mail effektiv nur bei einem Empfänger an.
Was mache ich falsch?

Danke für Eure Hilfe

von Hmmm (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Also das Ergebnis meines Skript das ich weiter oben veröffentlicht habe
> ist im Bild ersichtlich.

Und dass es so nicht funktionieren kann, wurde schon erklärt.

nix_Pythonisch schrieb:
> Jedoch kommt das Mail effektiv nur bei einem Empfänger an.
> Was mache ich falsch?

Siehe oben:

Hmmm schrieb:
> Weiter oben wurde doch ein Beispiel verlinkt. Einfach statt des
> einzelnen Strings eine "List", wie das offenbar in Python heisst,
> übergeben.

von nix_Pythonisch (Gast)


Angehängte Dateien:

Lesenswert?

Sorry das Bild vergessen

von usuru (Gast)


Lesenswert?

ich verwende für Emails aus der Shell immer ssmtp, alt aber gut

1. Möglichkeit
1
echo -e 'subject:subject-text\ncc:cc-empf\nbcc:bcc-empf\n\nmessage-text' | ssmtp empfaenger@domain.tld

2.Möglichkeit
1
ssmtp empfaenger@domain.tld < dateiname
2
3
Beispiel für die Datei 'dateiname':
4
subject: sehr sehr wichtig
5
cc: meistermeier@nix.org
6
bcc: schmidchenschleicher@alles.org
7
1. zeile der email
8
2. zeile der email
9
                                     <--- Leerzeile !!!

von nix_Pythonisch (Gast)


Lesenswert?

usuru schrieb:
> ich verwende für Emails aus der Shell immer ssmtp, alt aber gut
>
> 1. Möglichkeitecho -e
> 'subject:subject-text\ncc:cc-empf\nbcc:bcc-empf\n\nmessage-text' | ssmtp
> empfaenger@domain.tld
>
> 2.Möglichkeitssmtp empfaenger@domain.tld < dateiname
> Beispiel für die Datei 'dateiname':
> subject: sehr sehr wichtig
> cc: meistermeier@nix.org
> bcc: schmidchenschleicher@alles.org
> 1. zeile der email
> 2. zeile der email
>                                      <--- Leerzeile !!!

Habe leider SSMTP nicht konfiguriert bekommen.
Kannst du mir sagen wie das funktioniert?

von usuru (Gast)


Lesenswert?

Meine /etc/ssmtp/ssmtp.conf
1
root=absender@domain.de
2
mailhub=mail.mailserver.de:465
3
UseTLS=Yes
4
AuthUser=absender@domain.de
5
AuthPass=Streng%-geheim34
6
rewriteDomain=so-heisst-mein-rechner
7
hostname=so-heisst-mein-rechner

und meine /etc/ssmtp/revaliases
1
root:absender@domain.de:mail.mailserver:465
2
mein-username-im-rechner:absender@domain.de:mail.mailserver.de:465

von nix_Pythonisch (Gast)


Lesenswert?

usuru schrieb:
> Meine /etc/ssmtp/ssmtp.confroot=absender@domain.de
> mailhub=mail.mailserver.de:465
> UseTLS=Yes
> AuthUser=absender@domain.de
> AuthPass=Streng%-geheim34
> rewriteDomain=so-heisst-mein-rechner
> hostname=so-heisst-mein-rechner
>
> und meine
> /etc/ssmtp/revaliasesroot:absender@domain.de:mail.mailserver:465
> mein-username-im-rechner:absender@domain.de:mail.mailserver.de:465

Danke für die Hilfe,
werde es heute Abend probieren.

von Nur_ein_Typ (Gast)


Angehängte Dateien:

Lesenswert?

nix_Pythonisch schrieb:
> ich möchte mir ein ganz ganz einfaches Skript bauen um aus der shell
> raus Emails zu versenden.
> Dachte mir das könnte mit Python gut gehen.

Das tut es auch, aber...

>
1
> #!/usr/bin/python
2
> import sys
3
> TO_ = sys.argv[1]
4
> CC_ = sys.argv[2]
5
> BETREF = sys.argv[3]
6
> MESSAGE = sys.argv[4]
7
> 
8
> print TO_
9
> print CC_
10
> print BETREF
11
> print MESSAGE

Dieser Teil deutet darauf hin, daß Du a) nicht besonders viel Erfahrung 
mit Python hast und b) eine recht veraltete Version benutzt. In Python 
Version 2 war print ein Statement und konnte ohne Klammern aufgerufen 
werden wie bei Dir, in Python Version 3 ist print() hingegen eine 
Funktion und muß mit Klammern aufgerufen werden -- also "print(TO_)" 
anstalle von "print to". Python Version 2 ist allerdings End of life und 
sollte daher heute nicht mehr für Neuimplementierungen verwendet werden.

Und dann ist da so eine Sache mit Deiner Shebang-Zeile. Grundsätzlich 
ist das kein Problem, direkt den Interpreter aufzurufen, aber leider 
funktioniert das nicht, wenn man eine virtuelle Umgebung mit 
virtualenv(1) oder dem Python-Modul venv benutzt. Besser wäre daher 
"#!/usr/bin/env python" oder in Deiner Umgebung, in der "python" noch 
auf die veraltete Version 2 zeigt, "#!/usr/bin/env python3".

Weiterhin ist es keine besonders gute Idee, direkt über das sys-Modul 
auf die übergebenen Kommandozeilenargumente zuzugreifen. Dafür gibt es 
in Python die Klasse ArgumentParser im Modul argparse; damit werden die 
Argumente nicht nur gelesen und gegebenenfalls in den erwarteten 
Datentyp konvertiert (oder eine Exception geworfen sofern das nicht 
möglich ist), zudem werden ein hübscher Hilfstext und leserliche 
Fehlermeldungen erzeugt. Mit dem ArgumentParser und dem Parameter 
"nargs" für die Methode add_argument() kannst Du für ein 
Kommandozeilenargument dann auch mehrere Werte übergeben, die Dir dann 
in einer Liste zurückgegeben werden.

Im Anhang findest Du ein vereinfachtes Beispiel für einen solchen 
Parser. In einem echten Skript zu produktiven Zwecken würde ich dort 
allerdings noch mehrere Dinge einbauen, etwa die Möglichkeit, 
Konfigurationsdateien zu benutzen, um zum Beispiel so Dinge wie 
SMTP-Server, From, To, und so weiter darin festzulegen. Das ginge mit 
der ConfigParser-Klasse aus dem Standardmodul configparser recht 
einfach, um dazu nur eine Möglichkeit zu nennen. Außerdem würde ich die 
Mailadressen über eines der extern verfügbaren Module validieren. Du 
siehst: ich persönlich würde mir größere Mühe machen, das Parsing der 
Kommandozeilenargumente so wasserdicht wie nur irgend möglich zu machen 
-- das macht den Rest dann wesentlich einfacher.

>
1
> server.sendmail(senderEmail, empfangsEmail, text)
>
> Das Prinzip funktioniert aber leider kommen die beim Cc die Mails nicht
> an.

... weil Du als empfangsEmail nur eine Adresse angibst, und da kommt die 
Mail dann eben auch nur an. Wenn Du eine Liste von allen To:-, CC:- und 
BCC:-Adressen angäbst, dann würden Deine Mails auch bei den anderen 
vorgesehenen Empfängern ankommen.

> Könnt Ihr mir sagen wo ich gute Doku zu diesem smtplib gibt.

Gute Dokumentation gibt es online, wie bei allen 
Python-Standard-Modulen, auf der offiziellen Python-Dokumentationsseite 
[1]. Außerdem kannst Du die Dokumentation installierter Module mit 
"pydoc <modul>" auf der Kommandozeile anzeigen lassen, bei Dir also mit 
"pydoc smtplib" und wenn Du nur die Dokumentation zur SMTP-Klasse aus 
dem Modul smtplib anzeigen lassen willst, "pydoc smtplib.SMTP".

[1] https://docs.python.org/3/library/smtplib.html

von nix_Pythonisch (Gast)


Lesenswert?

Nur_ein_Typ schrieb:
> Dieser Teil deutet darauf hin, daß Du a) nicht besonders viel Erfahrung
> mit Python hast und b) eine recht veraltete Version benutzt.

Du hast absolut recht mit beiden Aussagen.

Nur_ein_Typ schrieb:
> Im Anhang findest Du ein vereinfachtes Beispiel für einen solchen
> Parser. In einem echten Skript zu produktiven Zwecken würde ich dort
> allerdings noch mehrere Dinge einbauen, etwa die Möglichkeit,
> Konfigurationsdateien zu benutzen, um zum Beispiel so Dinge wie
> SMTP-Server, From, To, und so weiter darin festzulegen. Das ginge mit
> der ConfigParser-Klasse aus dem Standardmodul configparser recht
> einfach, um dazu nur eine Möglichkeit zu nennen. Außerdem würde ich die
> Mailadressen über eines der extern verfügbaren Module validieren. Du
> siehst: ich persönlich würde mir größere Mühe machen, das Parsing der
> Kommandozeilenargumente so wasserdicht wie nur irgend möglich zu machen
> -- das macht den Rest dann wesentlich einfacher.

Danke Für das Beispiel und den Tipp.

Nur_ein_Typ schrieb:
> ... weil Du als empfangsEmail nur eine Adresse angibst, und da kommt die
> Mail dann eben auch nur an. Wenn Du eine Liste von allen To:-, CC:- und
> BCC:-Adressen angäbst, dann würden Deine Mails auch bei den anderen
> vorgesehenen Empfängern ankommen.

Ok das ist also mein Fehler. Kann man mit Python die Liste aus dem 
Objekt msg direkt auslesen?

Nur_ein_Typ schrieb:
> Gute Dokumentation gibt es online, wie bei allen
> Python-Standard-Modulen, auf der offiziellen Python-Dokumentationsseite
> [1]. Außerdem kannst Du die Dokumentation installierter Module mit
> "pydoc <modul>" auf der Kommandozeile anzeigen lassen, bei Dir also mit
> "pydoc smtplib" und wenn Du nur die Dokumentation zur SMTP-Klasse aus
> dem Modul smtplib anzeigen lassen willst, "pydoc smtplib.SMTP".
>
> [1] https://docs.python.org/3/library/smtplib.html

Vielen Dank für deine Detaillierte Hilfe. Sehr sehr nett von Dir.
Danke

von nix_python (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> ich möchte mir ein ganz ganz einfaches Skript bauen um aus der shell
> raus Emails zu versenden.

Das geht ohne Python w.o. beschrieben, warum willst Du Python als Umweg 
???

von nix_python (Gast)


Lesenswert?

Wenn Dir ssmtp zu alt ist, nimm msmtp, das ist die moderne Version für 
die Shell

von Karl (Gast)


Lesenswert?

nix_python schrieb:
> Das geht ohne Python w.o. beschrieben, warum willst Du Python als Umweg
> ???

Weil es Python besser kann und weniger kryptisch ist?

von Karl (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Kann man mit Python die Liste aus dem Objekt msg direkt auslesen?

Wenn man bei Google MIMEMultipart eingibt, ist der 1. Treffer die 
offizielle Doku mit Beispielen.

von nix_Pythonisch (Gast)


Lesenswert?

nix_python schrieb:
> Wenn Dir ssmtp zu alt ist, nimm msmtp, das ist die moderne Version
> für
> die Shell

Ich bekomme ssmtp nicht zum laufen.
Habe die Einstellungen

nix_Pythonisch schrieb:
> usuru schrieb:
>> Meine /etc/ssmtp/ssmtp.confroot=absender@domain.de
>> mailhub=mail.mailserver.de:465
>> UseTLS=Yes
>> AuthUser=absender@domain.de
>> AuthPass=Streng%-geheim34
>> rewriteDomain=so-heisst-mein-rechner
>> hostname=so-heisst-mein-rechner
>>
>> und meine
>> /etc/ssmtp/revaliasesroot:absender@domain.de:mail.mailserver:465
>> mein-username-im-rechner:absender@domain.de:mail.mailserver.de:465
>
> Danke für die Hilfe,
> werde es heute Abend probieren.

so angepasst.
Kann man irgendwie debugen?

Danke für die Hilfe

von Nur_ein_Typ (Gast)


Lesenswert?

nix_Pythonisch schrieb:
> Nur_ein_Typ schrieb:
>> ... weil Du als empfangsEmail nur eine Adresse angibst, und da kommt die
>> Mail dann eben auch nur an. Wenn Du eine Liste von allen To:-, CC:- und
>> BCC:-Adressen angäbst, dann würden Deine Mails auch bei den anderen
>> vorgesehenen Empfängern ankommen.
>
> Ok das ist also mein Fehler. Kann man mit Python die Liste aus dem
> Objekt msg direkt auslesen?

Na klar, ähnlich wie Du hineinschreibst, kannst Du auch lesend zugreifen 
-- die Klasse unterstützt das Dictionary-Interface (Python-Datentyp 
dict) sowohl schreibend mit der "magischen" Methode __setitem__() als 
auch lesend mit der "magischen" Methode __getitem__(), aaber...

>
1
> msg['To'] = TO_
2
> msg['To'] = CC_

...aaaber zum Beispiel an dieser Stelle schreibst Du in den Header der 
Nachricht und überschreibst das Feld 'To' dann gleich wieder. Das ist 
natürlich nicht die Idee... und wenn Du Listen (Python-Datentyp list) 
übergeben willst, dann mußt Du natürlich so eine Liste bauen. Insofern 
möchte ich empfehlen und anregen, daß Du einmal das offizielle 
Python-Tutorial durcharbeitest: [1]. Wenn das Englische Dir nicht so 
liegen sollte, gibt es eine deutsche Übersetzung unter [2], allerdings 
für eine ältere Version -- wobei sich bei den Basics, die Du brauchst, 
seitdem gar nicht so sehr viel geändert hat.

Ansonsten gilt es bei E-Mails sauber zu differenzieren zwischen den 
Envelope- und dem Mail-Headern. Die Envelope-Header sind die, die dem 
SMTP-Server im Dialog vom Programm übergeben werden, in Deinem Fall also 
mit der Methode sendmail() Deiner Instanz der Klasse SMTP. Dann gibt es 
die Mailheader, die Du in Deiner Instanz der Klasse MIMEMultipart (die 
in Python3 in email.mime.multipart verschoben worden ist) setzt, und die 
vom SMTP-Server üblicherweise ohnehin ignoriert werden (das ist zwar 
nicht immer ganz richtig, soll uns aber hier nicht stören).

[1] https://docs.python.org/3/tutorial/
[2] https://py-tutorial-de.readthedocs.io/de/python-3.3/

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.