superset 定时发送邮件时,附件为中文出现乱码

ef send_email_smtp(
        to,
        subject,
        html_content,
        config,
        files=None,
        data=None,
        images=None,
        dryrun=False,
        cc=None,
        bcc=None,
        mime_subtype="mixed",
):
    """
    Send an email with html content, eg:
    send_email_smtp(
        '[email protected]', 'foo', 'Foo bar',['/dev/null'], dryrun=True)
    """
    smtp_mail_from = config["SMTP_MAIL_FROM"]
    to = get_email_address_list(to)

    msg = MIMEMultipart(mime_subtype)
    msg["Subject"] = subject
    msg["From"] = smtp_mail_from
    msg["To"] = ", ".join(to)
    msg.preamble = "This is a multi-part message in MIME format."

    recipients = to
    if cc:
        cc = get_email_address_list(cc)
        msg["CC"] = ", ".join(cc)
        recipients = recipients + cc

    if bcc:
        # don't add bcc in header
        bcc = get_email_address_list(bcc)
        recipients = recipients + bcc
    msg["Date"] = formatdate(localtime=True)
    mime_text = MIMEText(html_content, "html")
    msg.attach(mime_text)

    # Attach files by reading them from disk
    for fname in files or []:
        basename = os.path.basename(fname)
        with open(fname, "rb") as f:
            msg.attach(
                MIMEApplication(
                    f.read(),
                    Content_Disposition="attachment; filename='%s'" % make_header([(basename, 'UTF-8')]).encode(
                        'UTF-8'),
                    Name=make_header([(basename, 'UTF-8')]).encode('UTF-8'),
                )
            )
            # # msg.add_header('Content-Disposition', 'attachment',
            # #                filename='=?utf-8?b?' + base64.b64encode(basename.encode('UTF-8')).decode() + '?=')
            # msg.attach(
            #     MIMEApplication(
            #         f.read(),
            #         Content_Disposition="attachment; filename='%s'" % dd_b64(basename),
            #         Name=basename,
            #     )
            # )

    # Attach any files passed directly
    for name, body in (data or {}).items():
        msg.attach(
            MIMEApplication(
                body,
                Content_Disposition="attachment; filename='%s'" % make_header([(name, 'UTF-8')]).encode('UTF-8'),
                Name=make_header([(name, 'UTF-8')]).encode('UTF-8')
            )
        )
        # # msg.add_header('Content-Disposition', 'attachment',
        # #                filename='=?utf-8?b?' + base64.b64encode(name.encode('UTF-8')) + '?=')
        # msg.attach(
        #     MIMEApplication(
        #         body,
        #         Content_Disposition="attachment; filename='%s'" % dd_b64(name),
        #         Name=name
        #     )
        # )

    # Attach any inline images, which may be required for display in
    # HTML content (inline)
    for msgid, body in (images or {}).items():
        image = MIMEImage(body)
        image.add_header("Content-ID", "<%s>" % msgid)
        image.add_header("Content-Disposition", "inline")
        msg.attach(image)

    send_MIME_email(smtp_mail_from, recipients, msg, config, dryrun=dryrun)

上面为修改后的代码,主要的修改是在邮件头部的设置。

 

第一次修改,只改了Content_Disposition 里面的filename,如下图片的修改,该修改结果是 foxmail的显示正常,但是iso 和网页版 和网易邮箱都是无法正确显示附件名称,

superset 定时发送邮件时,附件为中文出现乱码_第1张图片

第二次修改,头部的name也用头部make_header 处理,如下图,无论是网页版,还是Foxmail,还是iso 还是lookout都可以正常显示:

superset 定时发送邮件时,附件为中文出现乱码_第2张图片

修改后的最终代码:
msg.attach(
    MIMEApplication(
        f.read(),
        Content_Disposition="attachment; filename='%s'" % make_header([(basename, 'UTF-8')]).encode(
            'UTF-8'),
        Name=make_header([(basename, 'UTF-8')]).encode('UTF-8'),
    )
)

涉及到的修改还有一处:

msg.attach(
    MIMEApplication(
        body,
        Content_Disposition="attachment; filename='%s'" % make_header([(name, 'UTF-8')]).encode('UTF-8'),
        Name=make_header([(name, 'UTF-8')]).encode('UTF-8')
    )
)

原理讲解:

MIMEApplication:会把默认指定传输做base64 加密Content-Transfer-Encoding: base64,因此传送时需要对数据做based64 

make_header 默认会做base64

客户端在解析的时候会对其解码,如果不对内容进行base64,客户端无法解析

filename 和 Name 两者要一致

 

你可能感兴趣的:(python3)