Search code examples
pythonpython-3.xemailutf-8smtplib

Python smtplib and internationalization error with smtputf8 fix


Am having problem with python smtplib when using a non ascii characters in from name. Part of the error code - is

server does not advertise the required SMTPUTF8 capability

I have checked online for solutions and also looked around in stackoverflow with no solutions.

Using same

smtp

on Other mail client with same From name it worked so I figured this can be solved with code since I can't edit the server config.

Please help with a solution guide or example to help fix this.

See snippet of code below with traceback.

# the problem is this line below. How do I make it work regardless 
# since i have no means of advertising smtputf8 from there server.
# Thunderbird doesn't have problem with the name when used as client.

data['from_name'] = "Böy" # problem is the ö
data['from_email'] = "user@example.com"
msg = MIMEMultipart()
msg['To'] = "{to_name} <{to_email}>".format(**data)
msg['From'] = "{} <{}>".format(data['from_name'], data['from_email'])
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach(MIMEText(body, 'html'))

smtp_server.send_message(msg) # exception is raised here

Traceback:

`Traceback (most recent call last):
  File "Emailer.py", line 460, in <module>
    main(args)
  File "Emailer.py", line 447, in main
    sender.send()
  File "Emailer.py", line 386, in send
    smtp_server.send_message(msg)
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/smtplib.py", line 952, in send_message
    "One or more source or delivery addresses require"
smtplib.SMTPNotSupportedError: One or more source or delivery addresses require internationalized email support, but the server does not advertise the required SMTPUTF8 capability`

Solution

  • I am unable to reproduce your issue. With the following augmented code, I have what appears to be a MCVE:

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.utils import formatdate
    
    
    data = {'to_name': 'me', 'to_email': 'me@example.net'}
    subject = 'Hellö'
    body = 'Hellö'
    
    data['from_name'] = "Böy" # problem is the ö
    data['from_email'] = "user@example.com"
    msg = MIMEMultipart()
    msg['To'] = "{to_name} <{to_email}>".format(**data)
    msg['From'] = "{} <{}>".format(data['from_name'], data['from_email'])
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject
    msg.attach(MIMEText(body, 'html'))
    
    print(msg.as_string())
    

    But when I run it, Python produces a completely healthy, completely 7-bit US-ASCII message with all the parts encoded precisely like they should be for a legacy server which doesn't support SMTPUTF8.

    Content-Type: multipart/mixed; boundary="===============2605356503081581034=="
    MIME-Version: 1.0
    To: me <me@example.net>
    From: =?utf-8?b?QsO2eSA8dXNlckBleGFtcGxlLmNvbT4=?=
    Date: Mon, 13 Aug 2018 10:56:02 +0300
    Subject: =?utf-8?b?SGVsbMO2?=
    
    --===============2605356503081581034==
    Content-Type: text/html; charset="utf-8"
    MIME-Version: 1.0
    Content-Transfer-Encoding: base64
    
    SGVsbMO2
    
    --===============2605356503081581034==--
    

    However, I will notice that instantiating a bare MIMEMultipart as your top-level message is not really correct. You should have a Message object and then add MIME parts to that. But this still uses the somewhat complex legacy Python email API; with the new API, which was introduced in 3.3 and became the preferred API in 3.6, you should start with an EmailMessage and take it from there.

    Anyway, if you only have a single body part, you should not wrap it in a multipart message. Simply create an email message and attach the text part directly to that. (It's not wrong per se to have a more complex MIME structure than you need, but it's silly to add unnecessary complexity and overhead.)