1. 程式人生 > >python介面自動化(三十二)--Python傳送郵件(常見四種郵件內容)番外篇——上(詳解)

python介面自動化(三十二)--Python傳送郵件(常見四種郵件內容)番外篇——上(詳解)

簡介

  本篇文章與前邊沒有多大關聯,就是對前邊有關發郵件的總結和梳理。在寫指令碼時,放到後臺執行,想知道執行情況,會通過郵件、SMS(簡訊)、飛信、微信等方式通知管理員,用的最多的是郵件。在linux下,Shell指令碼傳送郵件告警是件很簡單的事,有現成的郵

件服務軟體或者呼叫運營商郵箱伺服器。

  對於Python來說,需要編寫指令碼呼叫郵件伺服器來發送郵件,使用的協議是SMTP。接收郵件,使用的協議是POP3和IMAP。我想有必要說明下 ,POP3和IMAP的區別:POP3在客戶端郵箱中所做的操作不會反饋到郵箱伺服器,比如刪除一封郵件,郵箱伺服器並不

會刪除。IMAP則會反饋到郵箱伺服器,會做相應的操作。

  Python分別提供了收發郵件的庫,smtplib、poplib和imaplib。

  本章主要講解如果使用smtplib庫實現傳送各種形式的郵件內容。在smtplib庫中,主要主要用smtplib.SMTP()類,用於連線SMTP伺服器,傳送郵件。

這個類有幾個常用的方法:

方法

描述

SMTP.set_debuglevel(level) 設定輸出debug除錯資訊,預設不輸出
SMTP.docmd(cmd[, argstring]) 傳送一個命令到SMTP伺服器
SMTP.connect([host[, port]]) 連線到指定的SMTP伺服器
SMTP.helo([hostname]) 使用helo指令向SMTP伺服器確認你的身份
SMTP.ehlo(hostname) 使用ehlo指令像ESMTP(SMTP擴充套件)確認你的身份
SMTP.ehlo_or_helo_if_needed() 如果在以前的會話連線中沒有提供ehlo或者helo指令,這個方法會呼叫ehlo()或helo()
SMTP.has_extn(name) 判斷指定名稱是否在SMTP伺服器上
SMTP.verify(address) 判斷郵件地址是否在SMTP伺服器上
SMTP.starttls([keyfile[, certfile]]) 使SMTP連線執行在TLS模式,所有的SMTP指令都會被加密
SMTP.login(user, password) 登入SMTP伺服器
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[])

傳送郵件

from_addr:郵件發件人

to_addrs:郵件收件人

msg:傳送訊息

SMTP.quit() 關閉SMTP會話
SMTP.close() 關閉SMTP伺服器連線

看下官方給的示例:

我們根據示例給自己發一個郵件測試下:

我這裡測試使用本地的SMTP伺服器,也就是要裝一個支援SMTP協議的服務,比如sendmail、postfix等。

CentOS安裝sendmail:yum install sendmail

1 >>> import smtplib
2 >>> s = smtplib.SMTP("localhost")
3 >>> tolist = ["[email protected]", "[email protected]"]
4 >>> msg = '''\
5 ... From: [email protected]
6 ... Subject: test
7 ... This is a test '''
8 >>> s.sendmail("[email protected]", tolist, msg)
9 {}

進入騰訊和網易收件人郵箱,就能看到剛發的測試郵件,一般都被郵箱伺服器過濾成垃圾郵件,所以收件箱沒有,你要去垃圾箱看看。

可以看到,多個收件人可以放到一個列表中進行群發。msg物件裡From表示發件人,Subject是郵件標題,換行後輸入的是郵件內容。

1.1 Python傳送郵件並抄送

 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 import smtplib
 4 def sendMail(body):
 5     smtp_server = 'smtp.163.com'
 6     from_mail = '[email protected]'
 7     mail_pass = 'xxx'
 8     to_mail = ['[email protected]', '[email protected]']
 9     cc_mail = ['[email protected]']
