home
erste Version am 20.02.2021
letzte Änderung am 21.02.2021

peek_mails

Bei diesem Kurz-Projekt handelt es sich um ein auf die Schnelle zusammengebasteltes Script, mit dem die relevanten Header-Daten von eMails auf einem externen Mailserver angezeigt werden können.



Die Motivation für dieses Script entstand durch die Ankündigung meines Domain-Hoster (hosteurope.de), den bisherigen WebMailer SquirrelMail durch WebMailer Pro abzulösen.
Den WebMailer habe ich immer gerne (an meinem always-on 11W-PC) genutzt, um mal kurz nach neuen eMails zu schauen - wenn das Smartphone nicht eingeschaltet oder in greifbarer Nähe war.
Leider funktioniert der neue WebMailer bei mir aber nicht.
Ein SupportCall hat ergeben, dass es an meiner Catch-All-Adresse liegt und "Webmailer Pro aber eine primär zugeordnete Adresse benötigt".
...dann eben nicht....bzw. jetzt mein peek_mails-Script.


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# peek_mails.py
#
# Zeigt ein paar Header-Daten von eingegangen eMails an.
#
# Als Workaround für diese blöde Umstellung auf "WebMailer Pro" bei
# HostEurope ... bzw. dessen Unfähigkeit, mit catch-all-Adressen
# umzugehen.
#
# 20.02.2021 D.Ahlgrimm

import email.header
import imaplib

# ----------------------------------------------------------------------
# liefert ein paar relevante Daten aus einer roh-eMail.
def parse_email(data):
if len(data)!=2:
return None
data=data[0][1].decode()
_from=_to=_subject=_date=""
subj_open=False
# via subj_open wird sowas hier umschifft:
# Subject: =?UTF-8?B?bm9jaCBlaW4gVMOkw6TDpMOkc3QuIGRpZXNtYWwgYWJlciBtaXQgZWlu?=
# =?UTF-8?Q?er_verdammt_langen_Betreffzeile=2c_die_nat=c3=bcrlich_auch_wieder?=
# =?UTF-8?Q?_ein_paar_verqu=c3=a4re_=c3=9cmlaute_enth=c3=a4lt_und_sowieso_gan?=
# =?UTF-8?Q?z_lang_und_Kacke_i=c3=9ft=2e=2e=2e=23=23=23---***_hexhex?=
for ln in data.split("\n"):
if ln.startswith(" ") and subj_open:
try:
t, e=email.header.decode_header(ln[1:])[0]
_subject+=t.decode("utf8")
except:
pass
else:
subj_open=False

if ln.startswith("From: "):
_from=ln.split(" ", 1)[1].strip()
elif ln.startswith("To: "):
_to=ln.split(" ", 1)[1].strip()
elif ln.startswith("Subject: "):
subj_open=True
_subject=ln.split(" ", 1)[1].strip()
try:
t, e=email.header.decode_header(_subject)[0]
_subject=t.decode("utf8")
except:
pass
elif ln.startswith("Date: "):
_date=ln.split(" ", 1)[1].strip()
return _from, _to, _subject, _date


# ----------------------------------------------------------------------
#
if __name__=='__main__':
mail=imaplib.IMAP4_SSL("blablafoobar.mail.server-he.de")
mail.login("username", "password")

fldrs=mail.list()
if len(fldrs)==2 and fldrs[0]=="OK":
for ln in fldrs[1]:
fldr=ln.decode().split(' "." ')[1]
mails=mail.select(fldr)
if len(mails)==2 and mails[0]=="OK":
try:
mail_cnt=int(mails[1][0].decode())
except:
mail_cnt=0
if fldr in ("HE-Reports"):
continue
if mail_cnt>0:
print("%3d %s"%(mail_cnt, fldr))

result, data=mail.search(None, "ALL")
for mail_id in data[0].decode().split():
result, data=mail.fetch(mail_id, "(RFC822)")
ped=parse_email(data)
if ped is None:
print("???")
else:
_from, _to, _subject, _date=ped
print("\nFrom: ", _from)
print("To: ", _to)
print("Subject:", _subject)
print("Date: ", _date)
#print(data[0][1].decode())
else:
print(">>>", fldr)
download als ZIP

Liefert dann etwa sowas hier (nachdem ich mir selbst Test-eMails geschickt hatte - weil alle anderen eMails schon von Thunderbird in lokale Ordner wegsortiert waren):
dede@11w:~> ./peek_mails.py
  3 INBOX

From:    xxxxxx <xxxxxx@gmx.de>
To:      dede@dahlgrimm.de
Subject: tescht
Date:    Sat, 20 Feb 2021 10:17:50 +0100

From:    xxxxxx <xxxxxx@xxxxx.org>
To:      detlev.ahlgrimm@dahlgrimm.de
Subject: noch ein Test (mit Umlauten im Beträf..öü)
Date:    Sat, 20 Feb 2021 10:57:00 +0100

From:   
xxxxxx <xxxxxx@xxxxx.org>
To:      detlev.ahlgrimm@dahlgrimm.de
Subject: noch ein Tääääst. diesmal aber mit einer verdammt langen Betreffzeile, die natürlich auch wieder ein paar verquäre Ümlaute enthält und sowieso ganz lang und Kacke ißt...###---*** hexhex
Date:    Sat, 20 Feb 2021 11:48:44 +0100
dede@11w:~>




