【问题标题】:Create HTML Mail with inline Image and PDF Attachment创建带有内嵌图像和 PDF 附件的 HTML 邮件
【发布时间】:2017-03-16 07:20:33
【问题描述】:

我想用 Python/Django 编写包含这些部分的 HTML 邮件:

  • HTML 链接到 logo.png
  • logo.png 应该在邮件用户代理中内联显示(而不是作为附件)
  • info.pdf 应该显示为附件
  • 邮件用户代理无法显示 HTML 时应显示的文本。

我关注了this 博文。

结果:

  • HTML 和内嵌图像有效
  • 但是 info.pdf 文件被视为内联 logo.png,并且某些邮件用户代理不显示它:-(

如何在python中的一封邮件中创建两种方式(下载(info.pdf)和内联(logo.png))?

【问题讨论】:

  • 这有帮助吗? :stackoverflow.com/a/20717538/2286762
  • @soupboy 不,它没有帮助。您引用的问题仅解决了一种附加文件的方法。
  • 但是你能够实现的内联图像部分对吗?你能在你遇到问题的地方展示你的代码吗?
  • 我喜欢投反对票....如果我知道为什么这样做的话。请告诉我,我很好奇。
  • @soupboy 在我年轻的时候,即使我没有“完成”的定义,我也会写代码。我现在 40 岁,只有在我有完成/准备好的定义时才使用 pyCharm。我试图找到一个解释如何构建使用两者的邮件(通过 cid:logo.png 的内联附件和可下载的附件)。我找不到指导方针。这就是我没有编码的原因,这就是为什么这个问题不包含回溯 :-) 你在答案中找到了代码和一个不错的 ascii 艺术结构......

标签: python django email mime


【解决方案1】:

我对这种结构进行了逆向工程,以便在实践中使用:

+-------------------------------------------------------+
| multipart/mixed                                       |
|                                                       |
|  +-------------------------------------------------+  |
|  |   multipart/related                             |  |
|  |                                                 |  |
|  |  +-------------------------------------------+  |  |
|  |  | multipart/alternative                     |  |  |
|  |  |                                           |  |  |
|  |  |  +-------------------------------------+  |  |  |
|  |  |  | text can contain [cid:logo.png]     |  |  |  |
|  |  |  +-------------------------------------+  |  |  |
|  |  |                                           |  |  |
|  |  |  +-------------------------------------+  |  |  |
|  |  |  | html can contain src="cid:logo.png" |  |  |  |
|  |  |  +-------------------------------------+  |  |  |
|  |  |                                           |  |  |
|  |  +-------------------------------------------+  |  |
|  |                                                 |  |
|  |  +-------------------------------------------+  |  |
|  |  | image logo.png  "inline" attachment       |  |  |
|  |  +-------------------------------------------+  |  |
|  |                                                 |  |
|  +-------------------------------------------------+  |
|                                                       |
|  +-------------------------------------------------+  |
|  | pdf ("download" attachment, not inline)         |  |
|  +-------------------------------------------------+  |
|                                                       |
+-------------------------------------------------------+

不幸的是我只找到了这个复杂的解决方案:

from django.core.mail.message import EmailMessage


def create_email(subject='', body='', from_email=None, to=None, bcc=None,
                 connection=None, attachments=[], headers=None,
                 cc=None, reply_to=None, html_body='', html_inline_attachments=[]):
    message = _create_email(subject=subject, body=body, from_email=from_email, to=to, bcc=bcc,
                            connection=connection, headers=headers, cc=cc, reply_to=reply_to,
                            html_body=html_body, html_inline_attachments=html_inline_attachments)

    for attachment in attachments:
        if isinstance(attachment, basestring):
            message.attach_file(attachment)
            continue
        message.attach(attachment)

    return message


def _create_email(subject='', body='', from_email=None, to=None, bcc=None,
                  connection=None, headers=None,
                  cc=None, reply_to=None, html_body='', html_inline_attachments=[]):
    if not (body or html_body):
        raise ValueError('Missing body or html_body!')

    for address, type, name in [
        (from_email, basestring, 'from_email'),
        (to, list, 'to'),
        (cc, list, 'cc'),
        (bcc, list, 'bcc')]:
        if address and not isinstance(address, type):
            raise ValueError('"{}" must be a list! ({})'.format(name, address))

    if body and not html_body:
        if html_inline_attachments:
            raise ValueError('"html_body" is missing!')
        return EmailMessage(subject=subject, body=body, from_email=from_email, to=to, bcc=bcc,
                            connection=connection, headers=headers, cc=cc,
                            reply_to=reply_to)

    if not body:
        body = html_to_text(html_body)
    msg = EmailMessage(subject=subject, from_email=from_email, to=to, bcc=bcc,
                       connection=connection, headers=headers, cc=cc, reply_to=reply_to)
    alternative = MIMEMultipart('alternative')
    alternative.attach(MIMEText(body.encode('utf8'), 'plain', 'utf8'))
    alternative.attach(MIMEText(html_body.encode('utf8'), 'html', 'utf8'))
    related = MIMEMultipart('related')
    related.attach(alternative)
    for inline in html_inline_attachments:
        inline_attachment = msg._create_attachment(os.path.basename(inline), open(inline).read())
        inline_attachment.add_header('Content-Disposition', 'inline')
        inline_attachment.add_header('Content-ID', os.path.basename(inline))
        related.attach(inline_attachment)
    msg.attach(related)
    return msg

如果有人有更简单的解决方案,请告诉我:-)

【讨论】:

  • 这个图形表示帮助我更好地理解了结构。感谢那。使用 SMIME 时,我观察到 multipart/mixed 后面是 application/pkcs7-signature 部分和 multipart/signed 持有这两者。类似于:multipart/signed [ multipart/mixed, application/pkcs7-signature]
猜你喜欢
  • 2012-03-22
  • 1970-01-01
  • 2015-12-10
  • 2015-08-01
  • 2011-01-14
  • 2012-07-29
  • 2015-03-28
  • 2018-12-23
  • 1970-01-01
相关资源
最近更新 更多