【问题标题】:Django: How to send HTML emails with embedded imagesDjango:如何发送带有嵌入图像的 HTML 电子邮件
【发布时间】:2011-04-16 19:25:58
【问题描述】:

如何发送带有嵌入图像的 HTML 电子邮件? HTML 应该如何链接到图像?图像应作为 MultiPart 电子邮件附件添加?

非常感谢任何示例。

【问题讨论】:

    标签: html django image email


    【解决方案1】:

    我已经尝试了下面的代码并且成功了。

    代码:

        msg = EmailMessage()
        
        # generic email headers
        msg['Subject'] = 'Welcome'
        msg['From'] = 'abc@gmail.com'
        recipients = ['abc@gmail.com']
        
        # set the plain text body
        msg.set_content('This is a plain text body.')
        
        # now create a Content-ID for the image
        image_cid = make_msgid(domain='')
        # if `domain` argument isn't provided, it will
        # use your computer's name
        
        # set an alternative html body
        msg.add_alternative("""\
            <html>
           <body>
              <table border='0' cellpadding='1' cellspacing='0' width='800'>
                 <tbody>
                    <tr>
                       <td height='506'>
                          <table border='0' cellpadding='0' cellspacing='0' width='600'>
                             <tbody>
                                <tr>
                                   <td valign='top'>
                                      <img height='190' src="cid:{image_cid}" width='800'  tabindex='0'>
                                   </td>
                                </tr>
                                <tr>
                                   <td height='306' valign='top'>
                                      <table cellpadding='0' cellspacing='20' width='800'>
                                         <tbody>
                                            <tr>
                                               <td align='left' height='804' style='font-family:arial,helvetica,sans-serif;font-size:13px' valign='top'>
                                                  Hi {name},<br><br>
                                                  Welcome!
                                               </td>
                                            </tr>
                                         </tbody>
                                      </table>
                                   </td>
                                </tr>
                             </tbody>
                          </table>
                       </td>
                    </tr>
                 </tbody>
              </table>
           </body>
        </html>
        """.format(image_cid=image_cid[1:-1],name='ABC'), subtype='html')
        # image_cid looks like <long.random.number@xyz.com>
        # to use it as the img src, we don't need `<` or `>`
        # so we use [1:-1] to strip them off
        
        # now open the image and attach it to the email
        with open('/path/image.jpg', 'rb') as img:
            # know the Content-Type of the image
            maintype, subtype = mimetypes.guess_type(img.name)[0].split('/')
        
            # attach it
            msg.get_payload()[1].add_related(img.read(),
                                             maintype=maintype,
                                             subtype=subtype,
                                             cid=image_cid)
        server = smtplib.SMTP(host=<hostname>, port=25)
        
        server.starttls()
        # send the message via the server.
        server.sendmail(msg['From'], recipients, msg.as_string())
        
        server.quit()
    

    【讨论】:

    • make_msgid(domain='') 函数里面是什么你是如何创建Content-ID 的。并且您没有在代码中添加导入。你能提供更高效的代码吗?
    【解决方案2】:

    http://djangosnippets.org/snippets/285/

    你必须使用 MultiPart 和 cid:。发送带有图像的 html 邮件几乎总是一个坏主意。它为您的邮件和 smtp 服务器提供垃圾邮件点...

    这里是更好的例子:https://djangosnippets.org/snippets/3001/

    【讨论】:

    • 这个好像用的不是django的邮件系统,而是python的smtplib。
    【解决方案3】:

    如果您想发送带有图像作为附件的电子邮件(在我的情况下,它是在保存后直接从表单中捕获的图像),您可以使用以下代码作为示例:

    #forms.py
    
    from django import forms
    from django.core.mail import EmailMessage
    from email.mime.image import MIMEImage
    
    
    class MyForm(forms.Form):
        #...
        def save(self, *args, **kwargs):
            # In next line we save all data from form as usual.
            super(MyForm, self).save(*args, **kwargs)
            #...
            # Your additional post_save login can be here.
            #...
            # In my case name of field was an "image".
            image = self.cleaned_data.get('image', None)
            # Then we create an "EmailMessage" object as usual.
            msg = EmailMessage(
                'Hello',
                'Body goes here',
                'from@example.com',
                ['to1@example.com', 'to2@example.com'],
                ['bcc@example.com'],
                reply_to=['another@example.com'],
                headers={'Message-ID': 'foo'},
            )
            # Then set "html" as default content subtype.
            msg.content_subtype = "html"
            # If there is an image, let's attach it to message.
            if image:
                mime_image = MIMEImage(image.read())
                mime_image.add_header('Content-ID', '<image>')
                msg.attach(mime_image)
            # Then we send message.
            msg.send()
    

    【讨论】:

      【解决方案4】:

      我实现了 op 要求使用 django 的邮件系统。好处是它将使用 django 设置进行邮件发送(包括用于测试的不同子系统等。我在开发过程中也使用 mailhogs)。它的水平也相当高:

      from django.conf import settings
      from django.core.mail import EmailMultiAlternatives
      
      
      message = EmailMultiAlternatives(
          subject=subject,
          body=body_text,
          from_email=settings.DEFAULT_FROM_EMAIL,
          to=recipients,
          **kwargs
      )
      message.mixed_subtype = 'related'
      message.attach_alternative(body_html, "text/html")
      message.attach(logo_data())
      
      message.send(fail_silently=False)
      

      logo_data 是一个附加标志的辅助函数(在这种情况下我想附加的图像):

      from email.mime.image import MIMEImage
      
      from django.contrib.staticfiles import finders
      
      
      @lru_cache()
      def logo_data():
          with open(finders.find('emails/logo.png'), 'rb') as f:
              logo_data = f.read()
          logo = MIMEImage(logo_data)
          logo.add_header('Content-ID', '<logo>')
          return logo
      

      【讨论】:

      • 嘿,谢谢! logo_data 函数确实解释了一个技巧。可惜 Django 的附加函数没有添加可选的标头。
      • 这是发送内嵌图像电子邮件的最短和最佳方式。想特别确认一下使用@lru_cache是很明智的,但是你忘了在表头加上from functools import lru_cache。另外,对于这个答案的追随者——这里是 HTML 模板:body_html = """&lt;html&gt;&lt;img src="cid:logo" alt="logo image"&gt;&lt;/html&gt;"""
      【解决方案5】:

      请记住,django 只为标准 smtplib 提供 wrappers - 我不知道它是否会有所帮助,但请尝试查看以下示例:http://code.activestate.com/recipes/473810-send-an-html-email-with-embedded-image-and-plain-t/

      所以我猜你可以使用EmailMessage 的标头值来定义这个'image1' - 消息标头是值的字典,所以只需添加类似{'Content-ID': '&lt;image1&gt;'} 的内容。

      然后使用attach() 将文件附加到您的电子邮件中。之后,您可以使用代码生成这样的 html 消息:

      html_content = '<b>Some HTML text</b> and an image: <img src="cid:image1">'
      

      【讨论】:

        猜你喜欢
        • 2013-11-11
        • 2012-04-07
        • 2014-01-25
        • 1970-01-01
        • 2021-10-31
        • 2012-07-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多