imaplib/email: Mail => lesbar machen

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
tantris
User
Beiträge: 10
Registriert: Donnerstag 31. August 2006, 10:05

Hi,

ich programmiere seit ca. einem Monat in Python (die letzten 8 Jahre waren eher von C/C++ und etwas Java geprägt).
Aktuell stehe ich vor folgendem Problem:
Wir haben in der Firma ein Intranet mit Webapplikationen, unter anderem eine Todo-Liste für jeden Mitarbeiter.
Angedacht ist nun folgendes: Angenommen ein Kunde schickt mir eine Mail a'la "Ich möchte dieses und jenes", dann soll diese Mail weitergeleitet werden auf einen todo@-Account (Imap). Von diesem soll dann ein Python-Skript jede Minute oder so die nachrichten abholen und aus den Daten ein entsprechendes Todo in die DB stopfen.

Jetzt kann das natürlich relativ eklig werden wegen diverser mime-Typen, encodings, HTML, kaputtem HTML, Outlook ;-) weil ich ja keine Ahnung hab, von welchem Client mir ein Kunde schreibt... Am Ende sollte auf jeden Fall einfaches HTML oder XML (aber HTML sollte einfacher sein) in die DB geschrieben werden.

Wie würdet ihr da vorgehen? Gibt es evtl. schon nette Methoden, um eine imap-Nachricht so in eine email.Message zu verwandeln, dass ich sozusagen "direkt" an den Nachrichtentext komme?
BlackJack

Im IMAP Beispiel in der Python Dokumentation wird der `fetch()` Methode '(RFC822)' als Selektions-Argument angegeben. Ich vermute mal, dass die Ergebnisse dann als MIME-Messages formatiert zurückkommen, sich also mit dem `email` Modul parsen und auseinandernehmen lassen.
tantris
User
Beiträge: 10
Registriert: Donnerstag 31. August 2006, 10:05

Hmm das Beispiel hatte ich auch gesehen - ein fetch liefert mir das hier:

Code: Alles auswählen

In [63]: data=M.fetch('1','(RFC822)')
In [64]: data
Out[64]:
('OK',
 [('1 (RFC822 {990}',
   'Return-Path: <martin@foo.de>\r\nX-Sieve: cmu-sieve 2.0\r\nReceived: from [10.10.10.54] (etsch.intern.foo.de [10.10.10.54])\r\n\tby amazonas.intern.foo.de (8.11.6/8.11.6) with ESMTP id k6QDQJT20660\r\n\tfor <todo@foo.de>; Wed, 26 Jul 2006 15:26:19 +0200\r\nMessage-ID: <44C76D7C.4060205@foo.de>\r\nDate: Wed, 26 Jul 2006 15:26:20 +0200\r\nFrom: Martin <martin@foo.de>\r\nUser-Agent: Thunderbird 1.5.0.4 (Windows/20060516)\r\nMIME-Version: 1.0\r\nTo: todo@foo.de\r\nSubject: Das ist ein Testtodo\r\nContent-Type: text/html; charset=ISO-8859-15\r\nContent-Transfer-Encoding: 8bit\r\n\r\n<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r\n<html>\r\n<head>\r\n  <meta content="text/html;charset=ISO-8859-15"\r\n http-equiv="Content-Type">\r\n</head>\r\n<body bgcolor="#ffffff" text="#333399">\r\n<font size="-1"><font face="Courier New, Courier, monospace">Hier steht\r\ndie n\xe4here Beschreibung des Todos<br>\r\n<br>\r\nMartin<br>\r\n</font></font>\r\n</body>\r\n</html>\r\n'),
  ')'])
