Django EmailMultiAlternatives和HTML电子邮件在Win2003上的Outlook 2003中显示

cet*_*eek 2 html python email django

我在从我的django应用程序发送电子邮件时使用django.core.mail.EmailMultiAlternatives,以确保在电子邮件客户端不支持HTML时邮件降级为文本.

这是我的send_email方法:

def send_email(self, from_address, to_list, subject, msg_text, msg_html):
        subject=subject.replace('\r','').replace('\n',' ')
        self.msg = EmailMultiAlternatives(subject, msg_text, from_address, to_list)
        self.msg.attach_alternative(msg_html, "text/html")
        self.msg.content_subtype = "html"
        self.msg.send()
Run Code Online (Sandbox Code Playgroud)

它适用于Gmail,Hotmail和许多其他电子邮件客户端 - 显示HTML内容没有问题.但它不会在Win2003上运行的Outlook 2003中显示HTML内容 - 只是文本版本.

如果我强行将HTML放入EmailMultiAlternatives调用中,即使用msg _html instead of msg_text,如下所示:

self.msg = EmailMultiAlternatives(subject, msg_html, from_address, to_list)
Run Code Online (Sandbox Code Playgroud)

然后它在所有客户端都能正常工作; 但这意味着对于不支持HTML的客户端或(更可能)已禁用HTML的客户端没有文本回退.

我认为值得一提的是,电子邮件是在Mac OS X上运行的django应用程序上生成的(以防万一它与操作系统之间的行终止符差异有关).

我看到使用其他语言的人与outlook有类似的问题......

我想知道是否有人知道为什么outlook会有不同的行为,是否有可以在我的代码中应用的简单修复?

mob*_*ley 5

我没有Outlook安装可用于测试这个,所以我想知道你的函数第五行的原因.

self.msg.content_subtype = "html"
Run Code Online (Sandbox Code Playgroud)

我不太了解多部分电子邮件内部,但在我的系统上,该行导致消息的两个部分都具有内容类型的text/html.离开它会在第一部分产生一条带有"Content-Type:text/plain"的消息,而在第二部分则会出现"Content-Type:text/html".

在任何情况下,关于Java问题的答案之一都提到将字符集更改为iso-8859-1.我认为你应该能够用django.core.mail做到这一点.

EmailMessage类(EmailMultiAlternatives从中继承)具有名为"encoding"的属性,用于设置要使用的字符集.默认情况下它是None,因此使用utf-8的默认字符集(除非在设置中被覆盖).

换句话说,在问题中列出的函数中的发送行之前添加如下内容:

self.msg.content_subtype = "iso-8859-1"
Run Code Online (Sandbox Code Playgroud)

不幸的是,这只会改变第一部分指定的编码(上面函数中的msg_text).附加替代内容的函数似乎不使用encoding属性.我不确定这是正确的方法,但我将EmailMultiAlternatives子类化为覆盖相关功能,它似乎工作正常.

class EmailMultiAlternativesWithEncoding(EmailMultiAlternatives):
    def _create_attachment(self, filename, content, mimetype=None):
        """
        Converts the filename, content, mimetype triple into a MIME attachment
        object. Use self.encoding when handling text attachments.
        """
        if mimetype is None:
            mimetype, _ = mimetypes.guess_type(filename)
            if mimetype is None:
                mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
        basetype, subtype = mimetype.split('/', 1)
        if basetype == 'text':
            encoding = self.encoding or settings.DEFAULT_CHARSET
            attachment = SafeMIMEText(smart_str(content,
                settings.DEFAULT_CHARSET), subtype, encoding)
            # original text being replaced above (not last argument)
            # attachment = SafeMIMEText(smart_str(content,
            #     settings.DEFAULT_CHARSET), subtype, settings.DEFAULT_CHARSET)
        else:
            # Encode non-text attachments with base64.
            attachment = MIMEBase(basetype, subtype)
            attachment.set_payload(content)
            Encoders.encode_base64(attachment)
        if filename:
            attachment.add_header('Content-Disposition', 'attachment',
                                  filename=filename)
        return attachment
Run Code Online (Sandbox Code Playgroud)

我不确定"smart_str(content,settings.DEFAULT_CHARSET)"部分是否也应该引用"encoding"而不是"settings.DEFAULT_CHARSET",但这是写入消息体处理文本(django.core.mail.EmailMessage.message) ).

正如我所说的,我没有Outlook所以我实际上无法测试Outlook方面,但它确实似乎将charset更改为iso-8859-1这两个部分.