首頁  >  文章  >  後端開發  >  Python3如何使用SMTP協定發送E-mail電子郵件的範例

Python3如何使用SMTP協定發送E-mail電子郵件的範例

黄舟
黄舟原創
2017-10-02 09:43:143332瀏覽

SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協定,它是一組用於由來源地址到目的地址傳送郵件的規則,由它來控制信件的中轉方式。以下這篇文章主要為大家介紹了關於Python3如何利用SMTP協定發送E-mail電子郵件的方法,需要的朋友可以參考下。

前言

本文主要介紹給大家介紹了關於Python3用SMTP協定發送電子郵件的相關內容,在介紹如何使用python程式向在指定郵箱發送郵件之前,我們需要先介紹一下有關電子郵件的相關知識。

Email的歷史比Web還要久遠,直到現在,Email也是網路上應用非常廣泛的服務。

幾乎所有的程式語言都支援發送和接收電子郵件,但是,先等等,在我們開始編寫程式碼之前,有必要搞清楚電子郵件是如何在互聯網上運作的。

假設我們自己的電子郵件地址是me@163.com,對方的電子郵件地址是friend@sina.com,現在我們用Outlook或Foxmail之類的軟體寫好郵件,填上對方的Email地址,點“發送”,電子郵件就發出去了。這些電子郵件軟體稱為MUA:Mail User Agent-郵件使用者代理程式。

Email從MUA發出去,不是直接到達對方電腦,而是發到MTA:Mail Transfer Agent——郵件傳輸代理,就是那些Email服務提供商,比如網易、新浪等等。由於我們自己的電子郵件是163.com,所以,Email首先被投遞到網易提供的MTA,再由網易的MTA發到對方服務商,也就是新浪的MTA。這個過程中間可能還會經過別的MTA,但我們不關心具體路線,我們只關心速度。

Email到達新浪的MTA後,由於對方使用的是@sina.com的郵箱,因此,新浪的MTA會把Email投遞到郵件的最終目的地MDA:Mail Delivery Agent——郵件投遞代理。 Email到達MDA後,就靜靜地躺在新浪的某個伺服器上,存放在某個文件或特殊的資料庫裡,我們將這個長期保存郵件的地方稱之為電子郵箱。對方要取到郵件,必須透過MUA從MDA上把郵件取到自己的電腦上。

所以,一封電子郵件的旅程是:

寄件者-> MUA -> MTA -> MTA -> 若幹MTA - > MDA <- MUA <- 收件者

有了上述基本概念,要寫程式來傳送和接收郵件,本質上就是:

1.寫MUA把郵件發到MTA。

      2.將MUA從MDA上收郵件。

發送電子郵件時,MUA和MTA使用的協定是SMTP:Simple Mail Transfer Protocol,後面的MTA到另一個MTA也是用SMTP協定。

收到郵件時,MUA和MDA使用的協定有兩種:POP:Post Office Protocol,目前版本是3,俗稱POP3;IMAP:Internet Message Access Protocol,目前版本是4,優點是不但能取郵件,還可以直接操作MDA上儲存的郵件,例如從收件匣移到垃圾箱,等等。

郵件客戶端軟體在發送郵件時,會讓你先設定SMTP伺服器,也就是你要發到哪個MTA上。假設你正在使用163的郵箱,你就不能直接發到新浪的MTA上,因為它只服務新浪的用戶,所以,你得填163提供的SMTP伺服器位址:smtp.163.com,為了證明你是163的用戶,SMTP伺服器還要求你填寫郵件地址和郵箱口令,這樣,MUA才能正常地把Email透過SMTP協定發送到MTA。

類似的,從MDA收郵件時,MDA伺服器也要求驗證你的郵箱口令,確保不會有人冒充你收取你的郵件,所以,Outlook之類的郵件用戶端會要求你填寫POP3或IMAP伺服器位址、郵件地址和口令,這樣,MUA才能順利地透過POP或IMAP協定從MDA取到郵件。

最後特別注意:目前大多數郵件服務商都需要手動開啟SMTP發信和POP收信的功能,否則只允許在網頁登入:

例如QQ郵箱

接下來,我們開始我們的正題,如何透過python發送電子郵件。

-------------------------------------------- ------------------------------------

發送簡單文字郵件