10     from_name = 'monitor' 
11     subject = u'監控'.encode('gbk')   # 以gbk編碼傳送,一般郵件客戶端都能識別
12 #     msg = '''\
13 # From: %s <%s>
14 # To: %s
15 # Subject: %s
16 # %s''' %(from_name, from_mail, to_mail_str, subject, body)  # 這種方式必須將郵件頭資訊靠左,也就是每行開頭不能用空格,否則報SMTP 554
17     mail = [
18         "From: %s <%s>" % (from_name, from_mail),
19         "To: %s" % ','.join(to_mail),   # 轉成字串,以逗號分隔元素
20         "Subject: %s" % subject,
21         "Cc: %s" % ','.join(cc_mail),
22         "",
23         body
24         ]
25     msg = '\n'.join(mail)  # 這種方式先將頭資訊放到列表中,然後用join拼接,並以換行符分隔元素,結果就是和上面註釋一樣了
26     try:
27         s = smtplib.SMTP()
28         s.connect(smtp_server, '25')
29         s.login(from_mail, mail_pass)
30         s.sendmail(from_mail, to_mail+cc_mail, msg)   
31         s.quit()
32     except smtplib.SMTPException as e:
33         print "Error: %s" %e
34 if __name__ == "__main__":
35     sendMail("This is a test!")

s.sendmail(from_mail, to_mail+cc_mail, msg) 在這裡注意下,收件人和抄送人為什麼放一起傳送呢?其實無論是收件人還是抄送人,它們收到的郵件都是一樣的,SMTP都是認為收件人這樣一封一封的發出。所以實際上並沒有抄送這個概念,只是在郵件頭加了抄送人的資訊罷了!另外,如果不需要抄送人,直接把上面cc的資訊去掉即可。

另外以上程式碼傳送的郵件會出現主題中文亂碼:

解決方案:三行程式碼即可,修改成紅色框程式碼即可

1.2 Python傳送郵件帶附件

由於SMTP.sendmail()方法不支援新增附件,所以可以使用email模組來滿足需求。email模組是一個構造郵件和解析郵件的模組。

先看下如何用email庫構造一個簡單的郵件:

message = Message()
message['Subject'] = '郵件主題'
message['From'] = from_mail
message['To'] = to_mail
message['Cc'] = cc_mail
message.set_payload('郵件內容')

基本的格式就是這樣的!

繼續回到主題,傳送郵件帶附件:

 1 # coding=utf-8
 2 #1.先設定編碼,utf-8可支援中英文,如上,一般放在第一行
 3 
 4 #2.註釋:包括記錄建立時間,建立人,專案名稱。
 5 '''
 6 Created on 2019-5-9
 7 @author: 北京-巨集哥
 8 Project:學習和使用郵箱髮帶有附件郵件
 9 '''
10 #3.匯入模組
11 import smtplib
12 from email.mime.text import MIMEText
13 from email.mime.multipart import MIMEMultipart
14 from email.header import Header
15 from email import encoders
16 from email.mime.base import MIMEBase
17 
18 def send_mail(file_new):
19     #-----------1.跟發件相關的引數------
20     smtpserver = 'smtp.mxhichina.com'                #發件伺服器
21     port = 0                      #埠
22     username = '[email protected]'  #發件箱使用者名稱
23     password = 'xx@@123'        #發件箱密碼
24     sender = '[email protected]'    #發件人郵箱
25     receiver = ['[email protected]','[email protected]'] #收件人郵箱
26     # ----------2.編輯郵件的內容------
27     #讀檔案內容
28     f = open(file_new, 'rb')
29     mail_body = f.read()
30     f.close()
31     # 郵件正文是MIMEText
32     body = MIMEText(mail_body, 'html', 'utf-8')
33     # 郵件物件
34     msg = MIMEMultipart()
35     msg['Subject'] = Header("自動化測試報告", 'utf-8').encode()#主題
36     msg['From'] = Header(u'測試機 <%s>'%sender)                #發件人
37     msg['To'] = Header(u'測試負責人 <%s>'%receiver)            #收件人
38     msg['To'] = ';'.join(receiver)
39     msg.attach(body)
40     # # MIMEBase表示附件的物件
41     att = MIMEText(mail_body, "base64", "utf-8")
42     att["Content-Type"] = "application/octet-stream"
43     # filename是顯示附件名字
44     att["Content-Disposition"] = 'attachment; filename="test_report.html"'
45     msg.attach(att)
46     # ----------3.傳送郵件------
47     try:
48         smtp = smtplib.SMTP()
49         smtp.connect(smtpserver)  # 連伺服器
50         smtp.login(sender, password)
51     except:
52         smtp = smtplib.SMTP_SSL(smtpserver, port)
53         smtp.login(sender, password)  # 登入
54     smtp.sendmail(sender, receiver, msg.as_string())  # 傳送
55     smtp.quit()
56 
57 if __name__ == "__main__":
58     #本地檔案的路徑
59     att_path= r'E:\pythontest\text.txt'
60     send_mail(att_path)

 

