2009-09-15 7 views
8

Sto avendo un problema email caratteri Unicode utilizzando smtplib in Python 3. Questo non riesce a 3.1.1, ma lavora a 2.5.4:Python 3 smtplib inviare con caratteri unicode

import smtplib 
    from email.mime.text import MIMEText 

    sender = to = '[email protected]' 
    server = 'smtp.DEF.com' 
    msg = MIMEText('€10') 
    msg['Subject'] = 'Hello' 
    msg['From'] = sender 
    msg['To'] = to 
    s = smtplib.SMTP(server) 
    s.sendmail(sender, [to], msg.as_string()) 
    s.quit() 

ho provato un esempio dai documenti, che ha anche fallito. http://docs.python.org/3.1/library/email-examples.html, il Invia il contenuto di una directory come un esempio di messaggio MIME

Qualche suggerimento?

+0

per chiarire, in 2.5.4, invia senza un messaggio di errore, ma sostituisce '€' con '?'. – foosion

risposta

10

La chiave è nella the docs:

class email.mime.text.MIMEText(_text, _subtype='plain', _charset='us-ascii') 

A subclass of MIMENonMultipart, the MIMEText class is used to create MIME objects of major type text. _text is the string for the payload. _subtype is the minor type and defaults to plain. _charset is the character set of the text and is passed as a parameter to the MIMENonMultipart constructor; it defaults to us-ascii. No guessing or encoding is performed on the text data.

Quindi quello che serve è chiaramente, nonmsg = MIMEText('€10'), ma piuttosto:

msg = MIMEText('€10'.encode('utf-8'), _charset='utf-8') 

Anche se non tutto ciò che chiaramente documentate, sendmail ha bisogno di una stringa di byte, non di uno Unicode (è ciò che specifica il protocollo SMTP); guarda come appare lo msg.as_string() per ciascuno dei due modi di costruirlo - data la "non ipotesi o codifica", il tuo modo ha ancora quel personaggio dell'euro (e non c'è modo per sendmail di trasformarlo in un vero strattone), il mio no (e utf-8 è chiaramente specificato in tutto).

+0

Che invia senza generare un messaggio di errore. Ho inviato a Thunderbird e Gmail. Thunderbird ha mostrato solo 10 come testo del messaggio. Gmail ha mostrato il totale di € 10. Python invia come 'content-transfer-encoding: base64' mentre Thunderbird invia € 10 come 'content-transfer-encoding: 8-bit' e gmail invia come 'multipart/alternative; boundary = ... 'Qualche suggerimento per generare un messaggio che Thunderbird può interpretare? – foosion

+0

Non sono un esperto di Thunderbird, ma provo altre codifiche come 'iso-8859-15'. Anche se ogni programma in questi giorni che non può fare correttamente utf-8 vale la pena gettarlo nella spazzatura della storia, mente! -) –

+0

Il problema non sembra essere iso-8859-15 o utf-8, sembra essere content-transfer-encoding. Tutto il resto che ho controllato usa 8 bit, mentre python usa base64. La coercizione dell'header a 8 bit non aiuta. Usare quopri.encodestring() potrebbe funzionare per ottenere la codifica a 8 bit, ma non sono stato in grado di capire come farlo funzionare. – foosion

2

_charset parametro di MIMEText predefinito su us-ascii in base allo docs. Dal momento che non è da noi-ascii set non funziona.

esempio nella documentazione che hai provato chiaramente afferma:

For this example, assume that the text file contains only ASCII characters.

Si potrebbe utilizzare il metodo .get_charset sul vostro messaggio di indagare il set di caratteri, non v'è inciso .set_charset pure.

+0

Come dici tu, il set di caratteri è us-ascii, che non include €. L'uso di set_charset sul msg non risolve il problema. Il problema (avrei dovuto essere più preciso) è sulla linea sendmail - UnicodeEncodeError: il codec 'ascii' non può codificare il carattere '\ x80' in posizione 161: ordinale non nel range (128) Ho letto questo per indicare che ho per codificare il testo in modo che tutto sia nel range (128), ma non sono stato in grado di capire come. – foosion

+0

Stavo guardando il terzo esempio nella pagina degli esempi, inviando un'intera directory. Ho provato a inviare una directory composta da un singolo file zip usando l'esempio. Questo fallì. – foosion