classification
Title: smtplib.SMTP.sendmail: improve exception message
Type: enhancement Stage:
Components: email Versions: Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: barry, berker.peksag, ncoghlan, r.david.murray, yegle
Priority: normal Keywords:

Created on 2014-02-02 02:41 by yegle, last changed 2019-03-15 22:47 by BreamoreBoy.

Messages (4)
msg209943 - (view) Author: yegle (yegle) Date: 2014-02-02 02:41
Currently the `msg` argument of `smtplib.SMTP.sendmail` accept a `str` in Py3k if every characters in this `str` is in ASCII range, or a `bytes`.

This is confusing for new comer because:

1. When you send your mail using only ASCII characters, everything is fine (no matter you use bytes or str).
2. When sometimes you included non-ASCII characters in your email, the traceback is hard to understand.

Here's an example of such traceback:

Traceback (most recent call last):
  File "./manage.py", line 113, in <module>
    manager.run()
  File "/data/web/cgi-bin/venv/lib/python3.3/site-packages/flask_script/__init__.py", line 405, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/data/web/cgi-bin/venv/lib/python3.3/site-packages/flask_script/__init__.py", line 384, in handle
    return handle(app, *positional_args, **kwargs)
  File "/data/web/cgi-bin/venv/lib/python3.3/site-packages/flask_script/commands.py", line 145, in handle
    return self.run(*args, **kwargs)
  File "./manage.py", line 108, in run
    conn.send(msg)
  File "/data/web/cgi-bin/venv/lib/python3.3/site-packages/flask_mail.py", line 168, in send
    message.as_string())
  File "/data/web/cgi-bin/python-3.3.3/lib/python3.3/smtplib.py", line 747, in sendmail
    msg = _fix_eols(msg).encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character '\u9f99' in position 646: ordinal not in range(128)

Here's my proposal:

--- smtplib.py.orig     2014-02-01 21:26:47.000000000 -0500
+++ smtplib.py  2014-02-01 21:37:51.000000000 -0500
@@ -744,7 +744,12 @@
         esmtp_opts = []
         print(msg)
         if isinstance(msg, str):
-            msg = _fix_eols(msg).encode('ascii')
+            try:
+                msg = _fix_eols(msg).encode('ascii')
+            except UnicodeEncodeError:
+                raise SMTPException(
+                    "msg may be a string containing characters in the "
+                    "ASCII range, or a byte string.")
         if self.does_esmtp:
             # Hmmm? what's this? -ddm
             # self.esmtp_features['7bit']=""
msg236411 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2015-02-22 17:28
Assuming that the inline patch in msg209943 is acceptable I'll volunteer to change the test code unless the originator wants the job.
msg236412 - (view) Author: yegle (yegle) Date: 2015-02-22 17:40
I have no plan to work further, Mark can take the code and improve anyway you want.
msg236464 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2015-02-23 21:13
I don't believe that there is much sense in implementing the proposed change.  If the stdlib was changed every time a UnicodeEncodeError was reported just to show a slightly clearer exception message, I dread to think how much extra code would be added in total.  Committing a change such as this takes core dev time which IMHO opinion could be put to better use.
History
Date User Action Args
2019-03-15 22:47:00BreamoreBoysetnosy: - BreamoreBoy
2015-02-23 21:13:48BreamoreBoysetmessages: + msg236464
versions: + Python 3.5, - Python 3.3
2015-02-22 19:21:59berker.peksagsetnosy: + berker.peksag
2015-02-22 17:40:02yeglesetmessages: + msg236412
2015-02-22 17:28:51BreamoreBoysetnosy: + BreamoreBoy
messages: + msg236411
2014-02-02 02:44:32yselivanovsetnosy: + ncoghlan
2014-02-02 02:41:28yeglecreate