簡體   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