How to send utf-8 e-mail?

56,167

Solution 1

You should just add 'utf-8' argument to your MIMEText calls (it assumes 'us-ascii' by default).

For example:

# -*- encoding: utf-8 -*-

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

msg = MIMEMultipart("alternative")
msg["Subject"] = u'テストメール'
part1 = MIMEText(u'\u3053\u3093\u306b\u3061\u306f\u3001\u4e16\u754c\uff01\n',
                 "plain", "utf-8")
msg.attach(part1)

print msg.as_string().encode('ascii')

Solution 2

The question asked by Martin Drlík is 7 years and 8 months old... And nowadays, thanks to the developers of Python, encoding problems are solved with version 3 of Python.

Consequently, it is no longer necessary to specify that one must use the utf-8 encoding:

#!/usr/bin/python2
# -*- encoding: utf-8 -*-
...
    part2 = MIMEText(text, "plain", "utf-8")

We will simply write:

#!/usr/bin/python3
...
    part2 = MIMEText(text, "plain")

Ultimate consequence: Martin Drlík's script works perfectly well!

However, it would be better to use the email.parser module, as suggested in email: Examples.

Share:
56,167

Related videos on Youtube

Martin Drlík
Author by

Martin Drlík

Updated on July 09, 2022

Comments

  • Martin Drlík
    Martin Drlík almost 2 years

    how to send utf8 e-mail please?

    import sys
    import smtplib
    import email
    import re
    
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    
    def sendmail(firm, fromEmail, to, template, subject, date):
        with open(template, encoding="utf-8") as template_file:
            message = template_file.read()
    
        message = re.sub(r"{{\s*firm\s*}}", firm, message)
        message = re.sub(r"{{\s*date\s*}}", date, message)
        message = re.sub(r"{{\s*from\s*}}", fromEmail, message)
        message = re.sub(r"{{\s*to\s*}}", to, message)
        message = re.sub(r"{{\s*subject\s*}}", subject, message)
    
        msg = MIMEMultipart("alternative")
        msg.set_charset("utf-8")
        
        msg["Subject"] = subject
        msg["From"] = fromEmail
        msg["To"] = to
    
        #Read from template
        html = message[message.find("html:") + len("html:"):message.find("text:")].strip()
        text = message[message.find("text:") + len("text:"):].strip()
    
        part1 = MIMEText(html, "html")
        part2 = MIMEText(text, "plain")
        
        msg.attach(part1)    
        msg.attach(part2)
    
        try:
            server = smtplib.SMTP("10.0.0.5")
            server.sendmail(fromEmail, [to], msg.as_string())
            return 0
        except Exception as ex:
            #log error
            #return -1
            #debug
            raise ex
        finally:
            server.quit()
    
    if __name__ == "__main__":
        #debug
        sys.argv.append("Moje")
        sys.argv.append("[email protected]")
        sys.argv.append("[email protected]")
        sys.argv.append("may2011.template")
        sys.argv.append("This is subject")
        sys.argv.append("This is date")
    
        
        if len(sys.argv) != 7:
            exit(-2)
    
        firm = sys.argv[1]
        fromEmail = sys.argv[2]
        to = sys.argv[3]
        template = sys.argv[4]
        subject = sys.argv[5]
        date = sys.argv[6]
        
        exit(sendmail(firm, fromEmail, to, template, subject, date))
    

    Output

    Traceback (most recent call last):
      File "C:\Documents and Settings\Administrator\Plocha\Newsletter-build-desktop\sendmail.py", line 69, in <module>
        exit(sendmail(firm, fromEmail, to, template, subject, date))   
      File "C:\Documents and Settings\Administrator\Plocha\Newsletter-build-desktop\sendmail.py", line 45, in sendmail
        raise ex
      File "C:\Documents and Settings\Administrator\Plocha\Newsletter-build-desktop\sendmail.py", line 39, in sendmail
        server.sendmail(fromEmail, [to], msg.as_string())
      File "C:\Python32\lib\smtplib.py", line 716, in sendmail
        msg = _fix_eols(msg).encode('ascii')
    UnicodeEncodeError: 'ascii' codec can't encode character '\u011b' in position 385: ordinal not in range(128)
    
    • orlp
      orlp about 13 years
      We are missing line numbers so we can locate the exact line of the error.
    • blubb
      blubb about 13 years
      The error is probably in the message.as_string(). You need to provide more, or we won't be able to help you.
  • hephestos
    hephestos about 12 years
    Sorry for being this old post and I write a new question underneath but I have to... Is supposed a human to write things like 'u\3035\u3093 ????? you have some japanese word right? how do you come up with these codes? from the tutorials i have read I always see this numbers ( while I understand are codes for letters , I don;t get how the input is done to this code or similar ones ...)
  • sasikumar
    sasikumar about 12 years
    These codes are here only for illustration purposes. You can set your python source input encoding to utf-8 and type Unicode constants directly. If you need to get those '\u...' codes for some chars, you can just do something like print repr(u'テストメール')
  • hephestos
    hephestos about 12 years
    First thank you for the quick answer...Check this out ( to understand my issue with this question) I did this test : I put a utf-8 word (greek letters) in a variable and stored in a dictionary 'ΤΕΣΤ'=X. In the "Immediate window" when I do print listOfutfs reports me some u'' codes! ( from mysql I had ΤΕΣΤ retrieved ). Then I say ok give me the value back as listOfutfs['ΤΕΣΤ'], it replies to me KeyError: '\xce\xa6\xce\xa1\xce\x9b\xce\x9a'!!!!!!!!!!!!!!!!
  • hephestos
    hephestos about 12 years
    ok, got it [u'ΤΕΣΤ']! terrible sorry, I didn't know that this whole thing of u'' is for explanatory reasons....How do you concatenate though, unicodes in python then? you can not write u""" ΤΕΣΤ """ also, right ?
  • sasikumar
    sasikumar about 12 years
    You actually can. Follow the python Unicode howto: docs.python.org/howto/unicode.html
  • hephestos
    hephestos about 12 years
    Thank you abbot, I just realised how many months lost...cheers
  • IonicBurger
    IonicBurger almost 9 years
    I have tested this on python2.6.4 and it does not work as expected, the way to get past it is to also encode the unicode string as 'utf', it does however seem to work on python 2.7.2. In 2.6.4 you would do as an example, MIMEText( u'\3053'.encode('utf-8'), 'plain', 'utf-8')
  • tripleee
    tripleee about 2 years
    If this still uses the old MIMEText API, it should perhaps be avoided by anyone writing new code.
  • Orsiris de Jong
    Orsiris de Jong about 2 years
    Well my code is compatible from python 2.7 up to recent 3.10, and tested via continuous integration. So as far as I want to keep retrocompatibility, I'll stick to MIMEText which, except of some shortcommings which I already cover via my code, doesn't have any major flaw AFAIK. Anyway, thanks for your advice.