Anhänge aus Email entfernen. Aber wie?

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
darksidecowboy
User
Beiträge: 5
Registriert: Dienstag 29. Januar 2013, 23:32

Hallo erstmal!
Ich bin noch ganz neu hier sowohl im Forum als auch was die Programmierung mit Python angeht.
Leider hänge ich zur Zeit an einem Problem zu mir keine rechte Lösung einfallen will.
Mein Programm läuft in einer Endlosschleife. Es soll nun in bestimmten Fällen eine Email mit Anhang verschicken. Dummerweise verschickt es bei jedem weiteren mal bei dem eine Mail verschickt wird auch alle zuvor bereits verschickten Anhänge wieder mit. D.h. die dritte Mail enthält auch die Anhänge der vorigen beiden, Das will ich natürlich nicht.
Leider bin ich überfrag wie ich das Problem löse. Google hat mir da auch nicht so wirklich weiter geholfen ich habe zwar einen Hinweis darauf gefunden es mit set_payload zu versuchen. Alle bisherigen Versuche scheiterten aber.

Der Part in dem die Mail erstellt wird sieht bei mir so aus:

Code: Alles auswählen

msg = MIMEMultipart()
msg['Subject'] = 'Betreffzeile'
msg['From'] = 'Absender <absender@abc.de>'
msg['Reply-to'] = 'absender@abc.de'
msg['To'] = 'epfaenger@abc.det'
msg.preamble = 'Multipart massage.\n'
part = MIMEText("Text in der Email")
msg.attach(part)
part = MIMEApplication(open("Datei.bsp","rb").read())
part.add_header('Content-Disposition', 'attachment', filename="datei.bsp")
msg.attach(part)
Vielleicht kann sich jemand erbarmen und mir einen Hinweis geben :)

LG und vielen Dank...
BlackJack

@darksidecowboy: Also ich sehe in dem Code kein Problem. Ein minimales aber lauffähiges Beispiel, welches das Problem aufweist, wäre nicht schlecht. Dann könnte man das Problem nachvollziehen.
darksidecowboy
User
Beiträge: 5
Registriert: Dienstag 29. Januar 2013, 23:32

Ja, den obigen Code hätte ich mir auch sparen können.
Ich werde morgen mal eine Minimalversion tippen und hier posten.
Das Problem ist glaube ich, dass dem Objekt "msg" bei jedem mal wo diese Zeilen durchlaufen werden:

Code: Alles auswählen

part = MIMEApplication(open("Datei.bsp","rb").read())
part.add_header('Content-Disposition', 'attachment', filename="datei.bsp")
msg.attach(part)
die datei "datei.bsp" ein weiteres mal angehängt wird. Sprich wenn ich den Code z.B. 3 mal ablaufen lasse habe ich 3 Anhänge. Ändert sich zwischenzeitlich der Inhalt von "datei.bsp" so habe ich in der Mail am Ende alle 3 Versionen der Datei im Anhang...
BlackJack

@darksidecowboy: Das dürfte aber nur passieren wenn Du das `Message`-Objekt nicht neu erstellst, sondern immer das selbe verwendest.

Das mit der Datei ist so übrigens keine gute Idee. Man sollte Dateien die man öffnet auch wieder schliessen, und nicht hoffen, dass das die automatische Speicherverwaltung zeitnah für einen erledigt. Dafür gibt es von der Sprachdefinition nämlich *ausdrücklich* keine Garantie. Bei CPython passiert das in der Regel zwar relativ zeitnah, aber auch dort gibt es Fälle, bei denen man reale Probleme mit dieser kleinen „Schlamperei” bekommt. Also sollte man sich das gar nicht erst angewöhnen. In diesem Fall bietet sich die ``with``-Anweisung an um das in nur einer zusätzlichen Zeile zu lösen.
darksidecowboy
User
Beiträge: 5
Registriert: Dienstag 29. Januar 2013, 23:32

