This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author msladek
Recipients msladek
Date 2012-02-20.08:03:26
SpamBayes Score 0.00085044466
Marked as misclassified No
Message-id <1329725009.21.0.0898146100656.issue14062@psf.upfronthosting.co.za>
In-reply-to
Content
Hello!

I think there is a problem when adding UTF-8 subject to email message. I wrote following function (its code is based on examples I found in offical docs) which should send an email with UTF-8 subject, UTF-8 plain text body and attached file when all arguments are given. 
fromAddr - address of sender
toAddr - address of recipient
subject - subject
body - text of email body
attachment - full path to file we want to attach

Here is the code:

def sendMail (fromAddr, toAddr, subject, body = '', attachment = ''):
    message = email.mime.multipart.MIMEMultipart()
    message.add_header('From',fromAddr)
    message.add_header('To',toAddr)

    message['Subject'] = email.header.Header(subject,'utf-8')

    if (body != ''):
        msgPart = email.mime.text.MIMEText(body,'plain','utf-8')
        message.attach(msgPart)
    if (attachment != ''):
        if os.path.exists(attachment) == True:
            filename = attachment.rpartition(os.sep)[2]
            fp = open(attachment,'rb')
            msgPart = email.mime.base.MIMEBase('application','octet-stream')
            msgPart.set_payload(fp.read())
            fp.close()
            email.encoders.encode_base64(msgPart)
            msgPart.add_header('Content-Disposition','attachment',filename=filename)
            message.attach(msgPart)
    if smtpPort == 25:
        smtpCon = smtplib.SMTP(smtpSrv,smtpPort)
    else:
        smtpCon = smtplib.SMTP_SSL(smtpSrv,smtpPort)
    if (smtpUser != '') and (smtpPass != ''):
        smtpCon.login(smtpUser,smtpPass)
    smtpCon.send_message(message,mail_options=['UTF8SMTP','8BITMIME'])
    smtpCon.quit()

Running the function with following arguments:

sendMail('rzrobot@seznam.cz','msladek@volny.cz','žluťoučký kůň','úpěl ďábelské ódy')

produces following output on receiving side:

Return-Path: <rzrobot@seznam.cz>
Received: from smtp2.seznam.cz (smtp2.seznam.cz [77.75.76.43])
	by mx1.volny.cz (Postfix) with ESMTP id DD6BB2E09CD
	for <msladek@volny.cz>; Mon, 20 Feb 2012 08:34:38 +0100 (CET)
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=seznam.cz;
	h=Received:Content-Type:MIME-Version:From:To:Subject:--===============1029508565==:MIME-Version:Content-Transfer-Encoding:X-Smtpd:X-Seznam-User:X-Session:X-Country:X-Virus-Info:X-Seznam-SPF:X-Seznam-DomainKeys;
	b=cdU1VSRTCDf0x2CeBNbLJxYSOhSy7r9lNp+1s7+bed6AGBI48vufe3q7f8JFxlfTc
	ulZIDptWi6PMvlZYCBkh1uzTKcihZR7MCoxgW0PJLO1LX5elTJsZ/GTc5oe/GZXkTPT
	qwj1EQIlVn0dpZtt4jIzfC2RrO2IRieR2rozeQM=
Received: from dvr.ph.sladkovi.eu (ip-84-42-150-218.net.upcbroadband.cz [84.42.150.218])	by email-relay2.ng.seznam.cz (Seznam SMTPD 1.2.15-6@18976) with ESMTP;	Mon, 20 Feb 2012 08:34:35 +0100 (CET)  
Content-Type: multipart/mixed; boundary="===============1029508565=="
MIME-Version: 1.0
From: rzrobot@seznam.cz
To: msladek@volny.cz
Subject: =?utf-8?b?xb5sdcWlb3XEjWvDvSBrxa/FiA==?= 
X-DKIM-Status: fail
X-Virus: no (m2.volny.internal - Mon, 20 Feb 2012 08:34:40 +0100 (CET))
X-Spam: no (m2.volny.internal - Mon, 20 Feb 2012 08:34:41 +0100 (CET))
X-Received-Date: Mon, 20 Feb 2012 08:34:42 +0100 (CET)

--===============1029508565==:Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
X-Smtpd: 1.2.15-6@18976
X-Seznam-User: rzrobot@seznam.cz
X-Session: 11
X-Country: CZ
X-Virus-Info:clean
X-Seznam-SPF:neutral
X-Seznam-DomainKeys:unknown

w7pwxJtsIMSPw6FiZWxza8OpIMOzZHk=

--===============1029508565==--