SMTP是發送郵件的協議,Python內建對SMTP的支持,可以發送純文字郵件、HTML郵件以及帶附件的郵件。

Python對SMTP支援有smtplib和email兩個模組,email負責建構郵件,smtplib負責發送郵件。

首先,我們來建構一個最簡單的純文字郵件:


#
from email.mime.text import MIMEText
msg = MIMEText(&#39;hello, this is axin...&#39;, &#39;plain&#39;, &#39;utf-8&#39;)

注意:到建構MIMEText物件時,第一個參數就是郵件正文,第二個參數是MIME的subtype,傳入'plain'表示純文本,最後的MIME就是'text/plain',最後一定要用utf-8編碼保證多語言相容性。

我們光有了正文內容還不可以,我們還需要為我們要發送的郵件添加頭部訊息。頭部訊息中包含發送者和接收者以及郵件主題等資訊。


msg = MIMEText(&#39;hello, this is axin...&#39;, &#39;plain&#39;, &#39;utf-8&#39;) #邮件正文
msg[&#39;From&#39;] = _format_addr(&#39;阿鑫 <%s>&#39; % from_addr) #邮件头部,发送者信息
msg[&#39;To&#39;] = _format_addr(&#39;aa <%s>&#39; % to_addr) #接收者信息
msg[&#39;Subject&#39;] = Header(&#39;test&#39;, &#39;utf-8&#39;).encode() #邮件主题

建構完我們要傳送的訊息後,我們只需要呼叫python對應的函數,透過SMTP發出去:


server = smtplib.SMTP(smtp_server, 25) #SMTP协议默认端口是25
server.set_debuglevel(1) #打印出和SMTP服务器交互的所有信息
server.login(from_addr, password) #登录SMTP服务器
server.sendmail(from_addr, [to_addr], msg.as_string()) #发送邮件
server.quit()

我們用set_debuglevel(1)就可以列印出和SMTP伺服器互動的所有資訊。 SMTP協定就是簡單的文字命令和回應。 login()方法用來登入SMTP伺服器,sendmail()方法就是發郵件,由於可以一次發給多個人,所以傳入一個list,郵件正文是一個str,as_string() 把MIMEText物件變成str。

完整程式碼範例如下:


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

import smtplib

def _format_addr(s): #格式化一个邮件地址
name, addr = parseaddr(s)
return formataddr((Header(name, &#39;utf-8&#39;).encode(), addr))

from_addr = &#39;fengxinlinux@sina.com&#39; #发送者邮箱地址
password = &#39;******&#39; #发送者邮箱密码,不告诉你密码=。=
to_addr = &#39;903087053@qq.com&#39; #接收者邮箱地址
smtp_server = &#39;smtp.sina.com&#39; #发送者所在的邮箱供应商的MTA地址
#from_addr = input(&#39;From: &#39;)
#password = input(&#39;Password: &#39;)
#to_addr = input(&#39;To: &#39;)
#smtp_server = input(&#39;SMTP server: &#39;)

msg = MIMEText(&#39;hello, this is axin...&#39;, &#39;plain&#39;, &#39;utf-8&#39;) #邮件正文
msg[&#39;From&#39;] = _format_addr(&#39;阿鑫 <%s>&#39; % from_addr) #邮件头部,发送者信息
msg[&#39;To&#39;] = _format_addr(&#39;axin <%s>&#39; % to_addr) #接收者信息
msg[&#39;Subject&#39;] = Header(&#39;test&#39;, &#39;utf-8&#39;).encode() #邮件主题


server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25
server.set_debuglevel(1) #打印出和SMTP服务器交互的所有信息
server.login(from_addr, password) #登录SMTP服务器
server.sendmail(from_addr, [to_addr], msg.as_string()) #发送邮件
server.quit()
1

運行程序,我們會發現我測試的郵箱中收到了一封新的郵件。

我們會發現,其他的資訊都一樣,但是收件者的資料不是我們程式裡填寫的axin。

因為許多郵件服務商在顯示郵件時,會把收件者名字自動替換為使用者註冊的名字,但是其他收件者名字的顯示不受影響。

我在測試時,有時候發送的郵件會被郵件服務商判定為垃圾郵件,直接被放到垃圾箱中了。 。 。至於什麼情況會被認定為垃圾郵件,我也摸不到頭緒。 。

發送附件的郵件

上面我們介紹瞭如何發送文字郵件,有了上面的知識後,發送帶有附件的郵件其實也非常的簡單。

附附件的郵件可以看做包含若干部分的郵件:文字和各個附件本身,所以,可以建構一個MIMEMultipart物件代表郵件本身,然後往裡面加上一個MIMEText作為郵件正文,再繼續往裡面加上表示附件的MIMEBase物件即可:


# 邮件对象:
msg= MIMEMultipart()
msg[&#39;From&#39;] = _format_addr(&#39;阿鑫 <%s>&#39; % from_addr) #邮件头部,发送者信息
msg[&#39;To&#39;] = _format_addr(&#39;axin <%s>&#39; % to_addr) #接收者信息
msg[&#39;Subject&#39;] = Header(&#39;test&#39;, &#39;utf-8&#39;).encode() #邮件主题

# 邮件正文是MIMEText:
msg.attach(MIMEText(&#39;hello, this is axin...&#39;, &#39;plain&#39;, &#39;utf-8&#39;))

# 添加附件就是加上一个MIMEBase,从本地读取一个图片:
with open(&#39;/home/fengxin/图片/11.jpg&#39;,&#39;rb&#39;) as fhandle:
mime = MIMEBase(&#39;image&#39;,&#39;jpeg&#39;,filename=&#39;11.jpg&#39;)
mime.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;, filename=&#39;11.jpg&#39;)
mime.add_header(&#39;Content-ID&#39;, &#39;<0>&#39;)
mime.add_header(&#39;X-Attachment-Id&#39;, &#39;0&#39;)
# 把附件的内容读进来:
mime.set_payload(fhandle.read())
# 用Base64编码:
encoders.encode_base64(mime)
# 添加到MIMEMultipart:
msg.attach(mime)

然後,按正常傳送流程把msg(注意類型已變成MIMEMultipart)寄出去,就可以收到附附件的郵件。

完整程式碼範例如下:


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


import smtplib

def _format_addr(s): #格式化一个邮件地址
name, addr = parseaddr(s)
return formataddr((Header(name, &#39;utf-8&#39;).encode(), addr))

from_addr = &#39;你的邮箱地址&#39; #发送者邮箱地址
password = &#39;你的邮箱密码&#39; #发送者邮箱密码
to_addr = &#39;903087053@qq.com&#39; #接收者邮箱地址
smtp_server = &#39;smtp.sina.com&#39; #发送者所在的邮箱供应商的MTA地址
#from_addr = input(&#39;From: &#39;)
#password = input(&#39;Password: &#39;)
#to_addr = input(&#39;To: &#39;)
#smtp_server = input(&#39;SMTP server: &#39;)


msg= MIMEMultipart()
msg[&#39;From&#39;] = _format_addr(&#39;阿鑫 <%s>&#39; % from_addr) #邮件头部,发送者信息
msg[&#39;To&#39;] = _format_addr(&#39;axin <%s>&#39; % to_addr) #接收者信息
msg[&#39;Subject&#39;] = Header(&#39;test&#39;, &#39;utf-8&#39;).encode() #邮件主题

msg.attach(MIMEText(&#39;hello, this is axin...&#39;, &#39;plain&#39;, &#39;utf-8&#39;))

with open(&#39;/home/fengxin/图片/11.jpg&#39;,&#39;rb&#39;) as fhandle:
mime = MIMEBase(&#39;image&#39;,&#39;jpeg&#39;,filename=&#39;11.jpg&#39;)
mime.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;, filename=&#39;11.jpg&#39;)
mime.add_header(&#39;Content-ID&#39;, &#39;<0>&#39;)
mime.add_header(&#39;X-Attachment-Id&#39;, &#39;0&#39;)
# 把附件的内容读进来:
mime.set_payload(fhandle.read())
# 用Base64编码:
encoders.encode_base64(mime)
# 添加到MIMEMultipart:
msg.attach(mime)

server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25
server.set_debuglevel(1) #打印出和SMTP服务器交互的所有信息
server.login(from_addr, password) #登录SMTP服务器
server.sendmail(from_addr, [to_addr], msg.as_string()) #发送邮件
server.quit()
1

運行後。測試郵箱正確收到郵件,如圖:

總結

以上是Python3如何使用SMTP協定發送E-mail電子郵件的範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn