2009-09-15 23 views
8

Estoy teniendo un problema enviando un correo electrónico utilizando caracteres Unicode smtplib en Python 3. Esta falla en el apartado 3.1.1, pero funciona en 2.5.4:Python 3 smtplib envía con caracteres 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() 

Probé un ejemplo de los documentos, que también falló. http://docs.python.org/3.1/library/email-examples.html, Enviar los contenidos de un directorio como un mensaje MIME ejemplo

¿Alguna sugerencia?

+0

Para aclarar, en 2.5.4, se envía sin un mensaje de error, pero reemplaza '€' con '?'. – foosion

Respuesta

10

La clave está en 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.

Así que lo que necesita es claridad, nomsg = MIMEText('€10'), sino más bien:

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

Si bien no todo lo que claramente documentada, sendmail necesita una cadena de bytes, no una de Unicode (eso es lo que especifica el protocolo SMTP); mira cómo se ve el msg.as_string() para cada una de las dos formas de compilarlo, dado el "no adivinar o codificar", tu camino todavía tiene ese carácter euro allí (y no hay forma de que sendmail lo convierta en una cadena de bytes), el mío no (y utf-8 está claramente especificado en todo).

+0

Eso se envía sin generar un mensaje de error. Envié a Thunderbird y a Gmail. Thunderbird solo mostró 10 como el texto del mensaje. Gmail mostró los 10 € completos. Python envía como 'codificación de transferencia de contenido: base64', mientras que Thunderbird envía 10 € como 'codificación de transferencia de contenido: 8 bits' y los envíos de gmail como 'multipart/alternativa; boundary = ... '¿Alguna sugerencia para generar un mensaje que Thunderbird pueda interpretar? – foosion

+0

No soy un experto en Thunderbird, pero intento otras codificaciones como 'iso-8859-15'. Aunque cualquier programa en estos días que no puede hacer utf-8 correctamente, ¡vale la pena arrojarlo al basurero de la historia, mente! -) –

+0

El problema no parece ser iso-8859-15 o utf-8, parece ser content-transfer-encoding. Todo lo demás que revisé usa 8 bits, mientras que python usa base64. Coercing el encabezado a 8 bits no ayuda. Usar quopri.encodestring() podría funcionar para obtener la codificación de 8 bits, pero no he podido averiguar cómo hacerlo funcionar. – foosion

2

_charset parámetro de MIMEText por defecto a us-ascii de acuerdo con docs. Como no es de nosotros, ascii establece que no está funcionando.

ejemplo, en los documentos que has probado claramente establece:

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

Usted podría utilizar .get_charset método en su mensaje a investigar el juego de caracteres, no es por cierto .set_charset también.

+0

Como dices, el juego de caracteres es us-ascii, que no incluye €. Usar set_charset en el mensaje no soluciona el problema. El problema (debería haber sido más preciso) está en la línea sendmail - UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter '\ x80' en la posición 161: ordinal no está en rango (128) Lo leí para significar que tengo para codificar el texto para que todo esté dentro del alcance (128), pero no he podido descifrar cómo hacerlo. – foosion

+0

Estaba viendo el tercer ejemplo en la página de ejemplos, enviando un directorio completo. Intenté enviar un directorio que constaba de un único archivo zip usando el ejemplo. Esto falló – foosion

Cuestiones relacionadas