email modul - subject (Betreff) nicht lesbar darstellbar

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
nnako
User
Beiträge: 2
Registriert: Montag 6. Juli 2015, 18:55

Hallo,

ich experimentiere gerade ein wenig mit dem Modul "email" herum. Dabei bin ich auf einen Effekt gestoßen, der mir zeigt, wie wenig ich bisher von den eMail-Kodierungen verstanden habe. Vielleicht kann mir jemand von euch weiterhelfen.

Und zwar gehe ich folgendermaßen vor, um ein eMail-Gateway zu bauen:

- ich sende eine eMail mit dem SUBJECT "ich will jetzt endlich Würstchen..." an eine eigene eMail-Adresse z.B. "gateway@web.de"
- ich verwende ein Python-Skript und das Modul "imapclient", um die eMail von gateway@web.de per IMAP zu holen. Per imapclient.fetch() .
- ich dekodiere die eMail über email.message_from_string() und hole mir per message.get_all('subject')[0] den SUBJECT

Nun sehe ich folgendes im zurückgegebenen SUBJECT-String:
'ich will jetzt endlich =?UTF-8?B?V8O8cnN0Y2hlbi4uLg==?='

Wenn ich KEINE Umlaute verwende, also z.B. "ue" anstatt "ü", so erhalte ich an dieser Stelle einen komplett lesbaren String.

FRAGEN
(1) Kann mir jemand erläutern, was unterwegs mit meinem SUBJECT passiert ist?
(2) Gibt es eine Möglichkeit, den Betreff einer eMail (trotz Umlauten) sauber zu übertragen?

Danke.
Nnako
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@nnako: das Mail-Protokoll ist ein 7bit Protokoll, daher müssen Zeichen die außerhalb von ASCII liegen codiert werden, hier mit base64-encoded utf8. Zwischen =? und dem nächsten ? steht das Encoding und dann bis ?= steht der base64-codierte String.

Code: Alles auswählen

>>> text = 'ich will jetzt endlich =?UTF-8?B?V8O8cnN0Y2hlbi4uLg==?='
>>> re.sub('=\?(.*?)\?B\?(.*?)\?=', lambda m: m.group(2).decode('base64').decode(m.group(1)), text)
u'ich will jetzt endlich W\xfcrstchen...'
BlackJack

Wobei das `email`-Package da auch etwas für hat:

Code: Alles auswählen

In [14]: email.Header.decode_header('ich will jetzt endlich =?UTF-8?B?V8O8cnN0Y2hlbi4uLg==?=')
Out[14]: [('ich will jetzt endlich', None), ('W\xc3\xbcrstchen...', 'utf-8')]
Aus den (Bytestring, Encoding)-Tupeln kann man dann eine Unicode-Zeichenkette zusammenbasteln.
nnako
User
Beiträge: 2
Registriert: Montag 6. Juli 2015, 18:55

Hallo ihr beiden,

vielen Dank, habe nun letztere Variante verwendet:

Code: Alles auswählen

#get the module
import email

# decode subject if there were special characters
tmpSubject = email.header.decode_header(strOriginalSubject)

# run through encoded subject
result = ''
for part in tmpSubject:

    # check if there is an encoding
    if part[1] == None:

        # copy part
        result = result + part[0].decode('iso-8859-1')

    else:

        # decode part
        result = result + part[0].decode(part[1])
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

oder kurz:

Code: Alles auswählen

result = ''.join(text.decode(encoding or 'iso-8859-1') for text, encoding in tmpSubject)
Antworten