Workaround for the problem that UTF-8 Japanese mail cannot be sent with Flask-Mail (Python3)

If you write the conclusion first

Flask-Mail is messing with the global settings when sending mail with utf-8 without permission, so after importing it, if you restore it, it will work. Specifically, write this somewhere before sending.

test.py


from email import charset
charset.add_charset('utf-8', charset.SHORTEST, charset.BASE64, 'utf-8')

Or, if it is limited to Japan, if you explicitly specify charset in shift_jis, you can send it without problems without doing the above.

test.py


msg = Message(sender=(u"sender", "[email protected]"),
                  subject = u"title",
                  recipients = ["[email protected]"],
                  reply_to = u"Reply<[email protected]>",
                  charset = 'shift_jis')  #← This is
msg.body = u"It's an exam flask_sjis"
mail.send(msg)

that's all. The following is a capture.

What is Flask-Mail?

Flask has a super useful extension called Flask-Mail. It's easy enough with smtplib and email, but it's unusually easy to send emails that are often used to create web services.

I wonder if you can understand by looking at this.

http://pythonhosted.org/flask-mail/

In particular, as a recent requirement, I often send multipart / altnative e-mail newsletters (those that support both HTML mail and text mail), but that is also unusually easy to send.

test.py


from flask import Flask
from flaskext.mail import Mail, Message

app = Flask(__name__)
mail = Mail(app)
msg = Message(subject, sender=sender, recipients=reciepients)
msg.body='Hooray'
msg.html='<h1>Hooray</h1>'
mail.send(msg)

Dangerous.

The problem you are having

Actually, in Python2, it works in a good mood due to brain stop, but when it is executed in Python3, it usually becomes like this. I don't understand what it means and I completely lose my motivation.

Flask seems to be good, so I'll touch it! -> Like! Put it into actual business! -> Send an email? Flask-Mail seems to be useful! -> Gee! !! !! !! !! Clogged! !! !! I wonder if there are people like this. It's me. Hello! !! !!

Click here for the experiment code

flask_urf8.py


# -*- coding: utf-8 -*-
from flask import Flask
from flask_mail import Message, Mail

app = Flask(__name__)

with app.app_context():
    mail = Mail(app)
    msg = Message(sender=(u"sender", "[email protected]"),
                  subject=u"title",
                  recipients=["[email protected]"],
                  reply_to=u"Reply<[email protected]>")
    msg.body = u"A flask_utf8"
    mail.send(msg)

result

Traceback (most recent call last):
  File "flask_utf8.py", line 14, in <module>
    mail.send(msg)
  File "/Users/yasunori/venvs/sai/lib/python3.3/site-packages/flask_mail.py", line 416, in send
    message.send(connection)
  File "/Users/yasunori/venvs/sai/lib/python3.3/site-packages/flask_mail.py", line 351, in send
    connection.send(self)
  File "/Users/yasunori/venvs/sai/lib/python3.3/site-packages/flask_mail.py", line 168, in send
    message.as_string())
  File "/usr/local/Cellar/python3/3.3.3/Frameworks/Python.framework/Versions/3.3/lib/python3.3/smtplib.py", line 746, in sendmail
    msg = _fix_eols(msg).encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character '\u3042' in position 364: ordinal not in range(128)

why?

So, I was reading the Flask-Mail code, but I wondered what it was.

flask_mail.py


charset.add_charset('utf-8', charset.SHORTEST, None, 'utf-8')

There is this description. The global (!) Character code setting used for mail is overwritten (!) Without permission.

So, as I checked before, Python3 doesn't work with this setting so far. http://qiita.com/yasunori/items/265d8db746742bb967c4#2-10

So, after importing Flask-Mail, I overwrote it and restored it, and it worked.

Baka! !! !!.py


from email import charset
charset.add_charset('utf-8', charset.SHORTEST, charset.BASE64, 'utf-8')

I mean, how many settings do you change?

After reading the Flask-Mail issue, "If you use BASE64 for BODY, it's easy to get caught in the spam filter, so I think it's better to set it to None. That's what Django does, too." "Seriously !? Thank you!" It was in.

By the way, Django in question has been changed so that it will not be overwritten now because "I was wondering why I overwrote the global". It seems that Flask-Mail has taken in a momentary gap.

Finally

Please let me know if there is a more fundamental solution.

That's it.

Recommended Posts

Workaround for the problem that UTF-8 Japanese mail cannot be sent with Flask-Mail (Python3)
Workaround for the problem that? Is displayed when checking the version when using non-standard perl | python with pkg version
Address to the bug that node.surface cannot be obtained with python3 + mecab
The problem that the ifconfig command cannot be used
A solution to the problem that the Python version in Conda cannot be changed
Solution when the image cannot be displayed with tkinter [python]
How to solve the problem that video content cannot be played on Firefox for Linux
Workaround for the problem that sys.argv is not passed when executing a Python script with only the file name in Python2.7 on Windows
Be careful of LANG for UnicodeEncodeError when printing Japanese with Python 3
Understand the probabilities and statistics that can be used for progress management with a python program
The story of making a module that skips mail with python
Solution to the problem that Ctrl + z cannot be used in Powershell in Docker for windows environment (provisional)
Mathematical optimization that can be used for free work with Python + PuLP
Python modules with "-(hyphen)" cannot be removed
Items that cannot be imported with sklearn
Intuitive explanation that does not rely on mathematical formulas for the Monty Hall problem and simulation with Python
About the matter that localhost: 4040 cannot be accessed after running Spark with Docker
Python script that makes UTF-8 files with all BOMs under the folder without BOMs
Project cannot be created with Python3.5 (Windows) + django1.7.1
Use logger with Python for the time being
Investigation when import cannot be done with python
Solving the Python knapsack problem with the greedy algorithm
Python note: When the pip command cannot be used
Japanese can be used with Python in Docker environment
Run with CentOS7 + Apache2.4 + Python3.6 for the time being
Import libraries that cannot be pip installed with PyCharm
Try to solve the internship assignment problem with Python
The first algorithm to learn with Python: FizzBuzz problem
Python knowledge notes that can be used with AtCoder
[Memorandum] Japanese keys cannot be used in python string.Template.substitute
Information for controlling the motor with Python on RaspberryPi
Python program that looks for the same file name
The 14th offline real-time writing reference problem with Python
A memo that I touched the Datastore with python
I tried to solve the problem with Python Vol.1
The story that Japanese output was confused with Django
4 boxes that might be useful for the Pepper hackathon
[Raspberry Pi] Scraping of web pages that cannot be obtained with python requests + Beautiful Soup
Problem that pip install cannot be done with pyenv + Yosemite (error: command'clang' failed with exit status 1)
Dealing with the error that HTTP fetch error occurs in gpg and the key cannot be obtained