Enviar correo no-ASCII desde un programa Python

PythonArco

Cómo enviar correo con cuerpo o cabeceras no-ASCII desde un programa Python

Lo fácil

Enviar un correo ASCII es algo trivial gracias al módulo smtplib:

import smtplib
 
sender = "SteveBallmer@microshow.com"
receiver = "usuarios@internes.org"
 
msg =  "From: %s\n" % sender
msg += "To: %s\n" % receiver
msg += "Subject: Se alquilan sillas voladoras (patentadas)\n\n"
msg += "Sillas voladoras en versiones 'home' y 'professional' de alta calidad y libres de virus."
 
server = smtplib.SMTP('smtp.example.org')
server.sendmail(sender, receiver, msg)
server.quit()

Caracteres extendidos

El problema viene cuando necesitas enviar caracteres no-ASCII, es decir, tiene que utilizar una codificación de caracteres UTF-8, latin-1 o similar.

import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
 
sender = "SteveBallmer@microshow.com"
receiver = "usuarios@internes.org"
body = unicode(texto, 'latin-1')
 
coding = 'latin-1'
msg = MIMEText(body.encode(coding), 'plain', coding)
msg['From']    = sender
msg['To']      = receiver
msg['Subject'] = Header(u'Vendo cañones lanza-sillas', coding)  # la 'ñ' no se puede codificar en ASCII
 
server = smtplib.SMTP('smtp.example.org')
server.sendmail(sender, receiver, msg.as_string())
server.quit()

En el ejemplo, ‘texto’ es una variable que contiene texto procedende de un fichero codificado en latin-1 o quizá de un terminal con la misma codificación. Podría ser cualquier otra codificación, pero debe ser conocida y debe indicarse al crear la variable ‘body’ (de tipo unicode).

A MIMEText se le debe pasar texto codificado e indicar a su vez el encoding que se ha usado. A Header se le puede pasar texto unicode indicando qué encoding debe usar para codificar dicho texto.

Referencias