@tretol: Dein Code enthält einen Einrückungsfehler.
Die Namen sind teilweise sehr schlecht. Ein Name soll dem Leser vermitteln was der Wert bedeutet und nicht zu rätselraten führen. Also keine kryptischen Abkürzungen oder absolut generische Namen mit angehängten Nummern. Oder einbuchstabige Namen wie `k` für etwas anderes als ganze Zahlen.
Dateien die man öffnet sollte man auch wieder schliessen. Am besten in dem man `open()` zusammen mit der ``with``-Anweisung verwendet. `fin` ist kein guter Name. `zeilen` wäre einer.
`zeilenzähler` und `zeile2` werden nirgends verwendet. Die innere ``for``-Schleife mit `zeile2` ist sowieso komplett unsinnig.
Jede Zeile dreimal mit `split()` zu zerlegen um dann jedes mal nur ein Element zu verwenden ist verschwenderisch. Zudem würde ich die Anzahl auf eine Trennstelle beschränken, denn ``=`` darf durchaus in E-Mail-Adressen für den To-Header vorkommen.
`outlook` wird erst nach der Zuordnung von Dateinamen zu Kunden benötigt. Man sollte Definition und Verwendung nicht zu weit auseinander haben, sonst wird es schwieriger Code auf Funktionen aufzuteilen wenn er zu lang wird, oder man hat nach Änderungen Definitionen im Code die später gar nicht mehr verwendet werden, weil man sie beim löschen von altem Code übersehen hat.
Dein momentanes Vorgehen kann problematisch werden wenn ein Kundename Bestandteil eines anderen Kundennamen ist. Man müsste die mindestens nach der Länge sortieren und längere vor kürzeren prüfen und beim ersten Treffer die innere Schleife abbrechen. Vorausgesetzt es darf immer nur einen Kunden pro Dateiname geben.
Pfadteile setzt man nicht mit ``+`` sondern mit `os.path.join()` zusammen. Zudem solltest Du den Pfad auch bei `listdir()` verwenden, denn sonst kann es sein das zum Zuordnen der Dateinamen ein anderes Verzeichnis verwendet wird als das aus dem die Anlagen für die E-Mails generiert werden.
Ist es gewollt, das auch Mails für Kunden erzeugt werden, für die es keine Dateien für die Anlage gibt?
Da in der letzten äusseren ``for``-Schleife sowohl die Schlüssel als auch die Werte benötigt werden, kann man auch gleich über diese Paare iterieren.
Ich komme dann ungefähr hier raus als Zwischenergebnis:
Code: Alles auswählen
#!/usr/bin/env python3
import os
import win32com.client as win32
ATTACHMENT_PATH = r'D:\Programme\Dropbox\Dropbox\Python\E-Mail'
def main():
kundenname_zu_email_adressen = dict()
kundenname_zu_dateinamen = dict()
with open('Kontakte.txt') as zeilen:
for zeile in zeilen:
kundenname, email_adressen = zeile.split('=', 1)
kundenname_zu_email_adressen[kundenname] = email_adressen
kundenname_zu_dateinamen[kundenname] = list()
for filename in os.listdir(ATTACHMENT_PATH):
for kundenname in kundenname_zu_email_adressen:
#
# TODO Problematisch wenn Kundennamen Teil von anderen
# Kundennamen sein können. Beispielsweise ”Müller” und
# ”Müller & Co”.
#
if kundenname in filename:
kundenname_zu_dateinamen[kundenname].append(filename)
outlook = win32.Dispatch('outlook.application')
for kunde, filenames in kundenname_zu_dateinamen.items():
#
# TODO Sollen für Kunden ohne Dateinamen tatsächlich auch E-Mails
# erzeugt werden?
#
mail = outlook.CreateItem(0)
mail.Subject = 'testüberschrift'
for filename in filenames:
mail.Attachments.Add(os.path.join(ATTACHMENT_PATH, filename))
mail.To = kundenname_zu_email_adressen[kunde]
mail.Display()
if __name__ == '__main__':
main()
Was daran noch unschön ist, sind diese zwei ”parallelen” Wörterbücher. Da würde ich vielleicht mit einem `collections.namedtupel` die Werte jeweils zu einem Objekt zusammenfassen.
Code: Alles auswählen
#!/usr/bin/env python3
import os
from collections import namedtuple
import win32com.client as win32
ATTACHMENT_PATH = r'D:\Programme\Dropbox\Dropbox\Python\E-Mail'
Kunde = namedtuple('Kunde', 'email_adressen dateinamen')
def main():
kundenname_zu_kunde = dict()
with open('Kontakte.txt') as zeilen:
for zeile in zeilen:
kundenname, email_adressen = zeile.split('=', 1)
kundenname_zu_kunde[kundenname] = Kunde(email_adressen, list())
for filename in os.listdir(ATTACHMENT_PATH):
for kundenname, kunde in kundenname_zu_kunde.items():
#
# TODO Problematisch wenn Kundennamen Teil von anderen
# Kundennamen sein können. Beispielsweise ”Müller” und
# ”Müller & Co”.
#
if kundenname in filename:
kunde.dateinamen.append(filename)
outlook = win32.Dispatch('outlook.application')
for kunde in kundenname_zu_kunde.values():
#
# TODO Sollen für Kunden ohne Dateinamen tatsächlich auch E-Mails
# erzeugt werden?
#
mail = outlook.CreateItem(0)
mail.Subject = 'testüberschrift'
for filename in kunde.dateinamen:
mail.Attachments.Add(os.path.join(ATTACHMENT_PATH, filename))
mail.To = kunde.email_adressen
mail.Display()
if __name__ == '__main__':
main()