The Smtplib.Server.Sendmail Function in Python Raises Unicodeencodeerror: 'Ascii' Codec Can't Encode Character

The smtplib.server.sendmail function in python raises UnicodeEncodeError: 'ascii' codec can't encode character

smtplib.server's sendmail method expects a bytes instance; if it gets a str it tries to encode it to ASCII, resulting in a UnicodeEncodeError if the str contains any non-ASCII characters.

You can workaround this by encoding the message yourself:

>>> msg = 'Hello Wørld'
>>> from_ = 'a@example.com'
>>> to_ = 'b@example.com'
>>> subject = 'Hello'

>>> fmt = 'From: {}\r\nTo: {}\r\nSubject: {}\r\n{}'

>>> server.sendmail(to_, from_, fmt.format(to_, from_, subject, msg).encode('utf-8'))
{}

This will send this message*:

b'From: b@example.com'
b'To: a@example.com'
b'Subject: Hello'
b'Hello W\xc3\xb8rld'

However this workaround will not work if you want to send non-text binary data with your message.

A better solution is to use the EmailMessage class from the email package.

>>> from email.message import EmailMessage
>>> em = EmailMessage()
>>> em.set_content(msg)
>>> em['To'] = to_
>>> em['From'] = from_
>>> em['Subject'] = subject

>>> # NB call the server's *send_message* method
>>> server.send_message(em)
{}

This sends this message; note the extra headers telling the recipient the encoding used:

b'Content-Type: text/plain; charset="utf-8"'
b'Content-Transfer-Encoding: 8bit'
b'MIME-Version: 1.0'
b'To: to@example.com'
b'From: from@example.com'
b'Subject: Hello'
b'X-Peer: ::1'
b''
b'Hello W\xc3\xb8rld'

* Run the command python -m aiosmtpd -n -l localhost:1025† (Pre-Python3.9: python -m smtpd -n -c DebuggingServer localhost:1025) in a separate terminal to capture the message data.

† aiosmtpd must be installed using pip. Unlike smtpd it is not part of the standard library.

Ascii codec can't encode character when sending email

This error generally occurs due to inconsistency between the string values being dealt with, mainly with mixing variables of type str with those of type unicode. Based on the Unicode HOWTO, we must encode it properly to utf-8. So Produto becomes Produto.encode("utf-8") instead.

Issue with smtplib sending mail with unicode characters in Python 3.1

You can instead just use:

msg = MIMEText(message, _charset="UTF-8")
msg['Subject'] = Header(subject, "utf-8")

But either way you still have issues if your frm = "xxxx@xxxxxx.com" or to = "xxxx@xxxxxx.com" constains unicode characters. You can't use Header there.

Ascii encoding error during sending a mail

It appears as though whatever character \xa0 represents does not have a representation in ASCII. According to this link, \xa0 is the unicode character for a non-breaking space.

Since this is really just a space, you could try and replace all \xa0 characters in your string:

 messages = ["\n".join(msg.replace(u'\xa0', u' ')) for msg in messages]

To be fair, space and non-breaking spaces function differently, so depending on where this character appears in your message, the output could look slightly different after replacing the non-breaking spaces with regular spaces.

Another option is to ignore any characters that produce any error. This solution is not ideal because you could lose characters that end-up changing the formatting (or sometimes meaning) of your text. Replacing the non-breaking space with a normal space is smart to do regardless, but for all other pesky characters:

msg.encode("ascii", errors="ignore")

Alternatively, you can do msg.encode("ascii", errors="replace") but that will replace these characters with a '?' which doesn't look so nice.

UnicodeEncodeError: 'ascii' codec can't encode character in position 0-4: ordinal not range(128)

server.sendmail('email.com', 'email.com', 'привет'.encode('utf-8'))

Python: UnicodeEncodeError: 'ascii' codec can't encode character '\u039f' in position 0: ordinal not in range(128)

I assume that the error is on the server.sendmail(email, remail, message) line.

The documentation for sendmail is explicit (emphazise mine):

... msg may be a string containing characters in the ASCII range, or a byte string. A string is encoded to bytes using the ascii codec, and lone \r and \n characters are converted to \r\n characters. A byte string is not modified.

As you pass a message containing Greek (non ascii) characters, its encoding with the ASCII codec raises the error.

How to fix:

The simplest way is IMHO to use the send_message method:

from email.message import EmailMessage
...
msg = EmailMessage()
msg.set_content(message)
with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
server.login(email, password)
server.send_message(msg, email, remail) #remail is the receiver email

It will automatically encode the message in utf8 and add the relevant headers.



Related Topics



Leave a reply



Submit