Description:
Django 1.3 introduced the cc constructor kwarg for
django.core.mail.EmailMessage. CC addresses do not appear to work at
all in trunk, and do appear to work with this patch. Not sure if you're
trying to be compatible with Django <1.3, if so I guess an alternate
patch is necessary.
Please review this at http://codereview.appspot.com/4657057/
Affected files:
M gae2django/gaeapi/appengine/api/mail.py
Index: gae2django/gaeapi/appengine/api/mail.py
===================================================================
--- gae2django/gaeapi/appengine/api/mail.py (revision 166)
+++ gae2django/gaeapi/appengine/api/mail.py (working copy)
@@ -101,14 +101,10 @@
def send(self):
headers = {}
- if self.cc:
- headers['Cc'] = ', '.join(self.cc)
- if self.bcc:
- headers['Bcc'] = self.bcc
if self.reply_to:
headers['Reply-To'] = ', '.join(self.reply_to)
msg = _EmailMessage(self.subject, self.body, self.sender,
- self.to, self.bcc, headers=headers)
+ self.to, self.bcc, cc=self.cc, headers=headers)
msg.send(fail_silently=True)
thanks for your patch and reporting this issue. But I wasn't able to
reproduce it. What I've tested/verified so far:
- with Django 1.2.5 and Django 1.3 the CC header is in the mail
- with Django 1.3 there's no issue when CC is in headers (current
situation), it's still in the outgoing message
However, Rietveld removes the issue owner from CCs before sending. Maybe
you've seen this behavior?
thanks for the explanations! See inline reply below.
Steve Howard <st...@thumbtack.com> writes:
> Hi Andi,
>
> Sorry, I should have been more specific. The behavior I observed was that
> the message itself included the correct CC header, but the message was not
> actually delivered to CC recipients. This fooled me at first because I
> tested it by sending an email To: me and Cc: coworkers, and the email looked
> fine to me. But it was not delivered to my coworkers, as I was able to
> confirm by sending an email To: a coworker and Cc: me.
>
> From my cursory reading of the SMTP wikipedia page, my understanding is that
> the mail client specifies recipients independently of the message body,
> which includes the To: and Cc: headers. This is supported by looking at the
> code in django.core.mail -- message.EmailMessage.recipients() returns to +
> cc + bcc, while EmailMessage.message() adds the To and Cc headers. And
> smtp.EmailBackend._send() uses the recipients() list in transmitting the
> email, converting the message itself to a string before passing it to
> smtplib -- it never examines the headers itself.
Yes, you're right! The problem is that manual CC headers are not taken
into account by Django when recipients() is called. So, the way
gae2django handles the Cc argument doesn't work and there's no way to
make it work with Django < 1.3. As you've pointed out, starting with
Django 1.3 it could actually work, when the CC keyword is passed to the
constructor of message.EmailMessage.
>
> So I think the correct behavior is to pass the CC list to the constructor of
> the django.core.mail.message.EmailMessage, and *not* add the Cc: or Bcc:
> headers in client code -- Django's EmailMessage adds the Cc: header itself,
> and the Bcc: header should not be added at all because it would then be
> visible to all recipients.
Passing Bcc to the constructor of message.EmailMessage should be fine
since both APIs (Django, App Engine) provide this keyword.
>
> Hope this clarifies things, and thank you for your great work on gae2django,
> it's really handy :)
Thanks! Happy to hear that :)
-Andi
>
> Steve
>
> On Thu, Jun 30, 2011 at 12:31 AM, <albrec...@googlemail.com> wrote:
>
>> Hi Steve,
>>
>> thanks for your patch and reporting this issue. But I wasn't able to
>> reproduce it. What I've tested/verified so far:
>>
>> - with Django 1.2.5 and Django 1.3 the CC header is in the mail
>> - with Django 1.3 there's no issue when CC is in headers (current
>> situation), it's still in the outgoing message
>>
>> However, Rietveld removes the issue owner from CCs before sending. Maybe
>> you've seen this behavior?
>>
>>
>> http://codereview.appspot.com/**4657057/<http://codereview.appspot.com/4657057/>
>>
Yes, gae2django should be compatible with Django 1.2 for now...
Hi Steve,
thanks for the explanations! See inline reply below.
Yes, you're right! The problem is that manual CC headers are not taken
Steve Howard <st...@thumbtack.com> writes:
> Hi Andi,
>
> Sorry, I should have been more specific. The behavior I observed was that
> the message itself included the correct CC header, but the message was not
> actually delivered to CC recipients. This fooled me at first because I
> tested it by sending an email To: me and Cc: coworkers, and the email looked
> fine to me. But it was not delivered to my coworkers, as I was able to
> confirm by sending an email To: a coworker and Cc: me.
>
> From my cursory reading of the SMTP wikipedia page, my understanding is that
> the mail client specifies recipients independently of the message body,
> which includes the To: and Cc: headers. This is supported by looking at the
> code in django.core.mail -- message.EmailMessage.recipients() returns to +
> cc + bcc, while EmailMessage.message() adds the To and Cc headers. And
> smtp.EmailBackend._send() uses the recipients() list in transmitting the
> email, converting the message itself to a string before passing it to
> smtplib -- it never examines the headers itself.
into account by Django when recipients() is called. So, the way
gae2django handles the Cc argument doesn't work and there's no way to
make it work with Django < 1.3. As you've pointed out, starting with
Django 1.3 it could actually work, when the CC keyword is passed to the
constructor of message.EmailMessage.
Passing Bcc to the constructor of message.EmailMessage should be fine
>
> So I think the correct behavior is to pass the CC list to the constructor of
> the django.core.mail.message.EmailMessage, and *not* add the Cc: or Bcc:
> headers in client code -- Django's EmailMessage adds the Cc: header itself,
> and the Bcc: header should not be added at all because it would then be
> visible to all recipients.
since both APIs (Django, App Engine) provide this keyword.
http://codereview.appspot.com/4657057/diff/6001/gae2django/gaeapi/appengine/api/mail.py#newcode80
gae2django/gaeapi/appengine/api/mail.py:80: if value is not None:
Why did you add this test? None values for missing fields should be ok
(see comment below too)
http://codereview.appspot.com/4657057/diff/6001/gae2django/gaeapi/appengine/api/mail.py#newcode110
gae2django/gaeapi/appengine/api/mail.py:110: self.to, self.cc +
self.bcc, headers=headers)
This collapses CC and BCC into Bcc. IMO we need two paths for
constructing a new EmailMessage instance depending on Django version in
use here.
http://codereview.appspot.com/4657057/diff/6001/gae2django/gaeapi/appengine/api/mail.py
File gae2django/gaeapi/appengine/api/mail.py (right):
http://codereview.appspot.com/4657057/diff/6001/gae2django/gaeapi/appengine/api/mail.py#newcode80
gae2django/gaeapi/appengine/api/mail.py:80: if value is not None:
Why did you add this test? None values for missing fields should be ok
(see comment below too)
http://codereview.appspot.com/4657057/diff/6001/gae2django/gaeapi/appengine/api/mail.py#newcode110
gae2django/gaeapi/appengine/api/mail.py:110: self.to, self.cc +
self.bcc, headers=headers)
This collapses CC and BCC into Bcc. IMO we need two paths for
constructing a new EmailMessage instance depending on Django version in
use here.
Agreed. The CC's are in the CC header and both CC+BCC are correctly
returned when recipients() is called. So you approach should be fine
with all current Django versions.
Thanks again for clarification and the patch. Committed as r169.
-Andi