1. 程式人生 > >Python傳送郵件(常見四種郵件內容)

Python傳送郵件(常見四種郵件內容)

轉自:http://lizhenliang.blog.51cto.com/7876557/1875330

在寫指令碼時,放到後臺執行,想知道執行情況,會通過郵件、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伺服器連線

看下官方給的示例:

>>> import smtplib
>>> s=smtplib.SMTP("localhost")
>>> tolist=["[email protected]","[email protected]","[email protected]","[email protected]"]
>>> msg = '''\
     ... From: [email protected]
     ... Subject: testin'...
     ...
     ... This is a test '''
>>> s.sendmail("[email protected]",tolist,msg)
     { "[email protected]" : ( 550 ,"User unknown" ) }
>>> s.quit()

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

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

CentOS安裝sendmail:yum install sendmail

>>> import smtplib
>>> s = smtplib.SMTP("localhost")
>>> tolist = ["[email protected]", "[email protected]"]
>>> msg = '''\
... From: [email protected]
... Subject: test
... This is a test '''
>>> s.sendmail("[email protected]", tolist, msg)
{}

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


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

上面是使用本地SMTP伺服器傳送的郵件,測試下用163伺服器傳送郵件看看效果:

>>> import smtplib
>>> s = smtplib.SMTP("smtp.163.com")
>>> s.login("[email protected]", "xxx")
(235, 'Authentication successful')
>>> tolist = ["[email protected]", "[email protected]"]
>>> msg = '''\
... From: [email protected]
... Subject: test
... This is a test '''
>>> s.sendmail("[email protected]", tolist, msg)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/smtplib.py", line 725, in sendmail
    raise SMTPDataError(code, resp)
smtplib.SMTPDataError: (554, 'DT:SPM 163 smtp10,DsCowAAXIdDIJAtYkZiTAA--.65425S2 1477125592,please see http://mail.163.com/help/help_spam_16.htm?ip=119.57.73.67&hostid=smtp10&time=1477125592')

訪問給出的163網址,SMTP554錯誤是: "554 DT:SUM 信封發件人和信頭髮件人不匹配;"

大概已經明白啥意思,看上面再使用本地SMTP伺服器時候,收件人位置是“undisclosed-recipients”,看這樣163的SMTP伺服器不給我們服務的原因就是這裡收件人沒指定。

重新修改下msg物件,新增上收件人:

>>> msg = '''\           
... From: [email protected]
... To: [email protected] ,[email protected]
... Subject: test
...
... This is a test '''
>>> s.sendmail("[email protected]", tolist, msg)
{}


好了,可以正常傳送郵件了。msg這個格式是SMTP規定的,一定要遵守。

1、Python傳送郵件並抄送

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


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

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('郵件內容')

基本的格式就是這樣的!

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