1.3 Python傳送HTML郵件

 1 # coding=utf-8
 2 #1.先設定編碼,utf-8可支援中英文,如上,一般放在第一行
 3 
 4 #2.註釋:包括記錄建立時間,建立人,專案名稱。
 5 '''
 6 Created on 2019-5-9
 7 @author: 北京-巨集哥
 8 Project:學習和使用郵箱發HTML郵件
 9 '''
10 #3.匯入模組
11 #"-*- coding: utf-8 -*-"
12 import smtplib
13 from email.mime.text import MIMEText
14 
15 mail_user="[email protected]"
16 mail_password="******q1125"
17 mailto_list=["1918991791<[email protected]>","[email protected]"]
18 mail_host="smtp.163.com"
19 mail_postfix="163.com"
20 
21 def sendmail(to_list,sub,content):
22     me="北京-巨集哥"+"<"+mail_user+"@"+mail_postfix+">"
23     msg=MIMEText("<a href='https://www.cnblogs.com/du-hong'><font color='red'>北京-巨集哥</font></a>","html","utf-8")
24     msg['Subject']=sub
25     msg['From']=me
26     msg['To']=",".join(to_list)
27     try:
28         server=smtplib.SMTP()
29         server.connect(mail_host)
30         server.login(mail_user,mail_password)
31         server.sendmail(me,to_list,msg.as_string())
32         server.close()
33         return True
34     except Exception as e:
35         print (str(e))
36         return False
37 if sendmail(mailto_list,"標題:傳送的是html格式","<a href='https://www.cnblogs.com/du-hong'>北京-巨集哥</a>"):
38     print ("done!")
39 else:
40     print ("falsed!")

1.4 Python傳送圖片郵件

# coding=utf-8
#1.先設定編碼,utf-8可支援中英文,如上,一般放在第一行

#2.註釋:包括記錄建立時間,建立人,專案名稱。
'''
Created on 2019-5-9
@author: 北京-巨集哥
Project:學習和使用1郵箱發HTML郵件
'''
#3.匯入模組
#"-*- coding: utf-8 -*-"
import smtplib
from email.mime.text import MIMEText

mail_user="@@@@@163.com"
mail_password="@@@@"
mailto_list=["1918991791<[email protected]>","[email protected]"]
mail_host="smtp.163.com"
mail_postfix="163.com"

def sendmail(to_list,sub,content):
    me="北京-巨集哥"+"<"+mail_user+"@"+mail_postfix+">"
    msg=MIMEText('<html><body><img hidefocus="true" class="index-logo-src" src="//www.baidu.com/img/bd_logo1.png" width="270" height="129" usemap="#mp"></body></html>', 'html', 'utf-8')
    msg['Subject']=sub
    msg['From']=me
    msg['To']=",".join(to_list)
    try:
        server=smtplib.SMTP()
        server.connect(mail_host)
        server.login(mail_user,mail_password)
        server.sendmail(me,to_list,msg.as_string())
        server.close()
        return True
    except Exception as e:
        print (str(e))
        return False
if sendmail(mailto_list,"標題:傳送的是HTML格式","<a href='https://www.cnblogs.com/du-hong'>北京-巨集哥</a>"):
    print ("done!")
else:
    print ("falsed!")

上面發郵件的幾種常見的發郵件方法基本滿足日常需求了。

小結

1、linux環境下提示AttributeError: module 'smtplib' has no attribute 'SMTP',Windows環境執行程式碼也報如下錯誤:

2、原因當然不是模組的問題,檢查了一下拼寫也沒有出問題,最後在這個帖子(連結)的啟發下發現,發現自己的檔案命名為email.py,和模組中的函式有衝突,改名之後Linux環境郵件正常發