python學習(21) smtp發送郵件


原文鏈接:

 https://www.jianshu.com/p/369ec15bfe22

本文介紹python發送郵件模塊smtplib以及相關MIME模塊。
smtplib用於生成郵件發送的代理,發送郵件前需要通過MIMEText構造郵件內容。

發送純文本郵件

下面是個發送純文本郵件的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import smtplib
from email.mime.text import MIMEText
msg_from='XXXXX@163.com'
passwd='XXXXX'
msg_to='XXXXX@qq.com'

subject="python郵件測試"
content="這是我使用python smtplib及email模塊發送的郵件"

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 ("發送成功")
except smtplib.SMTPException as e:
print ("發送失敗")
finally:
s.quit()

 

MIMEText實例化一個郵件對象,內容為content,對於郵件標題Subject,發件人From,以及收件人To
需要以字典形式指出,或者通過add_header(下文會給出)添加,否則對方看不到這些信息。
想要通過smtp發送郵件,需要打開指定郵箱的smtp協議,以及設置smtp授權密碼。我設置的是163郵箱的。


設置好密碼后,將上述代碼中的passwd改為你的密碼,msg_from改為你的郵箱。smtplib可以通過SMTP_SSL
發送,也可以采用普通形式直接初始化,對應的兩個參數分別是授權的smtp服務器地址和端口號,因為我
設置的是163的,所以使用smtp.163.com服務器地址,端口號和服務器地址讀者可以自己去查。通過生成的
smtp實例,一次調用login,sendemail就可以發送了。最后記得調用quit退出。
發送一封純文本郵件,看一下效果

我們發現發件人標題顯示的只有郵箱地址,沒有昵稱,可以采用parseaddr和formataddr對發件人信息完善。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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郵件測試"
content="這是我使用python smtplib及email模塊發送的郵件"

msg = MIMEText(content,'plain','utf-8')
msg['Subject'] = Header(subject,'utf-8').encode()
msg['From'] = _format_addr('戀戀風辰 <%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 ("發送成功")
except smtplib.SMTPException as e:
print ("發送失敗")
finally:
s.quit()

 

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

發送html郵件

發送html郵件和之前發送純文本類似,只需要將plain變為html,即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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郵件測試html'
content = '<html><body><h1>Hello</h1>' +\
'<p>send by <a href="http://www.python.org">Python</a>...</p>'

msg = MIMEText(content, 'html', 'utf-8')
msg['Subject'] = Header(subject, 'utf-8').encode()
msg['From'] = _format_addr('戀戀風辰 <%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('發送成功')
except smtplib.SMTPException as e:
print('發送失敗')
finally:
s.quit()

 

看看效果:

發送帶附件的郵件

發送帶附件的郵件,和之前不同,需要通過MIMEMultipart創建郵件實例,
然后將文本,附件等通過attach方法綁定到郵件實例上,然后一起發送。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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郵件測試附件'
content = '<html><body><h1>Hello</h1>' +\
'<p>send by <a href="http://www.python.org">Python</a>...</p>'

#附件郵件對象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風辰 <%s>' %msg_from)
msg['To'] = msg_to
msg['Subject'] = Header(subject, 'utf-8').encode()
#添加正文
text = MIMEText(content, 'html','utf-8')
msg.attach(text)
#添加附件就是創建一個MIMEBase對象,然后attach到msg上。
with open('./email.jpg','rb') as f:
#設置附件名字
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')
#讀取內容放入附件
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('發送成功')
except smtplib.SMTPException as e:
print('發送失敗')
finally:
s.quit()

 

MIMEMultipart創建郵件實例msg,將收件人,發件人,主題設置到msg上。
然后通過MIMEText創建html文本內容,調用msg.attach方法將文本內容綁定
到郵件上。同樣的道理,打開一個圖片,通過MIMEBase創建一個附件實例,
設置文件名,文件類型,綁定的id等等,最后通過set_payload加載到附件,
然后msg.attach綁定到郵件實例上。后面的發送流程和之前一樣。
看看效果:

發送帶圖片的html郵件

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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郵件測試附件'
content = '<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image1"><br>good!'

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

#添加附件就是創建一個MIMEBase對象,然后attach到msg上。
with open('./email.jpg','rb') as f:
#設置附件名字
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('發送成功')
except smtplib.SMTPException as e:
print('發送失敗')
finally:
s.quit()

 

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

Messge類的繼承和派生關系

1
2
3
4
5
6
7
 Message
+- MIMEBase
+- MIMEMultipart
+- MIMENonMultipart
+- MIMEMessage
+- MIMEText
+- MIMEImage

MIMEBase繼承於Message,MIMEMultipart繼承於MIMEBase。

用MIMEText發送多種附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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郵件測試附件'
content = '多種附件'

#附件郵件對象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風辰 <%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('發送成功')
except smtplib.SMTPException as e:
print('發送失敗')
finally:
s.quit()

大體原理和之前一樣,通過MIMEText可以實現多種附件的發送。
注意格式改為base64,編碼用utf-8,可以實現多種附件發送。
效果如下:

通過MIMEApplication發送多種附件

同樣可以通過MIMEApplication發送多種附件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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郵件測試附件'
content = '多種附件'

#附件郵件對象
msg = MIMEMultipart()
msg['From'] = _format_addr('戀戀風辰 <%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('發送成功')
except smtplib.SMTPException as e:
print('發送失敗')
finally:
s.quit()

 

效果和之前的一樣,這就是python中利用smtplib和MIME構造郵件發送的案例。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM