SMTP是發送郵件的協議,Python內置對SMTP的支持,可以發送純文本郵件、HTML郵件以及帶附件的郵件。
Python對SMTP支持有smtplib和email兩個模塊,email負責構造郵件,smtplib負責發送郵件。
1、smtplib模塊
smtplib模塊定義了一個簡單的SMTP客戶端,可以用來在互聯網上發送郵件。
定義的類有如下:
class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])
class smtplib.SMTP_SSL([host[, port[, local_hostname[, keyfile[, certfile[, timeout]]]]]])
class smtplib.LMTP([host[, port[, local_hostname]]])
還有一些已經定義好的異常
exception smtplib.SMTPException
exception smtplib.SMTPServerDisconnected
exception smtplib.SMTPResponseException
exception smtplib.SMTPSenderRefused
exception smtplib.SMTPRecipientsRefused
exception smtplib.SMTPDataError
exception smtplib.SMTPConnectError
exception smtplib.SMTPHeloError
exception smtplib.SMTPAuthenticationError
這么多已定義的類中,我們最常用的的還是smtplib.SMTP類用法:
smtp實例封裝一個smtp連接,它支持所有的SMTP和ESMTP操作指令,如果host和port參數被定義,則smtp會在初始化期間自動調用connect()方法,如果connect()方法失敗,則會觸發SMTPConnectError異常,timeout參數設置了超時時間。在一般的調用過程中,應該遵connetc()、sendmail()、quit()步驟。
smtplib.SMTP提供的方法:
SMTP.set_debuglevel(level):#設置是否為調試模式。默認為False, SMTP.connect([host[, port]]):#連接到指定的smtp服務器。參數分別表示smpt主機和端口。 # 默認是本機的25端口。也可以寫成hostname:port的形式。 SMTP.docmd(cmd[, argstring]):#向smtp服務器發送指令。可選參數argstring表示指令的參數。 SMTP.helo([hostname]) :#使用"helo"指令向服務器確認身份。相當於告訴smtp服務器“我是誰”。 SMTP.has_extn(name):#判斷指定名稱在服務器郵件列表中是否存在。 #出於安全考慮,smtp服務器往往屏蔽了該指令。 SMTP.verify(address) :#判斷指定郵件地址是否在服務器中存在。 #出於安全考慮,smtp服務器往往屏蔽了該指令。 SMTP.login(user, password) :#登陸到smtp服務器。 #現在幾乎所有的smtp服務器,都必須在驗證用戶信息合法之后才允許發送郵件。
SMTP.sendmail(self, from_addr, to_addrs, msg, mail_options=[],
rcpt_options=[])
:#發送郵件。 #這里要注意一下第三個參數,msg是字符串,表示郵件。 #我們知道郵件一般由標題,發信人,收件人,郵件內容,附件等構成,發送郵件的時候,要注意msg的格式。 #這個格式就是smtp協議中定義的格式。 SMTP.quit() :#斷開與smtp服務器的連接,相當於發送"quit"指令。
2、email模塊
emial模塊用來處理郵件消息,其包括的類有:
class email.mime.base.MIMEBase(_maintype, _subtype, **_params):#這是MIME的一個基類。一般不需要在使用時創建實例。其中_maintype是內容類型,如text或者image。_subtype是內容的minor type 類型,如plain或者gif。 **_params是一個字典,直接傳遞給Message.add_header()。 class email.mime.multipart.MIMEMultipart([_subtype[, boundary[, _subparts[, _params]]]]:#MIMEBase的一個子類,多個MIME對象的集合,_subtype默認值為mixed。boundary是MIMEMultipart的邊界,默認邊界是可數的。 class email.mime.application.MIMEApplication(_data[, _subtype[, _encoder[, **_params]]]):#MIMEMultipart的一個子類。 class email.mime.audio. MIMEAudio(_audiodata[, _subtype[, _encoder[, **_params]]]): MIME音頻對象 class email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]):#MIME二進制文件對象。 class email.mime.text.MIMEText(_text[, _subtype[, _charset]]):#MIME文本對象,其中_text是郵件內容,_subtype郵件類型,可以是text/plain(普通文本郵件),html/plain(html郵件), _charset編碼,可以是gb2312等等。 class email.mime.message.MIMEMessage(_msg[, _subtype]):#具體的一個message實例,使用方法如下: msg=mail.Message.Message() #一個實例 msg['to']='XXX@XXX.com' #發送到哪里 msg['from']='YYY@YYYY.com' #自己的郵件地址 msg['date']='2012-3-16' #時間日期 msg['subject']='hello world' #郵件主題
smtplib.SMTP
1、利用smtplib.SMTP發送一份普通文本郵件
import smtplib from email.mime.text import MIMEText sender = 'wxtysg@163.com' # 發件人郵箱賬號 my_pass= 'gahghfh' # 發件人郵箱授權碼 receiver="888888@qq.com" #接收人郵箱 def mail(): ret = True try: content = "hello world"# 郵件內容 msg = MIMEText(content, 'plain', 'utf-8') msg['From'] = sender #發件人郵箱賬號 msg['To']=receiver msg['Subject'] = "Python發送郵件測試" # 郵件的主題 #創建連接對象並連接到服務器 server = smtplib.SMTP("smtp.163.com")# 發件人郵箱中的SMTP服務器,端口是25 server.login(sender, my_pass)# 發件人郵箱賬號、授權碼 server.sendmail(sender, receiver, msg.as_string()) server.quit() # 關閉連接 except Exception as e: ret = False print(e) return ret ret = mail() if ret: print("郵件發送成功") else: print("郵件發送失敗")
ps:使用標准的25端口連接SMTP服務器時,使用的是明文傳輸,發送郵件的整個過程可能會被竊聽。要更安全地發送郵件,可以加密SMTP會話,實際上就是先創建SSL安全連接,然后再使用SMTP協議發送郵件
smtplib.SMTP_SSL
利用smtplib.SMTP_SSL發送qq郵件
注意要:發送QQ郵件需建立SSL安全連接。故需將smtplib.SMTP() 改成了smtplib.SMTP_SSL()
class smtplib.SMTP_SSL([host[, port[, local_hostname[, keyfile[, certfile[, timeout]]]]]])
這是一個派生自SMTP的子類,通過SSL加密的套接字連接(使用此類,您需要使用SSL支持編譯的套接字模塊)。如果未指定主機,則使用“(本地主機)”。如果省略端口,則使用標准的SMTP-over-SSL端口(465)。 local_hostname和source_address與SMTP類中的含義相同。密鑰文件和證書文件也是可選的 - 它們可以包含用於SSL連接的PEM格式的私鑰和證書鏈文件。上下文也是可選的,可以包含SSLContext,是keyfile和certfile的替代方法;如果指定keyfile和certfile都必須為None。
1、發送一個普通文本郵件
QQ郵箱POP3 和 SMTP 服務器地址設置如下:
郵箱 | POP3服務器(端口995) | SMTP服務器(端口465或587) |
---|---|---|
qq.com | pop.qq.com | smtp.qq.com |
注:
1、SMTP服務器需要身份驗證。
2、如果是設置POP3和SMTP的SSL加密方式,則端口如下:
1)POP3接收郵件服務器(端口995);
2)SMTP發送郵件服務器(端口465或587)。
另外,用qq郵件服務器發送郵件需要先到郵箱里設開啟SMTP/POP3服務。然后獲取授權碼, 在代碼中要填寫的密碼是這個授權碼, 而不是郵箱密碼!
import smtplib from email.mime.text import MIMEText msg_from = '6666666@qq.com' # 發送方郵箱 passwd = 'aczbvlbtrsaadjda' # 填入發送方郵箱的授權碼 msg_to = '888888@qq.com' # 收件人郵箱 mail_host="smtp.qq.com" #發送人郵件的stmp服務器 port= 465 #端口號 #郵件 subject = "python郵件測試" # 主題 content = "Hello World"# 正文 msg = MIMEText(content) msg['Subject'] = subject msg['From'] = msg_from msg['To'] = msg_to #創建連接對象並連接到服務器 s = smtplib.SMTP_SSL(mail_host,port) # 郵件服務器及端口號,SMTP_SSL默認使用465端口號,端口號可省略 # 登錄服務器 s.login(msg_from, passwd) try: s.sendmail(msg_from, msg_to, msg.as_string()) print("發送成功") except s.SMTPException as e: print(e) print("發送失敗") finally: s.quit()
2、發送HTML格式的郵件
在構造MIMEText對象時,把HTML字符串傳進去,再把第二個參數由plain變為html就可以了:
import smtplib from email.mime.text import MIMEText msg_from = '2419636244@qq.com' # 發送方郵箱 passwd = 'qfzgdumpeswjdjic' # 填入發送方郵箱的授權碼 # tolist=["2419636231@qq.com","2419636244@qq.com"] msg_to = "2419636231@qq.com" # 收件人郵箱 ,可以一次發給多個人 mail_host="smtp.qq.com" #服務器 port= 465 #端口號 #郵件 subject = "python郵件測試" # 主題 content = """" <p>Python 郵件發送測試...</p> <p><a href="http://www.cnblogs.com/freely/">戳它</a></p> """#內容 msg = MIMEText(content,"html",'utf-8')#三個參數:第一個為文本內容,第二個MIME的subtype,設置文本格式,傳入'plain',最終的MIME就是'text/plain',第三個 utf-8 設置編碼 #plain 頁面上原樣顯示這段代碼 msg['Subject'] = subject msg['From'] = msg_from msg['To'] = msg_to #創建連接對象並連接到 s = smtplib.SMTP_SSL(mail_host,port) # 郵件服務器及端口號 # 登錄服務器 s.login(msg_from, passwd) try: s.sendmail(msg_from,msg_to, msg.as_string()) print("發送成功") except Exception as e: print(e) print("發送失敗") finally: s.quit()
附:如何獲取授權碼?
1、登陸發送方郵箱
2、開啟服務