#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email import encoders
from email.mime.base import MIMEBase
from email.utils import parseaddr, formataddr
# 格式化郵件地址
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body, attachment):
    smtp_server = 'smtp.163.com'
    from_mail = '[email protected]'
    mail_pass = 'xxx'
    to_mail = ['[email protected]', '[email protected]']
    # 構造一個MIMEMultipart物件代表郵件本身
    msg = MIMEMultipart()
    # Header對中文進行轉碼
    msg['From'] = formatAddr('管理員 <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('監控', 'utf-8').encode()
    # plain代表純文字
    msg.attach(MIMEText(body, 'plain', 'utf-8'))
    # 二進位制方式模式檔案
    with open(attachment, 'rb') as f:
        # MIMEBase表示附件的物件
        mime = MIMEBase('text', 'txt', filename=attachment)
        # filename是顯示附件名字
        mime.add_header('Content-Disposition', 'attachment', filename=attachment)
        # 獲取附件內容
        mime.set_payload(f.read())
        encoders.encode_base64(mime)
        # 作為附件新增到郵件
        msg.attach(mime)
    try:
        s = smtplib.SMTP()
        s.connect(smtp_server, "25")
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText物件變成str
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    sendMail('附件是測試資料, 請查收!', 'test.txt')

3 Python傳送HTML郵件
#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
# 格式化郵件地址
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body):
    smtp_server = 'smtp.163.com'
    from_mail = '[email protected]'
    mail_pass = 'xxx'
    to_mail = ['[email protected]', '[email protected]']
    # 構造一個MIMEMultipart物件代表郵件本身
    msg = MIMEMultipart() 
    # Header對中文進行轉碼
    msg['From'] = formatAddr('管理員 <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('監控', 'utf-8').encode()
    msg.attach(MIMEText(body, 'html', 'utf-8'))
    try:
        s = smtplib.SMTP()     
        s.connect(smtp_server, "25")   
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText物件變成str     
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    body = """
    <h1>測試郵件</h1>
    <h2 style="color:red">This is a test</h1>
    """
    sendMail(body)

4 Python傳送圖片郵件
#!/usr/bin/python
# -*- coding: utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import parseaddr, formataddr
# 格式化郵件地址
def formatAddr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def sendMail(body, image):
    smtp_server = 'smtp.163.com'
    from_mail = '[email protected]'
    mail_pass = 'xxx'
    to_mail = ['[email protected]', '[email protected]']
    # 構造一個MIMEMultipart物件代表郵件本身
    msg = MIMEMultipart() 
    # Header對中文進行轉碼
    msg['From'] = formatAddr('管理員 <%s>' % from_mail).encode()
    msg['To'] = ','.join(to_mail)
    msg['Subject'] = Header('監控', 'utf-8').encode()
    msg.attach(MIMEText(body, 'html', 'utf-8'))
    # 二進位制模式讀取圖片
    with open(image, 'rb') as f:
        msgImage = MIMEImage(f.read())
    # 定義圖片ID
    msgImage.add_header('Content-ID', '<image1>')
    msg.attach(msgImage)
    try:
        s = smtplib.SMTP()     
        s.connect(smtp_server, "25")   
        s.login(from_mail, mail_pass)
        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText物件變成str     
        s.quit()
    except smtplib.SMTPException as e:
        print "Error: %s" % e
if __name__ == "__main__":
    body = """
    <h1>測試圖片</h1>
    <img src="cid:image1"/>    # 引用圖片
    """
    sendMail(body, 'test.png')

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









相關推薦

Python傳送郵件常見郵件內容

轉自:http://lizhenliang.blog.51cto.com/7876557/1875330 在寫指令碼時,放到後臺執行,想知道執行情況,會通過郵件、SMS(簡訊)、飛信、微信等方式通知管理員,用的最多的是郵件。在linux下,Shell指令碼傳送郵件告警是

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

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

Python發送郵件常見郵件內容

t對象 3.6 idt serve ttl dddd python tdi tls Python發送郵件(常見四種郵件內容) 轉載 2017年03月03日 17:17:04 轉自:http://lizhenliang.blog.51cto.com/7876557

【轉】【PythonPython發送郵件常見郵件內容

.cn .com pytho html 常見 body gpo 詳細 tle 感謝:夢琪小生的《【轉】【Python】Python發送郵件(常見四種郵件內容)》 裏面詳細介紹了Python中發送郵件的方法,以供自己參考【轉】【Python】Python發送郵件(常見四種郵件

python 傳送郵件文字、表格、附件

import pandas as pd import smtplib   from email.mime.text import MIMEText   from email.mime.multipart import MIMEMultipart filena

URL訪問網站的過程三次握手、次揮手傳送RST包的情況,常用協議

URL訪問網站(三次握手、四次揮手) 1)獲得域名所對應的IP地址,若DNS快取中沒有相關資料,則IE瀏覽器向DNS伺服器發出DNS請求,以獲取域名所對應的IP地址。 2)IE瀏覽器與域名地址建立TCP連線,三次握手 3)http訪問 4)斷開TCP連線,四次揮手

機器學習實戰——線性迴歸和區域性加權線性迴歸python中複製的情形!

書籍:《機器學習實戰》中文版 IDE:PyCharm Edu 4.02 環境:Adaconda3  python3.6 注:本程式相比原書中的程式區別,主要區別在於函式驗證和繪圖部分。 一、一般線

Python請求外部POST請求,常見請求體

