[Python-de] Datum aus Mails parsen

Martin A. Brown martin at linux-ip.net
Di Mär 22 22:00:22 EDT 2016


Grüße Florian,

>ich will das Datum einer Mail rausfinden, ob es das Sende- oder 
>Empfangsdatum ist, oder eins der Stationen in der Mitte ist egal.

Aber es kommt darauf an ....

Ich meine, wie Christopher Arndt schon beantwortet hat--Du mußt 
wissen was für Deine Zwecke dient.  Ich würde auch noch etwas 
hinzufügen:  Man sollte diese Daten nicht schlichtweg trauen, denn 
jeder Rechner kann von NTP [0] Synchronismus abweichen.

>Nun habe ich mir mal eine beliebige Mail rausgegriffen:
>
>From someone at gmail.com Fri Feb 05 09:09:11 2016

Vorige Zeile wurde von dem MDA [1] geschreiben.  Diese Zeitstempel 
gehört nicht zu dem Netzwerk, sondern (ich vermute) den Rechner 
'hermes.informatik.uni-stattgart.de' und wurde von dem Dovecot MDA 
hinzugefügt.

>Received: from ipvsmail.informatik.uni-stuttgart.de
>        by hermes.informatik.uni-stuttgart.de (Dovecot) with LMTP id 842rLx9mtFbVeAAAqVsIVA
>        for <user at ipvs.uni-stuttgart.de>; Fri, 05 Feb 2016 10:09:12 +0100
>Received: from mx3.informatik.uni-stuttgart.de (mailgw.informatik.uni-stuttgart.de [129.69.211.42])
>        by ipvsmail.informatik.uni-stuttgart.de (Postfix) with ESMTP id D3111EA3
>        for <somereceiver at ipvsmail.informatik.uni-stuttgart.de>; Fri,  5 Feb 2016 10:09:12 +0100 (CET)
>Received: by mx3.informatik.uni-stuttgart.de (Postfix, from userid 65534)
>        id BD6DB6251; Fri,  5 Feb 2016 10:09:12 +0100 (CET)
>Received: from mail-lf0-f52.google.com (mail-lf0-f52.google.com [209.85.215.52])
>        (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
>        (No client certificate requested)
>        by mx3.informatik.uni-stuttgart.de (Postfix) with ESMTPS id E6D546249
>        for <somereceiver at ipvs.uni-stuttgart.de>; Fri,  5 Feb 2016 10:09:11 +0100 (CET)
>Received: by mail-lf0-f52.google.com with SMTP id 78so52976351lfy.3
>        for <somereceiver at ipvs.uni-stuttgart.de>; Fri, 05 Feb 2016 01:09:11 -0800 (PST)
>X-Received: by 10.25.42.18 with SMTP id q18mr5524069lfq.151.1454663351309;
>        Fri, 05 Feb 2016 01:09:11 -0800 (PST)
>Received: by 10.25.145.21 with HTTP; Fri, 5 Feb 2016 01:09:11 -0800 (PST)
>Received: by 10.25.145.21 with HTTP; Fri, 5 Feb 2016 01:09:11 -0800 (PST)

Die oben kopierten Headers sind alle von Rechnern durch die diese 
Email geflossen hat.  Jeder Rechner stellt sein eigenes 'Received' 
Header ganz oben voran.  D.h. die Ursprüngliche Nachricht trug nur 
dieses Datum:

>Date: Fri, 5 Feb 2016 10:09:11 +0100

Normaleweise, traut man die Zeitstempel (gewissermaßen).  In diesem 
Beispiel, brauchte es nur eine Sekunde um vom Rechner des Absenders 
zum Dovecot LMTP MDA auf hermes.informatik.uni-stuttgart.de.  Ich 
vermute deshalb daß es höchstwahrscheinlich 10:09:11 CET war am 
Rechner der Sender.

Die anderen Received headers berichten den Weg (stufenweise).

Wenn Du weiter über Email und das Datumformat wissen wolltest, 
kannst Du das alles in den RFCs lesen und lernen:

  * RFC 5322 [2]  (aktuell)
  * RFC 2822 [3]  (ein Zwischenstop)
  * RFC 822 [4]   (die Quelle)

>Ein wenig habe ich schon irrelevante Infos rausgenommen.
>
>Probleme die ich sehe ist a) die Zuverlässigkeit des Datums und b) 
>die Standardisierung des Formates.