Und aus gegebenem Anlass gleich ein kleiner Update hinterher:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# peek_mails.py
#
# Zeigt ein paar Header-Daten von eingegangen eMails an.
#
# Als Workaround für diese blöde Umstellung auf "WebMailer Pro" bei
# HostEurope ... bzw. dessen Unfähigkeit, mit catch-all-Adressen
# umzugehen.
#
# 20.02.2021 D.Ahlgrimm
#
# 21.02.2021 v1.01 UTF8 in "From:", für Mails das SEEN-Flag löschen,
# parse_email() durch email.message_from_string() ersetzt.

import email.header
import imaplib

# ----------------------------------------------------------------------
# liefert eine Zeile mit UTF8-Gezatter in lesbar.
def decode_line(ln):
ln2=ln.split(" ", 1)[1].strip()
try:
ln3=email.header.decode_header(ln2)
ln4=""
for t, e in ln3:
if e is not None:
ln4+=t.decode(e)
elif type(t)==bytes:
ln4+=t.decode()
elif type(t)==str:
ln4+=t
ln2=ln4
except Exception as e:
#print(e)
pass
return ln2

# ----------------------------------------------------------------------
# liefert ein paar relevante Daten aus einer roh-eMail.
def parse_email(data):
if len(data)!=2:
return None
data=data[0][1].decode()
_from=_to=_subject=_date=""
subj_open=False
# via subj_open wird sowas hier umschifft:
# Subject: =?UTF-8?B?bm9jaCBlaW4gVMOkw6TDpMOkc3QuIGRpZXNtYWwgYWJlciBtaXQgZWlu?=
# =?UTF-8?Q?er_verdammt_langen_Betreffzeile=2c_die_nat=c3=bcrlich_auch_wieder?=
# =?UTF-8?Q?_ein_paar_verqu=c3=a4re_=c3=9cmlaute_enth=c3=a4lt_und_sowieso_gan?=
# =?UTF-8?Q?z_lang_und_Kacke_i=c3=9ft=2e=2e=2e=23=23=23---***_hexhex?=
for ln in data.split("\n"):
if ln.startswith(" ") and subj_open:
try:
t, e=email.header.decode_header(ln[1:])[0]
_subject+=t.decode("utf8")
except:
pass
else:
subj_open=False

if ln.startswith("From: "):
#_from=ln.split(" ", 1)[1].strip()
_from=decode_line(ln)
elif ln.startswith("To: "):
#print(">>>>>>", ln)
_to=ln.split(" ", 1)[1].strip()
elif ln.startswith("Subject: "):
subj_open=True
_subject=ln.split(" ", 1)[1].strip()
try:
t, e=email.header.decode_header(_subject)[0]
_subject=t.decode("utf8")
except:
pass
elif ln.startswith("Date: "):
_date=ln.split(" ", 1)[1].strip()
return _from, _to, _subject, _date


# ----------------------------------------------------------------------
#
if __name__=='__main__':
mail=imaplib.IMAP4_SSL("blablafoobar.mail.server-he.de")
mail.login("username", "password")

fldrs=mail.list()
if len(fldrs)==2 and fldrs[0]=="OK":
for ln in fldrs[1]:
fldr=ln.decode().split(' "." ')[1]
mails=mail.select(fldr)
if len(mails)==2 and mails[0]=="OK":
try:
mail_cnt=int(mails[1][0].decode())
except:
mail_cnt=0
if fldr in ("HE-Reports"):
continue
if mail_cnt>0:
print("%3d %s"%(mail_cnt, fldr))

result, data=mail.search(None, "ALL")
for mail_id in data[0].decode().split():
result, data=mail.fetch(mail_id, "(RFC822)")
msg=email.message_from_string(data[0][1].decode())
print("\nFrom: ", decode_line("subj: "+"".join(msg["From"].split("\n"))))
print("To: ", decode_line("subj: "+"".join(msg["To"].split("\n"))))
print("Subject:", decode_line("subj: "+"".join(msg["Subject"].split("\n"))))
print("Date: ", msg["Date"])
"""
ped=parse_email(data)
if ped is None:
print("???")
else:
_from, _to, _subject, _date=ped
print("\nFrom: ", _from)
print("To: ", _to)
print("Subject:", _subject)
print("Date: ", _date)
#print(data[0][1].decode())
"""
mail.store(mail_id, '-FLAGS', '(\Seen)')
else:
print(">>>", fldr)
download als ZIP

Damit wird nun auch sowas hier korrekt dargestellt:
From:    ALDI Newsletter <newsletter@aldi-nord.de>
To:      xxxxxx@dahlgrimm.de
Subject: ❤️ Die schönsten Kreuzfahrten ❤️
Date:    Sat, 20 Feb 2021 14:09:24 +0100

From:    "FRITZ!Box" <xxxxxx@dahlgrimm.de>
To:      <
xxxxxx@dahlgrimm.de>,
Subject: FRITZ!Box-Info: Nutzungs- und Verbindungsdaten vom 20.02.2021
Date:    Sun, 21 Feb 2021 00:00:19 +0100