19

Here is a part of my code which sends an email:

servidor = smtplib.SMTP()
servidor.connect(HOST, PORT)
servidor.login(user, usenha)
assunto = str(self.lineEdit.text())
para = str(globe_email)             
texto = self.textEdit.toPlainText()
textos = str(texto)
corpo = MIMEText(textos.encode('utf-8'), _charset='utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = assunto
servidor.sendmail(user, [para], corpo.as_string())

Everything is ok except the part of the Subject. When I try to send a string with special characters (e.g. "ação") it raises this error:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-2: ordinal not in range(128)

How can I send emails with special characters in the Subject of MIMEText?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
jonathan.hepp
  • 1,603
  • 3
  • 15
  • 21

2 Answers2

47

It seems that, in python3, a Header object is needed to encode a Subject as utf-8:

# -*- coding: utf-8 -*-
from email.mime.text import MIMEText
from email.header import Header
s = 'ação'
m = MIMEText(s, 'plain', 'utf-8')
m['Subject'] = Header(s, 'utf-8')
print(repr(m.as_string()))

Output:

'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: base64\nSubject: =?utf-8?b?YcOnw6Nv?=\n\nYcOnw6Nv\n

So the original script would become:

servidor = smtplib.SMTP()
servidor.connect(HOST, PORT)
servidor.login(user, usenha)
assunto = str(self.lineEdit.text())
para = str(globe_email)             
texto = str(self.textEdit.toPlainText())
corpo = MIMEText(texto, 'plain', 'utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = Header(assunto, 'utf-8')
servidor.sendmail(user, [para], corpo.as_string())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • It seems? It is on the documentation: https://docs.python.org/2/library/email.header.html – Al Martins Oct 29 '20 at 13:38
  • 1
    @AlMartins Yes, "seems". I just tested this with Python-3.2.6, Python-3.3.0 and Python-3.8.6, and I got the exact same output whether a `Header` object was used or not. This is probably due to [compat32](https://docs.python.org/3/library/email.policy.html#email.policy.Compat32). Presumably the OP was using an earlier version of Python3 which had different behaviour. So it *seems* the current documentation is somewhat misleading, since a `Header` object isn't necessarily required. However, for the sake of backward compatibility, it *seems* best to continue using it. – ekhumoro Oct 29 '20 at 15:00
1

I've improved the answer with other way to connect with the server and loggin, because the other way i had the problem to authenticate with the application and people can see all the libraries that should be use

from email.mime.text import MIMEText
from email.header import Header
import smtplib

user='email1@teste.com'
pwd='password'
server = smtplib.SMTP('smtp.office365.com', 587) #it works with outlook
server.ehlo()
server.starttls()
server.login(user, pwd)
assunto = 'Teste'
para = 'email2@teste.com'
texto = 'Niterói é uma cidade incrível '
corpo = MIMEText(texto, 'plain', 'utf-8')
corpo['From'] = user
corpo['To'] = para
corpo['Subject'] = Header(assunto, 'utf-8')
try:
    server.sendmail(user, [para], corpo.as_string())
    print('email was sent')
except:
    print('error')
server.quit()
  • Thanks for your answer, but can you please expand on this answer? Review [How do I write a good answer?]( https://stackoverflow.com/help/how-to-answer) – abestrad Jun 26 '20 at 11:30
  • Not successful on Python 3 using Flask. html.encode('utf-8') works. – Al Martins Oct 30 '20 at 16:40