【问题标题】:Sending Multipart html emails which contain embedded images发送包含嵌入图像的多部分 html 电子邮件
【发布时间】:2016-08-23 21:06:10
【问题描述】:

我一直在使用 python 中的电子邮件模块,但我希望能够知道如何嵌入包含在 html 中的图像。

例如,如果身体是这样的

<img src="../path/image.png"></img>

我想将 image.png 嵌入到电子邮件中,src 属性应替换为 content-id。有人知道怎么做吗?

【问题讨论】:

    标签: python email mime attachment multipart


    【解决方案1】:

    我意识到 SMTP 和电子邮件库的某些事情是多么痛苦,我想我必须对它做点什么。我制作了a library,这使得将图像嵌入 HTML 变得更容易:

    from redmail import EmailSender
    email = EmailSender(host="<SMTP HOST>", port=0)
    
    email.send(
        sender="me@example.com",
        receivers=["you@example.com"]
        subject="An email with image",
        html="""
            <h1>Look at this:</h1>
            {{ my_image }}
        """, 
        body_images={
            "my_image": "path/to/image.png"
        }
    )
    

    很抱歉升职,但我认为这非常棒。如果您的图像采用这些格式,您可以将图像提供为 Matplotlib Figure、Pillow Imagebytes。它使用 Jinja 进行模板化。

    如果需要控制图片的大小,也可以这样做:

    email.send(
        sender="me@example.com",
        receivers=["you@example.com"]
        subject="An email with image",
        html="""
            <h1>Look at this:</h1>
            <img src="{{ my_image.src }}" width=200 height=300>
        """, 
        body_images={
            "my_image": "path/to/image.png"
        }
    )
    

    你可以直接 pip 安装它:

    pip install redmail
    

    它(希望)是您发送电子邮件所需的一切(还有更多),并且经过了很好的测试。我还写了大量的文档:https://red-mail.readthedocs.io/en/latest/,源代码在here

    【讨论】:

      【解决方案2】:

      代码工作

          att = MIMEImage(imgData)
          att.add_header('Content-ID', f'<image{i}.{imgType}>')
          att.add_header('X-Attachment-Id', f'image{i}.{imgType}')
          att['Content-Disposition'] = f'inline; filename=image{i}.{imgType}'
          msg.attach(att)
      

      【讨论】:

      • 嗨!感谢分享答案。如果您还要添加一些关于上面代码的解释,这可能会很有用。同样在 OP 的代码中,我没有看到 imgType 变量定义,因此您的代码会引发异常。
      【解决方案3】:

      适用于 Python 3.4 及更高版本。

      公认的答案非常好,但仅适用于较旧的 Python 版本(2.x 和 3.3)。我认为它需要更新。

      以下是在较新的 Python 版本(3.4 及更高版本)中执行此操作的方法:

      from email.message import EmailMessage
      from email.utils import make_msgid
      import mimetypes
      
      msg = EmailMessage()
      
      # generic email headers
      msg['Subject'] = 'Hello there'
      msg['From'] = 'ABCD <abcd@xyz.com>'
      msg['To'] = 'PQRS <pqrs@xyz.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='xyz.com')
      # if `domain` argument isn't provided, it will 
      # use your computer's name
      
      # set an alternative html body
      msg.add_alternative("""\
      <html>
          <body>
              <p>This is an HTML body.<br>
                 It also has an image.
              </p>
              <img src="cid:{image_cid}">
          </body>
      </html>
      """.format(image_cid=image_cid[1:-1]), 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/to/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)
      
      
      # the message is ready now
      # you can write it to a file
      # or send it using smtplib
      

      【讨论】:

      【解决方案4】:

      这是我找到的一个例子。

      Recipe 473810: Send an HTML email with embedded image and plain text alternate:

      HTML 是这些人的首选方法 希望发送带有富文本的电子邮件, 布局和图形。通常是 可取的嵌入图形 消息,以便收件人可以显示 直接发消息,不加赘述 下载。

      某些邮件代理不支持 HTML 或 他们的用户更喜欢收到简单的 短信。 HTML 的发件人 消息应包含纯文本 消息作为这些的替代 用户。

      这个食谱发送一个简短的 HTML 消息 具有单个嵌入图像和 备用纯文本消息。

      # Send an HTML email with an embedded image and a plain text message for
      # email clients that don't want to display the HTML.
      
      from email.MIMEMultipart import MIMEMultipart
      from email.MIMEText import MIMEText
      from email.MIMEImage import MIMEImage
      
      # Define these once; use them twice!
      strFrom = 'from@example.com'
      strTo = 'to@example.com'
      
      # Create the root message and fill in the from, to, and subject headers
      msgRoot = MIMEMultipart('related')
      msgRoot['Subject'] = 'test message'
      msgRoot['From'] = strFrom
      msgRoot['To'] = strTo
      msgRoot.preamble = 'This is a multi-part message in MIME format.'
      
      # Encapsulate the plain and HTML versions of the message body in an
      # 'alternative' part, so message agents can decide which they want to display.
      msgAlternative = MIMEMultipart('alternative')
      msgRoot.attach(msgAlternative)
      
      msgText = MIMEText('This is the alternative plain text message.')
      msgAlternative.attach(msgText)
      
      # We reference the image in the IMG SRC attribute by the ID we give it below
      msgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image1"><br>Nifty!', 'html')
      msgAlternative.attach(msgText)
      
      # This example assumes the image is in the current directory
      fp = open('test.jpg', 'rb')
      msgImage = MIMEImage(fp.read())
      fp.close()
      
      # Define the image's ID as referenced above
      msgImage.add_header('Content-ID', '<image1>')
      msgRoot.attach(msgImage)
      
      # Send the email (this example assumes SMTP authentication is required)
      import smtplib
      smtp = smtplib.SMTP()
      smtp.connect('smtp.example.com')
      smtp.login('exampleuser', 'examplepass')
      smtp.sendmail(strFrom, strTo, msgRoot.as_string())
      smtp.quit()
      

      【讨论】:

      • 非常感谢,我尝试了很多解决方案,这是一个完美的解决方案!
      • @Andrew Hare:有两个多部分视图(两个 msgText 实例)。我没有看到为每个指定的内容类型。接收系统如何知道为 Html 渲染哪个?
      • 我为第二个 msgText 实例添加了 msgText.replace_header('Content-Type','text/html')。
      • Ftr:MIMEText constructor 的第二个参数是子类型(默认为plain,第二个实例为'html')。
      • 它在 python 3.7.2 中对我有用,但我必须以不同的方式编写导入:from email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipart
      猜你喜欢
      • 2017-03-14
      • 1970-01-01
      • 2018-05-05
      • 1970-01-01
      • 2020-05-13
      • 2014-12-09
      • 2012-04-07
      • 2011-04-16
      相关资源
      最近更新 更多