Although no attachment argument was given, the client says that message has an attachment of unknown type and that message does not contain any text at all. See that message part header :Content-Type: text/plain; charset="utf-8" is part of the message part boundary instead of beeing inside of the message part.

When I change the code of function to generate the subject manually and add it via add_header like this:

def sendMail (fromAddr, toAddr, subject, body = '', attachment = ''):
    message = email.mime.multipart.MIMEMultipart()
    message.add_header('From',fromAddr)
    message.add_header('To',toAddr)

    base64Subject = base64.b64encode(subject.encode('utf-8')).decode()
    encodedSubject = '=?UTF-8?B?{0}?='.format(base64Subject)
    message.add_header('Subject',encodedSubject)

    if (body != ''):
        msgPart = email.mime.text.MIMEText(body,'plain','utf-8')
        message.attach(msgPart)
    if (attachment != ''):
        if os.path.exists(attachment) == True:
            filename = attachment.rpartition(os.sep)[2]
            fp = open(attachment,'rb')
            msgPart = email.mime.base.MIMEBase('application','octet-stream')
            msgPart.set_payload(fp.read())
            fp.close()
            email.encoders.encode_base64(msgPart)
            msgPart.add_header('Content-Disposition','attachment',filename=filename)
            message.attach(msgPart)
    if smtpPort == 25:
        smtpCon = smtplib.SMTP(smtpSrv,smtpPort)
    else:
        smtpCon = smtplib.SMTP_SSL(smtpSrv,smtpPort)
    if (smtpUser != '') and (smtpPass != ''):
        smtpCon.login(smtpUser,smtpPass)
    smtpCon.send_message(message,mail_options=['UTF8SMTP','8BITMIME'])
    smtpCon.quit()

Then everything is OK on receiving side, both subject and plaint text body are visible:

Return-Path: <rzrobot@seznam.cz>
Received: from smtp2.seznam.cz (smtp2.seznam.cz [77.75.76.43])
	by mx1.volny.cz (Postfix) with ESMTP id 177092E0825
	for <msladek@volny.cz>; Mon, 20 Feb 2012 08:51:58 +0100 (CET)
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=beta; d=seznam.cz;
	h=Received:Content-Type:MIME-Version:From:To:Subject:X-Smtpd:X-Seznam-User:X-Session:X-Country:X-Virus-Info:X-Seznam-SPF:X-Seznam-DomainKeys;
	b=F2A6GhX0TWVjnrB4vx/ayc1BTGDFxBI96oI0fk/gr/tgP0jlV1UC91m4i/O4ay+Bg
	lfka88qa71XZOlHtY2vl7zxYjGPJ97pRCdtqWB+JcNOa5bMsk6lmjMHh+A+FQ2e7+yb
	1F091t0nMcQlarriF8sD5rNjhuRYjvCv7kKbt8s=
Received: from dvr.ph.sladkovi.eu (ip-84-42-150-218.net.upcbroadband.cz [84.42.150.218])	by email-relay1.ng.seznam.cz (Seznam SMTPD 1.2.15-6@18976) with ESMTP;	Mon, 20 Feb 2012 08:51:55 +0100 (CET)  
Content-Type: multipart/mixed; boundary="===============1044203895=="
MIME-Version: 1.0
From: rzrobot@seznam.cz
To: msladek@volny.cz
Subject: =?UTF-8?B?xb5sdcWlb3XEjWvDvSBrxa/FiA==?=
X-Smtpd: 1.2.15-6@18976
X-Seznam-User: rzrobot@seznam.cz
X-Session: 11
X-Country: CZ
X-Virus-Info: clean
X-Seznam-SPF: neutral
X-Seznam-DomainKeys: unknown
X-DKIM-Status: pass seznam.cz
X-Virus: no (m2.volny.internal - Mon, 20 Feb 2012 08:52:00 +0100 (CET))
X-Spam: no (m2.volny.internal - Mon, 20 Feb 2012 08:52:01 +0100 (CET))
X-Received-Date: Mon, 20 Feb 2012 08:52:01 +0100 (CET)

--===============1044203895==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64

w7pwxJtsIMSPw6FiZWxza8OpIMOzZHk=

--===============1044203895==--

I am not a programmer so I might overlook some obvious mistake in my code but for now I think it's a bug.
History
Date User Action Args
2012-02-20 08:03:29msladeksetrecipients: + msladek
2012-02-20 08:03:29msladeksetmessageid: <1329725009.21.0.0898146100656.issue14062@psf.upfronthosting.co.za>
2012-02-20 08:03:28msladeklinkissue14062 messages
2012-02-20 08:03:26msladekcreate