python學(xué)習(xí)(21)smtp發(fā)送郵件

本文介紹python發(fā)送郵件模塊smtplib以及相關(guān)MIME模塊。
smtplib用于生成郵件發(fā)送的代理,發(fā)送郵件前需要通過(guò)MIMEText構(gòu)造郵件內(nèi)容。

發(fā)送純文本郵件

下面是個(gè)發(fā)送純文本郵件的例子。

import smtplib
from email.mime.text import MIMEText
msg_from='XXXXX@163.com'                                 
passwd='XXXXX'                                  
msg_to='XXXXX@qq.com'                                  
                            
subject="python郵件測(cè)試"                                       
content="這是我使用python smtplib及email模塊發(fā)送的郵件"

msg = MIMEText(content)
msg['Subject'] = subject
msg['From'] = msg_from
msg['To'] = msg_to
try:
    #s = smtplib.SMTP_SSL("smtp.163.com",465)
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, msg_to, msg.as_string())
    print ("發(fā)送成功")
except smtplib.SMTPException as e:
    print ("發(fā)送失敗")
finally:
    s.quit()

MIMEText實(shí)例化一個(gè)郵件對(duì)象,內(nèi)容為content,對(duì)于郵件標(biāo)題Subject,發(fā)件人From,以及收件人To需要以字典形式指出,或者通過(guò)add_header(下文會(huì)給出)添加,否則對(duì)方看不到這些信息。想要通過(guò)smtp發(fā)送郵件,需要打開(kāi)指定郵箱的smtp協(xié)議,以及設(shè)置smtp授權(quán)密碼。我設(shè)置的是163郵箱的。


1.png
2.png

設(shè)置好密碼后,將上述代碼中的passwd改為你的密碼,msg_from改為你的郵箱。smtplib可以通過(guò)SMTP_SSL發(fā)送,也可以采用普通形式直接初始化,對(duì)應(yīng)的兩個(gè)參數(shù)分別是授權(quán)的smtp服務(wù)器地址和端口號(hào),因?yàn)槲以O(shè)置的是163的,所以使用smtp.163.com服務(wù)器地址,端口號(hào)和服務(wù)器地址讀者可以自己去查。通過(guò)生成的smtp實(shí)例,一次調(diào)用login,sendemail就可以發(fā)送了。最后記得調(diào)用quit退出。發(fā)送一封純文本郵件,看一下效果


3.png

我們發(fā)現(xiàn)發(fā)件人標(biāo)題顯示的只有郵箱地址,沒(méi)有昵稱,可以采用parseaddr和formataddr對(duì)發(fā)件人信息完善。

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr

msg_from='XXXXX@163.com'                                 
passwd='XXXXX'                                  
msg_to='XXXXX@qq.com'
receivers = ['XXXXX@qq.com']                                
                            
subject="python郵件測(cè)試"                                       
content="這是我使用python smtplib及email模塊發(fā)送的郵件"

msg = MIMEText(content,'plain','utf-8')
msg['Subject'] = Header(subject,'utf-8').encode()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to

try:
    #s = smtplib.SMTP_SSL("smtp.163.com",465)
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print ("發(fā)送成功")
except smtplib.SMTPException as e:
    print ("發(fā)送失敗")
finally:
    s.quit()

這樣可以看到發(fā)件人的昵稱了。我設(shè)置的是戀戀風(fēng)辰。Header函數(shù)的作用是防止中文亂碼。
Header對(duì)字符串按照utf-8方式編碼。MIMEText中參數(shù)plain表示純文本,utf-8表示純文本的編碼方式。


4.png

發(fā)送html郵件

發(fā)送html郵件和之前發(fā)送純文本類(lèi)似,只需要將plain變?yōu)閔tml,即可。

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
msg_from = 'XXXXXX@163.com'
passwd = 'XXXXX'
msg_to='XXXXXX@qq.com'
receivers = ['XXXXXX@qq.com']
subject = 'python郵件測(cè)試html'
content = '<html><body><h1>Hello</h1>' +\
    '<p>send by <a 

msg = MIMEText(content, 'html', 'utf-8')
msg['Subject'] = Header(subject, 'utf-8').encode()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to

try:
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print('發(fā)送成功')
except smtplib.SMTPException as e:
    print('發(fā)送失敗')
finally:
    s.quit()

看看效果:


5.png

發(fā)送帶附件的郵件

發(fā)送帶附件的郵件,和之前不同,需要通過(guò)MIMEMultipart創(chuàng)建郵件實(shí)例,
然后將文本,附件等通過(guò)attach方法綁定到郵件實(shí)例上,然后一起發(fā)送。

import smtplib
import email
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart   
from email.utils import parseaddr, formataddr
from email.mime.base import MIMEBase


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

msg_from = 'XXXXX@163.com'
passwd = 'XXXXX'
msg_to='XXXXXX@qq.com'
receivers = ['XXXX@qq.com']
subject = 'python郵件測(cè)試附件'
content = '<html><body><h1>Hello</h1>' +\
    '<p>send by <a 

#附件郵件對(duì)象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to
msg['Subject'] = Header(subject, 'utf-8').encode()
#添加正文
text = MIMEText(content, 'html','utf-8')
msg.attach(text)
#添加附件就是創(chuàng)建一個(gè)MIMEBase對(duì)象,然后attach到msg上。
with open('./email.jpg','rb') as f:
    #設(shè)置附件名字
    mime = MIMEBase('image', 'jpg', filename='text.jpg')
    #加上頭信息
    mime.add_header('Content-Disposition','attachment',filename='test.jpg')
    mime.add_header('Content-ID','<0>')
    mime.add_header('X-Attachment-Id','0')
    #讀取內(nèi)容放入附件
    mime.set_payload(f.read())
    #用Base64編碼
    email.encoders.encode_base64(mime)
    #添加到MIMEMultipart中
    msg.attach(mime)

