[py3] Pass bytes as "msg" to smtplib.SMTP.sendmail()
When passing a unicode string to smtplib.SMTP.sendmail() as "msg"
argument, there is an implicit bytes encoding using "ascii" encoding in
python3. Of course this does not work if the string contains non-ASCII
characters. In fact, config's sendmails method intent to pass bytes to
smtplib.SMTP.sendmail() as it uses msg.as_string() method.
Unfortunately, in python3, this method returns a unicode string whereas
it returns a bytes string in python2; we thus fix this by calling
as_bytes() method on python3.
As there is no "as_bytes" method in python2, we need to handle python2
compatibility by hand and either call as_string() or as_bytes().
In testlib, where we mock smtplib.SMTP, we need to keep the "msg"
argument of Email class (defined in testlib as well) a unicode string.
Otherwise, it fails to be parsed by email.message_from_string() (from
stdlib) if it is bytes on python3.
--- a/cubicweb/cwconfig.py Wed Jul 24 13:39:52 2019 +0200
+++ b/cubicweb/cwconfig.py Tue Aug 06 14:26:17 2019 +0200
@@ -192,7 +192,7 @@
from threading import Lock
from warnings import filterwarnings
-from six import text_type
+from six import PY2, text_type
from logilab.common.decorators import cached, classproperty
from logilab.common.deprecation import deprecated
@@ -1344,9 +1344,10 @@
if self.mode == 'test':
raise
return False
- for msg, recipients in msgs:
+ for mimedoc, recipients in msgs:
+ msg = mimedoc.as_string() if PY2 else mimedoc.as_bytes()
try:
- smtp.sendmail(fromaddr, recipients, msg.as_string())
+ smtp.sendmail(fromaddr, recipients, msg)
except Exception as ex:
self.exception("error sending mail to %s (%s)",
recipients, ex)
--- a/cubicweb/devtools/testlib.py Wed Jul 24 13:39:52 2019 +0200
+++ b/cubicweb/devtools/testlib.py Tue Aug 06 14:26:17 2019 +0200
@@ -205,7 +205,7 @@
pass
def sendmail(self, fromaddr, recipients, msg):
- MAILBOX.append(Email(fromaddr, recipients, msg))
+ MAILBOX.append(Email(fromaddr, recipients, msg.decode('utf-8')))
cwconfig.SMTP = MockSMTP