HTTP 協議規定 POST 提交的資料必須放在訊息主體(entity-body)中,但協議並沒有規定資料必須使用什麼編碼方式。常見的四種編碼方式如下: 1、application/x-www-form-urlencoded 這應該是最常見的 POS

python執行系統命令的方式

lib 信息 數值 成功 星期 控制 src 圖片 pos 一、os模塊 1. os.system(‘cmd‘) 在子終端運行系統命令,不能獲取命令執行後的返回信息以及執行返回的狀態 import os os.system(‘date‘) # 2016年 06月 30

Python】Http Post請求請求體的Python實現

article gif 提交 直接 方法 method 根據 encode 文獻 前言 前幾天一個剛接觸Python不深的朋友問我的Python的xml格式Post請求怎麽發送,剛好最近也在看Http請求相關的內容,所以決定總結一下。 Content-Type Conte

U盤強制拔出丟失數據的恢復方法U盤寫保護的解決方法

沒有 文件 生成列 灰色 下載 而且 tool 需要 大小 ● U盤強制拔出丟失數據的恢復方法 U盤從出現以來,小巧便攜容量大深受人們的喜愛,不用像雲盤一樣需要下載,所以重要的文件我們都喜歡用U盤來傳遞數據,但是很多人使用U盤拔出時都沒有使用“彈出U盤”功能,取出過程中電腦

python 遍歷列表的方式

for enume list 列表 print clas int class range 1, list = [1,2,3,4] for i in list: … print i … 1 2

大金空調自動關機常見原因

故障 睡眠 分鐘 轉換成 面板 保護功能 就會 以及 情況 大金空調屬於空調界的NO.1有著完美的技術,但是缺點就是價格有點高,所以維修起來難度也大,在此株洲大金空調維修售後提供大金空調自動關機常見四種問題和原因,望對各位技師或用戶有一定的幫助1、遙控器設置原因:查看空調遙

open-falcon之使用mail-provider發郵件支持smtp SSL協議

ans 服務器 有一個 code var clone 安裝 安裝mail 端口 一、首先確定go語言安裝環境配置好 1.進入官網下載源碼包 https://golang.org/dl/ 2.解壓縮,配置環境變量 在/etc/profile最後加上export PAT

【譯】統計建模:兩文化、五部分

謝絕任何不通知本人的轉載,尤其是抄襲。   Abstract  1. Introduction  2. ROAD MAP 3. Projects in consulting 4. Return to the university 5. The

資料結構與演算法隨筆之------二叉樹的遍歷一文搞懂二叉樹的遍歷

二叉樹的遍歷 二叉樹的遍歷(traversing binary tree)是指從根結點出發,按照某種次序依次訪問二叉樹中所有的結點,使得每個結點被訪問依次且僅被訪問一次。 遍歷分為四種,前序遍歷,中序遍歷,後序遍歷及層序遍歷 前序 中

Python之路:網路程式設計基礎 Python基礎之網路程式設計

Python基礎之網路程式設計     學習網路程式設計之前,要對計算機底層的通訊實現機制要有一定的理解。 OSI 網際網路協議按照功能不同分為osi七層或tcp/ip五層或tcp/ip四層   可以將應用層,表示層,會

Docker網路管理容器的網路模式

下面,我們來學習Docker的網路管理。 Docker 在啟動時會建立一個虛擬網橋 docker0,預設地址為 172.17.0.1/16,容器啟動後都會被橋接到 docker0 上,並自動分配到一個 IP 地址 . docker0預設地址 網橋 容器橋接

Python學習筆記高階變數型別--字串

1、字串定義 字串 就是 一串字元,是程式語言中表示文字的資料型別   在Python中可以使用 一對雙引號"或者一對單引號'定義一個字串 雖然可以使用\"或者\’定義字串 如果字串內部需要使用',可以使用”定義字串 可以使用 索引 獲取一個字串中

Python自動化學習筆記——Python資料型別集合set,元組tuple、修改檔案、函式、random常用方法

1.修改檔案的兩種方式 1 #第一種 2 with open('users','a+') as fw: #用a+模式開啟檔案,使用with這種語法可以防止忘記close檔案 3 fw.seek(0) #移動檔案指標到最前面,然後才能讀到內容 4 result=fw.read()