Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a charset in email using smtplib in Python 2.7?

I'm writing a simple smtp-sender with authentification. Here's my code

    SMTPserver, sender, destination = 'smtp.googlemail.com', '[email protected]', ['[email protected]']
    USERNAME, PASSWORD = "user", "password"

    # typical values for text_subtype are plain, html, xml
    text_subtype = 'plain'


    content="""
    Hello, world!
    """

    subject="Message Subject"

    from smtplib import SMTP_SSL as SMTP       # this invokes the secure SMTP protocol (port 465, uses SSL)
    # from smtplib import SMTP                  # use this for standard SMTP protocol   (port 25, no encryption)
    from email.MIMEText import MIMEText

    try:
        msg = MIMEText(content, text_subtype)
        msg['Subject']=       subject
        msg['From']   = sender # some SMTP servers will do this automatically, not all

        conn = SMTP(SMTPserver)
        conn.set_debuglevel(False)
        conn.login(USERNAME, PASSWORD)
        try:
            conn.sendmail(sender, destination, msg.as_string())
        finally:
            conn.close()

    except Exception, exc:
        sys.exit( "mail failed; %s" % str(exc) ) # give a error message

It works perfect, untill I try to send non-ascii symbols (russian cyrillic). How should i define a charset in a message to make it show in a proper way? Thanks in advance!

UPD. I've changed my code:

text_subtype = 'text'
content="<p>Текст письма</p>"
msg = MIMEText(content, text_subtype)
msg['From']=sender # some SMTP servers will do this automatically, not all
msg['MIME-Version']="1.0"
msg['Subject']="=?UTF-8?Q?Тема письма?="
msg['Content-Type'] = "text/html; charset=utf-8"
msg['Content-Transfer-Encoding'] = "quoted-printable"
…
conn.sendmail(sender, destination, str(msg))

So, first time I spectify text_subtype = 'text', and then in header I place a msg['Content-Type'] = "text/html; charset=utf-8" string. Is it correct?

UPDATE Finally, I've solved my message problem You should write smth like msg = MIMEText(content.encode('utf-8'), 'plain', 'UTF-8')

like image 232
f1nn Avatar asked Apr 24 '12 09:04

f1nn


People also ask

How do I use Smtplib in Python?

Python provides smtplib module, which defines an SMTP client session object that can be used to send mail to any Internet machine with an SMTP or ESMTP listener daemon. host − This is the host running your SMTP server. You can specify IP address of the host or a domain name like tutorialspoint.com.

What is Smtplib in Python How can you use Python built-in mail server explain?

The smtplib module The smtplib is a Python library for sending emails using the Simple Mail Transfer Protocol (SMTP). The smtplib is a built-in module; we do not need to install it. It abstracts away all the complexities of SMTP.

Does Python come with Smtplib?

Python comes with the built-in smtplib module for sending emails using the Simple Mail Transfer Protocol (SMTP). smtplib uses the RFC 821 protocol for SMTP. The examples in this tutorial will use the Gmail SMTP server to send emails, but the same principles apply to other email services.

What is Smtplib port?

If port is zero, the standard SMTP-over-SSL port (465) is used.


1 Answers

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

def contains_non_ascii_characters(str):
    return not all(ord(c) < 128 for c in str)   

def add_header(message, header_name, header_value):
    if contains_non_ascii_characters(header_value):
        h = Header(header_value, 'utf-8')
        message[header_name] = h
    else:
        message[header_name] = header_value    
    return message

............
msg = MIMEMultipart('alternative')
msg = add_header(msg, 'Subject', subject)

if contains_non_ascii_characters(html):
    html_text = MIMEText(html.encode('utf-8'), 'html','utf-8')
else:
    html_text = MIMEText(html, 'html')    

if(contains_non_ascii_characters(plain)):
    plain_text = MIMEText(plain.encode('utf-8'),'plain','utf-8') 
else:
    plain_text = MIMEText(plain,'plain')

msg.attach(plain_text)
msg.attach(html_text)

This should give you your proper encoding for both text and headers regardless of whether your text contains non-ASCII characters or not. It also means you won't automatically use base64 encoding unnecessarily.

like image 87
Lorcan O'Neill Avatar answered Sep 28 '22 21:09

Lorcan O'Neill