繁体   English   中英

如何发送使用 PIL/pillow 创建的嵌入图像作为电子邮件(Python 3)

[英]How to send embedded image created using PIL/pillow as email (Python 3)

我正在创建我想嵌入到电子邮件中的图像。 我无法弄清楚如何将图像创建为二进制并传递到 MIMEImage。 下面是我的代码,当我尝试读取图像对象时出现错误 - 错误是“AttributeError:'NoneType'对象没有属性'read'”。

image=Image.new("RGBA",(300,400),(255,255,255))
image_base=ImageDraw.Draw(image)
emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
imgObj=emailed_password_pic.read()
msg=MIMEMultipart()
html="""<p>Please finish registration <br/><img src="cid:image.jpg"></p>"""
img_file='image.jpg'
msgText = MIMEText(html,'html')
msgImg=MIMEImage(imgObj)
msgImg.add_header('Content-ID',img_file)
msg.attach(msgImg)
msg.attach(msgText)

如果您查看第 4 行 - 我正在尝试读取图像,以便将其传递给 MIMEImage。 显然,图像需要作为二进制读取。 但是,我不知道如何将其转换为二进制以便 .read() 可以处理它。

FOLLOW-UP我编辑从每建议jsbueno代码-非常感谢你!!!:

  emailed_password=os.urandom(16)
  image=Image.new("RGBA",(300,400),(255,255,255))
  image_base=ImageDraw.Draw(image)
  emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
  stream_bytes=BytesIO()
  image.save(stream_bytes,format='png')
  stream_bytes.seek(0)
  #in_memory_file=stream_bytes.getvalue()
  #imgObj=in_memory_file.read()
  imgObj=stream_bytes.read()
  msg=MIMEMultipart()
  sender='xxx@abc.com'
  receiver='jjjj@gmail.com'
  subject_header='Please use code provided in this e-mail to confirm your subscription.'
  msg["To"]=receiver
  msg["From"]=sender
  msg["Subject"]=subject_header
  html="""<p>Please finish registration by loging into your account and typing in code from this e-mail.<br/><img src="cid:image.png"></p>"""
  img_file='image.png'
  msgText=MIMEText(html,'html')
  msgImg=MIMEImage(imgObj) #Is mistake here?
  msgImg.add_header('Content-ID',img_file)
  msg.attach(msgImg)
  msg.attach(msgText)
  smtpObj=smtplib.SMTP('smtp.mandrillapp.com', 587)
  smtpObj.login(userName,userPassword)
  smtpObj.sendmail(sender,receiver,msg.as_string())

我现在没有收到错误,但电子邮件中没有图像。 我对图像在 html/email 部分中附加和相关的方式感到困惑。 任何帮助表示赞赏!

更新:此代码实际上有效 - 我的 PC 上的代码中只是有轻微的错字。

在使用 PIL 以及图像应该采用什么格式才能合并到电子邮件中时,存在一些概念性错误。

在 PIL 中:ImageDraw 类操作就地,不像 Image 类调用,它通常在每次操作后返回一个新图像。 在您的代码中,这意味着对image_base.text的调用实际上正在更改位于您的image变量中的对象的像素数据。 这个调用实际上返回None并且上面的代码应该在下一行引发一个错误,如“AttributeError: None object does not have attribute 'read'”。

过去(也就是说,您应该从image变量中获取数据以将其附加到电子邮件中)出现了第二个问题:出于显而易见的原因,PIL 在内存中具有未压缩的原始像素数据格式的图像。 在电子邮件中附加图像时,我们通常希望图像整齐地打包在文件中 - PNG 或 JPG 格式通常更好,具体取决于意图 - 让我们继续使用 .PNG。 因此,您必须使用 PIL 创建文件数据,并附加文件数据(即包含 PNG 文件的数据,包括标题、元数据和压缩形式的实际像素数据)。 否则,您将在电子邮件中放入一堆(未压缩的)像素数据,接收方无法将这些数据重新组合成图像(即使他将数据视为像素,原始像素数据也不包含)图像形状如此-)

您有两种选择:要么在内存中生成文件字节,要么将它们写入磁盘中的实际文件,然后重新读取该文件以进行附加。 第二种形式更容易遵循。 第一个更有效并且“做正确的事” - 所以让我们保持它:

from io import BytesIO
# In Python 2.x:
# from StringIO import StringIO.StringIO as BytesIO

image=Image.new("RGBA",(300,400),(255,255,255))
image_base=ImageDraw.Draw(image)
# this actually modifies "image"
emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
stream = BytesIO()
image.save(stream, format="png")
stream.seek(0)
imgObj=stream.read()
...

(注意:我没有检查你的代码中处理邮件和 mime 的部分 - 如果你正确使用它,它现在应该可以工作)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM