在我的网络应用程序中,我偶尔使用可重复使用的邮件程序应用程序发送电子邮件:
user - self.user
subject = ("My subject")
from = "me@mydomain.com"
message = render_to_string("welcomeEmail/welcome.eml", {
"user" : user,
})
send_mail(subject, message, from, [email], priority="high" )
我想发送一封包含嵌入图片的电子邮件,所以我尝试在邮件客户端制作邮件,查看源代码,并将其放入我的模板(welcome.eml),但我一直无法获得它在发送时在邮件客户端中正确呈现。
有没有人知道我使用内嵌图像创建mime编码邮件模板的简单方法,这些模板在发送时会正确呈现?
答案 0 :(得分:27)
<强>更新强>
非常感谢Saqib Ali在我回复近5年后重新提出这个旧问题。
我当时给出的指示不再有效。我怀疑Django在这几年中有一些改进,这意味着send_mail()
强制执行纯文本。无论您在内容中添加什么内容,它都将以纯文本形式发送。
最新Django documentation解释了send_mail()
实际上只是为了创建django.core.mail.EmailMessage
类的实例,然后在该实例上调用send()
。 EmailMessage
有一个关于body参数的注释,它解释了我们现在在2014年看到的结果:
body:正文。这应该是纯文本消息。
...稍后在文档中......
默认情况下,EmailMessage中body参数的MIME类型为“text / plain”。保持这一点是一种好习惯。
足够公平(我承认我没有花时间调查为什么2009年的指示有效 - 我在2009年测试过它们 - 或者当它发生变化时)。 Django确实提供了document和django.core.mail.EmailMultiAlternatives
类,以便更容易发送同一消息的纯文本和HTML表示。
这个问题的案例略有不同。我们不是要寻求替代本身的替代方案,而是将相关的部分附加到其中一个替代方案中。在HTML版本中(如果你有或省略了纯文本版本并不重要),我们想要嵌入一个图像数据部分。不是内容的替代视图,而是HTML正文中引用的相关内容。
仍然可以发送嵌入的图像,但我没有看到使用send_mail
执行此操作的简单方法。现在是时候省去便利功能并直接实例化EmailMessage
。
以下是对上一个示例的更新:
from django.core.mail import EmailMessage
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Load the image you want to send as bytes
img_data = open('logo.jpg', 'rb').read()
# Create a "related" message container that will hold the HTML
# message and the image. These are "related" (not "alternative")
# because they are different, unique parts of the HTML message,
# not alternative (html vs. plain text) views of the same content.
html_part = MIMEMultipart(_subtype='related')
# Create the body with HTML. Note that the image, since it is inline, is
# referenced with the URL cid:myimage... you should take care to make
# "myimage" unique
body = MIMEText('<p>Hello <img src="cid:myimage" /></p>', _subtype='html')
html_part.attach(body)
# Now create the MIME container for the image
img = MIMEImage(img_data, 'jpeg')
img.add_header('Content-Id', '<myimage>') # angle brackets are important
img.add_header("Content-Disposition", "inline", filename="myimage") # David Hess recommended this edit
html_part.attach(img)
# Configure and send an EmailMessage
# Note we are passing None for the body (the 2nd parameter). You could pass plain text
# to create an alternative part for this message
msg = EmailMessage('Subject Line', None, 'foo@bar.com', ['bar@foo.com'])
msg.attach(html_part) # Attach the raw MIMEBase descendant. This is a public method on EmailMessage
msg.send()
2009年的原始回复:
要发送包含嵌入图像的电子邮件,请使用python的内置电子邮件模块来构建MIME部分。
以下应该这样做:
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Load the image you want to send at bytes
img_data = open('logo.jpg', 'rb').read()
# Create a "related" message container that will hold the HTML
# message and the image
msg = MIMEMultipart(_subtype='related')
# Create the body with HTML. Note that the image, since it is inline, is
# referenced with the URL cid:myimage... you should take care to make
# "myimage" unique
body = MIMEText('<p>Hello <img src="cid:myimage" /></p>', _subtype='html')
msg.attach(body)
# Now create the MIME container for the image
img = MIMEImage(img_data, 'jpeg')
img.add_header('Content-Id', '<myimage>') # angle brackets are important
msg.attach(img)
send_mail(subject, msg.as_string(), from, [to], priority="high")
实际上,您可能希望将HTML与纯文本替换一起发送。在这种情况下,使用MIMEMultipart创建“相关”mimetype容器作为根。然后使用子类型“alternative”创建另一个MIMEMultipart,并将MIMEText(子类型html)和MIMEText(子类型plain)附加到替代部件。然后将图像附加到相关的根目录。
答案 1 :(得分:2)
我在Django 1.10上使用Jarret的配方遇到了麻烦 - 因为你可以通过各种方式附加MIME数据而获得MIME和编码错误。
这是一个简单的多部分事务模板,用于包含可在django 1.10上运行的嵌入式coupon_image
文件对象的电子邮件:
from django.core.mail import EmailMultiAlternatives
from email.mime.image import MIMEImage
def send_mail(coupon_image):
params = {'foo':'bar'} # create a template context
text_body = render_to_string('coupon_email.txt', params)
html_body = render_to_string('coupon_email.html', params)
img_data = coupon_image.read() #should be a file object, or ImageField
img = MIMEImage(img_data)
img.add_header('Content-ID', '<coupon_image>')
img.add_header('Content-Disposition', 'inline', filename="coupon_image")
email = EmailMultiAlternatives(
subject="Here's your coupon!",
body=text_body,
from_email='noreply@example.com',
to=['someone@example.com',]
)
email.attach_alternative(html_body, "text/html")
email.mixed_subtype = 'related'
email.attach(img)
email.send(fail_silently=False)