In [65]: foo=Message.Message()
In [66]: foo.set_payload(data[1][0][1])
In [67]: str(foo)
Out[67]: 'From nobody Thu Aug 31 15:11:28 2006\n\nReturn-Path: <martin@foo.de>\r\nX-Sieve: cmu-sieve 2.0\r\nReceived: from [10.10.10.54] (etsch.intern.foo.de [10.10.10.54])\r\n\tby amazonas.intern.foo.de (8.11.6/8.11.6) with ESMTP id k6QDQJT20660\r\n\tfor <todo@foo.de>; Wed, 26 Jul 2006 15:26:19 +0200\r\nMessage-ID: <44C76D7C.4060205@foo.de>\r\nDate: Wed, 26 Jul 2006 15:26:20 +0200\r\nFrom: Martin  <martin@foo.de>\r\nUser-Agent: Thunderbird 1.5.0.4 (Windows/20060516)\r\nMIME-Version: 1.0\r\nTo: todo@foo.de\r\nSubject: Das ist ein Testtodo\r\nContent-Type: text/html; charset=ISO-8859-15\r\nContent-Transfer-Encoding: 8bit\r\n\r\n<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\r\n<html>\r\n<head>\r\n  <meta content="text/html;charset=ISO-8859-15"\r\n http-equiv="Content-Type">\r\n</head>\r\n<body bgcolor="#ffffff" text="#333399">\r\n<font size="-1"><font face="Courier New, Courier, monospace">Hier steht\r\ndie n\xe4here Beschreibung des Todos<br>\r\n<br>\r\nMartin<br>\r\n</font></font>\r\n</body>\r\n</html>\r\n'

Meinst du das so mit dem "per email parsen" oder vertue ich mich da gerade mit dem Anlegen der Message?
BlackJack

Da vertust Du Dich ein bischen. Mit `set_payload()` setzt Du die Daten als Inhalt der Nachricht, da wird nichts geparst. Also Deine Header stehen dann auch im Text der Mail und nicht davor. Versuchs mal so:

Code: Alles auswählen

In [65]: msg = email.message_from_string(txt)

In [66]: msg['subject']
Out[66]: 'Das ist ein Testtodo'

In [67]: msg.get_content_type()
Out[67]: 'text/html'

In [68]: msg.get_content_charset()
Out[68]: 'iso-8859-15'

In [69]: msg.get_payload()
Out[69]: '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN">\r\n<html>\r\n<head>\r\n  <meta
content="text/html;charset=ISO-8859-15"\r\n
http-equiv="Content-Type">\r\n</head>\r\n<body
bgcolor="#ffffff" text="#333399">\r\n<font size="-1"><font
face="Courier New, Courier, monospace">Hier steht\r\ndie
n\xe4here Beschreibung des
Todos<br>\r\n<br>\r\nMartin<br>\r\n</font></font>\r\n</body>\r\n</html>\r\n'
Etwas komplizierter wird's wenn Multipart-Nachrichten auseinander gepflückt werden sollen. MIME erlaubt ja beliebig tiefe Verschachtelung von Nachrichtenteilen.
tantris
User
Beiträge: 10
Registriert: Donnerstag 31. August 2006, 10:05

args danke dir ;-)
das sieht doch schon viel freundlicher aus *g*
tantris
User
Beiträge: 10
Registriert: Donnerstag 31. August 2006, 10:05

hmm wo finde ich eigentlich, welche Strings als "message_parts" in der imaplib zulässig sind?
In der Doku steht ja nur das Beispiel a'la M.fetch('1','(UID BODY[TEXT])')
oder M.fetch('1','(RFC822)') mit dem Vermerk, dass der hintere Teil angibt, welche message_parts man möchte - aber gibt es da noch andere Teile außer UID, BODY und dem RFC822-Teil? Egal wo ich suche, ich lande immer bei diesem Beispiel...
BlackJack

Das ist keine Python-Frage sondern eine IMAP-Frage. Das sind Argumente für den IMAP-Server. Viel Spass beim lesen des RFCs. :twisted:

Das wird übrigens auch in der Python-Doku verlinkt:

http://www.faqs.org/rfcs/rfc2060.html
tantris
User
Beiträge: 10
Registriert: Donnerstag 31. August 2006, 10:05

jepp da bin ich auch eben draufgestoßen *g* danke dir nochmal!
Antworten