Standardisierung:  In Received Headers, ist das herkömmliche 
Datumformat RFC822 genannt. Zum Beispiel auf ein Linux system:

  $ date --rfc-822
  Tue, 22 Mar 2016 18:00:52 -0700

Zuverlässigkeit:  Ein unlösliches Problem, denn E-Mail ist ein 
dezentrales System und jeder Rechner eine falsche Zeitstempel 
hinzufügen kann.  Auch wenn es nicht absichtlich ist.

>Der Date Header springt natürlich sofort ins Auge, aber ich denke 
>nicht, dass der sonderlich zuverlässig ist. 

>Regelmäßig bekomme ich Spam mit unbekannten Datum oder Datum in der 
>Zukunft. Außerdem habe ich bei ersten Testläufen auch verschiedene 
>Formate gesehen (z.B. die Zeit ohne Sekunden)

Ein E-Mail Programm (MUA [5]) kann irgendeine Datumformat benutzen.  
(Die meisten Programmen benutzen ein vernünftiges Format.)  Es soll 
nicht so sein, aber das wichtigste ist daß, dieses Datum für die 
Lieferung nicht geeignet ist.  Dieses Datum ist nur für den 
endgültige Leser vorgelegt.

Du kannst Dich entscheiden daß dieses Datum Deine Zwecke dient.  
Ich würde lieber ein Server Zeitstempel trauen/glauben.

(Noch etwas:  Die übliche Zeile 'From' 'To', 'Cc', 'Subject', 'Date' 
sind bei manchen MTAs [6] nicht gelesen, nur die Absender- u. 
Empfängeradresse vom SMTP Protokoll.)

>Nun frage ich mich, was da am zuverlässigsten ist?

Als Empfänger, kannst Du nie wirklich wissen.  Es ist möglich daß 
alle Rechner gelogen haben.  Ein Rechner konnte alle vorige Received 
Header geändert haben.  Es ist auch möglich daß keiner gelogen hat.  
Wenn alle Daten in Einklang sind, dann denke ich nur daß alles gut 
läuft.

>Die erste Zeile From gibt es offensichtlich auch nicht bei allen 
>Mails.

Ein bißchen merkwürdig(, aber fast alles ist so in diesem veralteten 
System!)  Die Verantwortung für dieses 'From' Zeile (N.B. keinen 
Doppelpunkt, ':') gehört dem MDA [1] (Dovecot in Deinem Beispiel).  

Vielleicht sind einige Emails auf anderer Weise in diesem 
Datenverzeichnis geschrieben worden?  (D.h. nicht von dem MDA 
geschrieben worden, sondern von einem anderen Programm...)

>Sollte man einfach den ersten Received Header nehmen, am ";" 
>trennen und dann datetime.strptime mit einen entsprechenden Format 
>String drauf los lassen?
>
>Was denkt Ihr, ist das Beste?

Wenn ich wissen wollte wann ein Email geschickt wurde, würde ich 
genau das tun.  Man weiß daß ein Rechner vielleicht von NTP 
(korrekte Zeit) abgeweicht ist.  Aber was tut man, wenn man schon 
ein Datei mit diesem Datum hat?  Wenn es nicht um legales oder 
gefährliches geht, dann greife ich zum ersten Received Header.

Man kann auch die Received Headers programmatisch lesen um 
herauszufinden wo eine Email sich verspätet hat.

Und Christopher Arndt hat recht mit seinem dateutil Vorschlag:

  >>> parser = dateutil.parser.parse
  >>> parser('Fri,  5 Feb 2016 10:09:12 +0100 (CET)')
  datetime.datetime(2016, 2, 5, 10, 9, 12, tzinfo=tzoffset(u'CET', 3600))

-Martin

 [0] https://de.wikipedia.org/wiki/Network_Time_Protocol
 [1] https://de.wikipedia.org/wiki/Mail_Delivery_Agent
 [2] https://tools.ietf.org/html/rfc5322#section-3.3
 [3] https://tools.ietf.org/html/rfc2822
 [4] https://tools.ietf.org/html/rfc822
 [5] https://de.wikipedia.org/wiki/E-Mail-Programm
 [6] https://de.wikipedia.org/wiki/Mail_Transfer_Agent
 [7] https://de.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#Protokoll

(Meiner Meinung nach ist es auch ein Irrweg in der Perfektion von 
dem eigenen Rechner zu glauben.)

-- 
Martin A. Brown
http://linux-ip.net/


Mehr Informationen über die Mailingliste python-de