'How to send utf-8 e-mail?
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)
Solution 1:[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:[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.
Solution 3:[3]
The previous answers here were adequate for Python 2 and earlier versions of Python 3. Starting with Python 3.6, new code should generally use the modern EmailMessage
API rather than the old email.message.Message
class or the related MIMEMultipart
, MIMEText
etc classes. The newer API was unofficially introduced already in Python 3.3, and so the old one should no longer be necessary unless you need portability back to Python 2 (or 3.2, which nobody in their right mind would want anyway).
With the new API, you no longer need to manually assemble an explicit MIME structure from parts, or explicitly select body-part encodings etc. Nor is Unicode a special case any longer; the email
library will transparently select a suitable container type and encoding for regular text.
import sys
import re
import smtplib
from email.message import EmailMessage
def sendmail(firm, fromEmail, to, template, subject, date):
with open(template, "r", 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 = EmailMessage()
msg["Subject"] = subject
msg["From"] = fromEmail
msg["To"] = to
html = message[message.find("html:") + len("html:"):message.find("text:")].strip()
text = message[message.find("text:") + len("text:"):].strip()
msg.set_content(text)
msg.add_alternative(html, subtype="html")
try:
server = smtplib.SMTP("10.0.0.5")
server.send_message(msg)
return 0
# XXX FIXME: useless
except Exception as ex:
raise ex
finally:
server.quit()
# Explicitly return error
return 1
if __name__ == "__main__":
if len(sys.argv) != 7:
# Can't return negative
exit(2)
exit(sendmail(*sys.argv[1:]))
I'm not sure I completely understand the template handling here. Practitioners with even slightly different needs should probably instead review the Python email
examples documentation
which contains several simple examples of how to implement common email use cases.
The blanket except
is clearly superfluous here, but I left it in as a placeholder in case you want to see what exception handling might look like if you had something useful to put there.
Solution 4:[4]
For whom it might interest, I've written a Mailer library that uses SMTPlib, and deals with headers, ssl/tls security, attachments and bulk email sending.
Of course it also deals with UTF-8 mail encoding for subject and body.
You may find the code at: https://github.com/netinvent/ofunctions/blob/master/ofunctions/mailer/__init__.py
The relevant encoding part is
message["Subject"] = Header(subject, 'utf-8')
message.attach(MIMEText(body, "plain", 'utf-8'))
TL;DR: Install with pip install ofunctions.mailer
Usage:
from ofunctions.mailer import Mailer
mailer = Mailer(smtp_server='myserver', smtp_port=587)
mailer.send_email(sender_mail='[email protected]', recipient_mails=['[email protected]', '[email protected]'])
Encoding is already set as UTF-8, but you could change encoding to whatever you need by using mailer = Mailer(smtp_srever='...', encoding='latin1')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | abbot |
Solution 2 | wjandrea |
Solution 3 | |
Solution 4 | tripleee |