Django EmailMultiAlternatives中嵌入HTML图像

6 投票
2 回答
3252 浏览
提问于 2025-04-16 19:57

我正在尝试发送带有HTML和嵌入图片的电子邮件。发送邮件的功能正常,邮件中也附加了图片,但在HTML中却没有显示出图片(内联显示)。我在视图中使用了Content:ID,在模板中使用了cid,但都没有成功 :(. 我尝试了很多方法和解决方案,但都没有用,请帮帮我!这是我的代码:

html_content = render_to_string('newsletters/newsletter_template.html', vars)
text_content = strip_tags(html_content) 

to = 'myemail@gmail.com'


msg = EmailMultiAlternatives(self.subject, text_content, settings.STAFF_FROM_EMAIL, [to])
msg.attach_alternative(html_content, "text/html")

image_file = open('../media/images/banner_admin.gif', 'rb')
msg_image = MIMEImage(image_file.read())
image_file.close()

msg_image.add_header('Content-ID', '<image1>')
msg.attach(msg_image)

msg.send()

模板文件:

<div style="border:2px solid #CCCCCC; width:900px; font-size:10px; padding:5px;">
    <div style="margin-bottom: 10px;"><img src="cid:image1" /></div>
    <div style="">{{body|linebreaks}}</div>
</div>

请告诉我这里是否有什么我遗漏的...

2 个回答

0

这个内容是从一个博客上摘录的代码示例

下面是HTML模板代码

<!-- BODY -->
<table class="body-wrap">
    <tr>
        <td></td>
        <td class="container" bgcolor="#FFFFFF">
             <div class="content">
                <table>
                    <tr>
                        <td>
                            {% for view in views %}
                                <h3>{{ view }}</h3>
                                <p><img src="cid:{{ view.image_filename }}" /></p>
                                {% if not forloop.last %}<p>&nbsp;</p>{% endif %}
                            {% endfor %}
                        </td>
                    </tr>
                </table>
            </div>
        </td>
        <td></td>
    </tr>
</table><!-- /BODY -->
Image table will be rendered as such:

<img src="cid:20161010_dailykpisnapshot_OCuZ4O4.png">
Views.py
import os
from email.mime.image import MIMEImage

from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string


rendered_report = RenderedReport.objects.get(pk=1)
views = rendered_report.rendered_views.all()

context = {'views': views}

html_content = render_to_string('reports/email.html', context=context).strip()

subject = 'HTML Email'
recipients = ['john.doe@test.com']
reply_to = ['noreply@test.com']

msg = EmailMultiAlternatives(subject, html_content, config.formatted_email_from, to, reply_to=reply_to)
msg.content_subtype = 'html'  # Main content is text/html
msg.mixed_subtype = 'related'  # This is critical, otherwise images will be displayed as attachments!

for view in views:
    # Create an inline attachment
    image = MIMEImage(view.png.read())
    image.add_header('Content-ID', '<{}>'.format(view.image_filename))
    msg.attach(image)

    # Create a regular attachment with a CSV file
    if view.csv:
        filename = os.path.basename(view.csv.name)
        msg.attach(filename, view.csv.read(), 'text/csv')

    # Create a regular attachment with a PDF file
    if view.pdf:
        filename = os.path.basename(view.pdf.name)
        msg.attach(filename, view.pdf.read(), 'application/pdf')

msg.send()

电子邮件的头部信息看起来像这样:

内容类型:image/png
内容处置:inline(内联)
内容传输编码:base64
内容ID:<20161010_dailykpisnapshot_OCuZ4O4.png>

在实际应用中,可能更好地直接引用你在S3上的图片。这样的话,在views.py里就不需要做其他的后端工作,只需把目标图片的S3网址放进去就可以了。

0

要在邮件正文中嵌入PNG文件,可以试试这段代码:

for f in ['img1.png', 'img2.png']:
    fp = open(os.path.join(os.path.dirname(__file__), f), 'rb')
    msg_img = MIMEImage(fp.read())
    fp.close()
    msg_img.add_header('Content-ID', '<{}>'.format(f))
    msg.attach(msg_img)

msg.send()

现在你可以在你的模板中使用 <img src="cid:img1.png">。这样做的结果是,邮件客户端会在邮件中显示这个图片,而不是把它当作附件。

撰写回答