try:
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print('發(fā)送成功')
except smtplib.SMTPException as e:
    print('發(fā)送失敗')
finally:
    s.quit()

MIMEMultipart創(chuàng)建郵件實(shí)例msg,將收件人,發(fā)件人,主題設(shè)置到msg上。然后通過(guò)MIMEText創(chuàng)建html文本內(nèi)容,調(diào)用msg.attach方法將文本內(nèi)容綁定到郵件上。同樣的道理,打開(kāi)一個(gè)圖片,通過(guò)MIMEBase創(chuàng)建一個(gè)附件實(shí)例,設(shè)置文件名,
文件類(lèi)型,綁定的id等等,最后通過(guò)set_payload加載到附件,然后msg.attach綁定到郵件實(shí)例上。后面的發(fā)送流程和之前
一樣。
看看效果:


6.png

發(fā)送帶圖片的html郵件

想要在html中添加圖片,并且在郵件正文中顯示,只需要在html文本中引用
圖片id即可。

import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart   
from email.utils import parseaddr, formataddr
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

msg_from = 'XXXXXXXXXXXX@163.com'
passwd = 'XXXXX'
msg_to='XXXXXXXXX@qq.com'
receivers = ['XXXXXXXXXX@qq.com']
subject = 'python郵件測(cè)試附件'
content = '<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image1"><br>good!'

#附件郵件對(duì)象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to
msg['Subject'] = Header(subject, 'utf-8').encode()
#添加正文
text = MIMEText(content, 'html','utf-8')
msg.attach(text)

#添加附件就是創(chuàng)建一個(gè)MIMEBase對(duì)象,然后attach到msg上。
with open('./email.jpg','rb') as f:
    #設(shè)置附件名字
    mime = MIMEImage(f.read())
    #加上頭信息
    mime.add_header('Content-Disposition','attachment',filename='test.jpg')
    mime.add_header('Content-ID','`<image1>`')
   
    #添加到MIMEMultipart中
    msg.attach(mime)

try:
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print('發(fā)送成功')
except smtplib.SMTPException as e:
    print('發(fā)送失敗')
finally:
    s.quit()

mime.add_header('Content-ID','<image1>') 設(shè)置圖片id為image1,
在html中引用image1就可以在郵件中文中顯示圖片了。
通過(guò)<img src="cid:image1">方式進(jìn)行引用。

Messge類(lèi)的繼承和派生關(guān)系

Message
+- MIMEBase
  +- MIMEMultipart
  +- MIMENonMultipart
     +- MIMEMessage
     +- MIMEText
     +- MIMEImage

MIMEBase繼承于Message,MIMEMultipart繼承于MIMEBase。

用MIMEText發(fā)送多種附件

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr, formataddr
import os

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

msg_from = 'XXXXXXXXX@163.com'
passwd = 'XXXXXXXXXXX'
msg_to='XXXXXXXXX@qq.com'
receivers = ['XXXXXXXXXXX@qq.com']
subject = 'python郵件測(cè)試附件'
content = '多種附件'

#附件郵件對(duì)象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to
msg['Subject'] = Header(subject, 'utf-8').encode()
#添加正文
text = MIMEText(content, 'html','utf-8')
msg.attach(text)

os.chdir('./res')    
dir = os.getcwd()

for fn in os.listdir(dir):
    print(fn)
    with open(fn,'rb') as f:
        mime = MIMEText(f.read(), 'base64', 'utf-8')
        mime.add_header('Content-Disposition','attachment',filename = fn)
        mime.add_header('Content-Type', 'application/octet-stream')
        msg.attach(mime)

try:
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print('發(fā)送成功')
except smtplib.SMTPException as e:
    print('發(fā)送失敗')
finally:
    s.quit()

大體原理和之前一樣,通過(guò)MIMEText可以實(shí)現(xiàn)多種附件的發(fā)送。
注意格式改為base64,編碼用utf-8,可以實(shí)現(xiàn)多種附件發(fā)送。
效果如下:


7.png

通過(guò)MIMEApplication發(fā)送多種附件

同樣可以通過(guò)MIMEApplication發(fā)送多種附件。

import smtplib
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr, formataddr
import os

def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))

msg_from = 'xxxxxxxxx@163.com'
passwd = 'xxxxxxxxxx'
msg_to='xxxxxxxxxxx@qq.com'
receivers = ['xxxxxxxxx@qq.com']
subject = 'python郵件測(cè)試附件'
content = '多種附件'

#附件郵件對(duì)象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風(fēng)辰 <%s>' %msg_from)
msg['To'] = msg_to
msg['Subject'] = Header(subject, 'utf-8').encode()
#添加正文
text = MIMEText(content, 'html','utf-8')
msg.attach(text)

os.chdir('./res')    
dir = os.getcwd()

for fn in os.listdir(dir):
    print(fn)
    with open(fn,'rb') as f:
        mime = MIMEApplication(f.read())
        mime.add_header('Content-Disposition','attachment',filename = fn)
        mime.add_header('Content-Type', 'application/octet-stream')
        msg.attach(mime)

try:
    s = smtplib.SMTP("smtp.163.com",25)
    s.login(msg_from, passwd)
    s.sendmail(msg_from, receivers, msg.as_string())
    print('發(fā)送成功')
except smtplib.SMTPException as e:
    print('發(fā)送失敗')
finally:
    s.quit()

效果和之前的一樣,這就是python中利用smtplib和MIME構(gòu)造郵件發(fā)送的案例。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容