Hallo, danke für den Hinweis die Datei wieder zu schließen :)

Hier mal ein minimaler lauffähiger Code:

Code: Alles auswählen

import smtplib
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from smtplib import SMTP

msg = MIMEMultipart()
msg['Subject'] = 'Betreff'
msg['From'] = 'Absender <absender@abc.de>'
msg['Reply-to'] = 'absender@abc.de'
msg['To'] = 'empfaenger@abc.de'
msg.preamble = 'Multipart massage.\n'
part = MIMEText("Text in der Email")
msg.attach(part)

n=2

while n>=1:

	anhang = open("datei.bsp","rb")
	part = MIMEApplication(anhang.read())
	anhang.close()
	part.add_header('Content-Disposition', 'attachment', filename="datei.bsp")
	msg.attach(part)

	smtp = SMTP("smtp.server.de")
	smtp.ehlo()
	smtp.login("loginname", "passwort")
	smtp.sendmail(msg['From'], msg['To'], msg.as_string())

	n=n-1
Führe ich den Code aus, dann bekomme ich 2 Emails mit Anhang.
Die erste Mail enthält korrekterweise den Anhang "datei.bsp"
Die zweite Mail enthält diesen Anhang aber zwei Mal, was ich natürlich nicht will :(

Der Punkt ist, dass sich zwischenzeitlich der Inhalt der Datei "datei.bsp" ändert und ich bei jedem Durchlauf der While-Schleife gerne nur die aktuelle Datei "datei.bsp" verschicken möchte.
So wie es jetzt ist bekomme ich auch alle alten Versionen der Datei im Anhang mitgeschickt.
BlackJack

@darksidecowboy: Ähm, ja na klar ist das so. Du sagst in dem Quelltext ja auch ziemlich deutlich das genau das passieren soll. Du erzeugst da ein Nachrichten-Objekt und hängst da in jedem Schleifendurchlauf immer einen weiteren Anhang dran und verschickst das. Wenn Du das nicht willst, musst jedes mal ein neues Nachrichten-Objekt erstellen, statt immer das selbe zu verwenden und zu erweitern.
darksidecowboy
User
Beiträge: 5
Registriert: Dienstag 29. Januar 2013, 23:32

@BlackJack: Ja das hatte ich befürchtet ich habe inzwischen zwar eine simple Lösung gefunden.
Ich "lösche" das Objekt oder vielmehr den Inhalt mit

Code: Alles auswählen

msg.set_payload([])
und fülle es dann wieder neu.
Allerdings erscheint mir die Lösung wenig elegant.
Wie kann ich denn ein neues Objekt erstellen ohne das ich am Ende zig Objekte ungenutzt rumfliegen hab?
Ich muss ja dann auch für jedes neue Objekt einen neuen Namen vergeben oder?
Dabei brauche ich im Grunde ja nur ein Objekt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo darksidecowboy,

in Python werden ständig Objekte erzeugt und wieder verworfen.
Bei Dir in jedem Schleifendurchgang anhang, smtp, part und noch tausende andere
die Du nicht siehst. Wo ist das Problem?
darksidecowboy
User
Beiträge: 5
Registriert: Dienstag 29. Januar 2013, 23:32

Ok wenn Python damit kein Problem hat, habe ich auch keins.
Aber muss ich dem Objekt dann bei jedem Durchlauf einen neuen Namen geben?
lunar

@darksidecowboy Nein, warum solltest Du?

"msg" ist übrigens nicht der Name des Objekts, sondern lediglich der Name, der diesem Objekt im aktuellen Namensraum gegeben ist. Ein Objekt kann verschiedenen Namen in verschiedenen Namensräumen zugewiesen sein, und derselbe Name kann in verschiedenen Namensräumen auf unterschiedliche Objekte verweisen. Name und Objekt sind per se völlig unabhängig voneinander.
Antworten