[python]《Python編程快速上手:讓繁瑣工作自動化》學習筆記6

1. 發送電子郵件和短信筆記(第16章)(代碼下載)

1.1 發送電子郵件

簡單郵件傳輸協議(SMTP)是用於發送電子郵件的協議。SMTP 規定電子郵件應該如何格式化、加密、在郵件服務器之間傳遞,以及在你點擊發送後,計算機要處理的所有其他細節。。但是,你並不需要知道這些技術細節,因爲Python 的smtplib 模塊將它們簡化成幾個函數。SMTP只負責向別人發送電子郵件。
SMTP發送郵件主要步驟如下:

import smtplib
# 連接到SMTP 服務器
smtpObj = smtplib.SMTP('smtp.example.com', 587)
# 向SMTP 電子郵件服務器“打招呼”
smtpObj.ehlo()
(250, b'mx.example.com at your service, [216.172.148.131]\nSIZE 35882577\
n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES\nCHUNKING')
# 開始TLS 加密
smtpObj.starttls()
(220, b'2.0.0 Ready to start TLS')
# 登陸賬號
smtpObj.login('[email protected]', 'MY_SECRET_PASSWORD')
(235, b'2.7.0 Accepted')
# 發送郵件
smtpObj.sendmail('[email protected]', '[email protected]', 'Subject: So
long.\nDear Alice, so long and thanks for all the fish. Sincerely, Bob')
# 斷開連接
smtpObj.quit()
(221, b'2.0.0 closing connection ko10sm23097611pbd.52 - gsmtp')
函數 用途
SMTP.connect(host=‘localhost’,port=0) 鏈接 SMTP 服務器,host爲SMTP 服務器常用域名,port爲smtp端口
smtpObj.ehlo() 判斷是否鏈接服務器成功
SMTP.login(user,password) 登陸需要認證的SMTP服務器,參數爲用戶名與密碼
SMTP.sendmail(from_addr,to_addrs,msg,mail_options=[],rcpt_options=[]) 發送郵件,from_addr爲發件人,to_addrs爲收件人,msg爲郵件內容
SMTP.starttls(keyfile=None,certfile=None) 啓用TLS安全傳輸模式
SMTP.quit() 斷開smtp服務器鏈接

提供商 SMTP 服務器常用域名見:
https://blog.csdn.net/zdqdj1/article/details/48030023
用Content-Type類型見:
https://www.cnblogs.com/keyi/p/5833388.html

在郵件主體中會常常包含 HTML、圖像、聲音以及附件格式等,MIME(Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展)作爲一種新的擴展郵件格式很好地補充了這一點,更多MIME 知識見 https://docs.python.org/3/library/email.html。 Python 中常用的 MIME 實現類如下:

函數 用途
email.mime.base.MIMEBase(_maintype,_subtype) MIME特定類的基類,_maintpe是Content-Type主要類型,_subtype是Content-Type次要類型
email.mime.multipart.MIMEMultipart(_subtype=‘mixed’) 生成包含多個部分的 MIME 對象,_subtype取值 mixed、related、alternative
email.mime.application.MIMEApplication(_ data, _ subtype=‘octet-stream’, _ encoder=email.encoders.encode_base64 添加應用,_ encoderw爲編碼格式,可使用email.encoders模塊查看內置編碼表
email.mime.audio.MIMEAudio (_ audiodata, _ subtype=None, _ encoder) 創建音頻數據,_audiodata原始二進制音頻數據,_subtype音頻類型,_encoder編碼
email.mime.image.MIMEImage(_ imagedata, _ subtype=None, _ encoder) 創建圖像數據
class email.mime.text.MIMEText(_ text, _ subtype=‘plain’) 創建文本

1.2 發送電子郵件具體實例

1.2.1 基礎郵件發送

基礎郵件發送類似上面郵件發送步驟,只不過添加getpass模塊,設置輸入用戶名和輸入密碼爲暗文,保證安全性。調用email.mime模塊,設置正文。具體代碼如下

import smtplib
# 設置暗文
import getpass
# 設置郵件內容
# 具體見https://docs.python.org/3/library/email.mime.html
# 創建文本
from email.mime.text import MIMEText
# 設置郵件編碼格式
from email.header import Header

# 連接到SMTP服務器
# SMTP服務器名,服務端口是一個整數值,幾乎總是587
smtpObj = smtplib.SMTP('smtp-mail.outlook.com', 587)

# starttls()讓SMTP 連接處於TLS模式。返回值220告訴你,該服務器已準備就緒。
print(smtpObj.starttls())

# 提示輸入用戶名
username = getpass.getpass(prompt="input username:")
# 提示輸入密碼
password = getpass.getpass(prompt="input password:")

# 收件人
recievername = ['[email protected]', '[email protected]']
# 返回值235表示認證成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)


# 設置內容,第二個參數表示文本
msg = MIMEText('正文內容', 'plain', 'utf-8')
# 設置標題
msg['Subject'] = Header('標題', 'utf-8')

try:
    smtpObj.sendmail(username, recievername, msg.as_string())
    print("郵件發送成功")
except:
    print("Error: 無法發送郵件")

# 退出服務器
smtpObj.quit()


結果如下所示:
基礎郵件發送

1.2.2 發送HTML郵件

如果我們要發送HTML郵件,而不是普通的純文本文件怎麼辦?方法很簡單,在構造MIMEText對象時,把HTML字符串傳進去,再把第二個參數由plain變爲html就可以了。

import smtplib
# 設置暗文
import getpass
# 設置郵件編碼格式
from email.header import Header
# 設置郵件內容
# 具體見https://docs.python.org/3/library/email.mime.html
from email.mime.text import MIMEText


# 連接到SMTP服務器
# SMTP服務器名,服務端口是一個整數值,幾乎總是587
smtpObj = smtplib.SMTP('smtp-mail.outlook.com', 587)

# starttls()讓SMTP 連接處於TLS模式。返回值220告訴你,該服務器已準備就緒。
print(smtpObj.starttls())

# 提示輸入用戶名
username = getpass.getpass(prompt="input username:")
# 提示輸入密碼
password = getpass.getpass(prompt="input password:")

# 收件人
recievername = ['[email protected]', '[email protected]']
# 返回值235表示認證成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)

mail_msg = """
<p>郵件正文</p>
<p><a href="https://blog.csdn.net/LuohenYJ">我的博客</a></p>
"""

# 設置內容 html格式
msg = MIMEText(mail_msg, 'html', 'utf-8')
# 設置標題
msg['Subject'] = Header('標題', 'utf-8')

try:
    smtpObj.sendmail(username, recievername, msg.as_string())
    print("郵件發送成功")
except:
    print("Error: 無法發送郵件")

# 退出服務器
smtpObj.quit()

結果如下所示:
基礎郵件發送

1.2.3 添加圖像發送郵件

import smtplib
# 設置暗文
import getpass

# 設置郵件編碼格式
from email.header import Header

# 多文件
# 具體見 https://docs.python.org/3/library/email.mime.html
# 詳細說明見 https://blog.csdn.net/qdujunjie/article/details/8995334
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
# 設置圖像
from email.mime.image import MIMEImage
# 設置郵件內容
from email.mime.text import MIMEText
import os
import requests

# 連接到SMTP服務器
# SMTP服務器名,服務端口是一個整數值,幾乎總是587
smtpObj = smtplib.SMTP('smtp-mail.outlook.com', 587)

# starttls()讓SMTP 連接處於TLS模式。返回值220告訴你,該服務器已準備就緒。
print(smtpObj.starttls())

# 提示輸入用戶名
username = getpass.getpass(prompt="input username:")
# 提示輸入密碼
password = getpass.getpass(prompt="input password:")


# 收件人
recievername = ['[email protected]', '[email protected]']
# 返回值235表示認證成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)


# 郵件的 HTML 文本中一般郵件服務商添加外鏈是無效的,但不是絕對的
# 添加圖像方式如下:


# 正文內容
# cid表示content-id
mail_msg = """
<p>郵件正文</p>
<p><a href="https://blog.csdn.net/LuohenYJ">我的博客</a></p>
<p>本地圖片演示:</p>
<p><img src="cid:imagelocal"></p>
<p>網絡圖片演示:</p>
<p><img src="cid:imageurl"></p>
"""
# 設置多內容
msg = MIMEMultipart()
# 添加正文
msg.attach(MIMEText(mail_msg, 'html', 'utf-8'))

# 指定本文圖片
fp = open('test.jpg', 'rb')
msgImageLocal = MIMEImage(fp.read())
fp.close()
# 定義圖片ID,在 HTML 文本中引用,和前面html對應
msgImageLocal.add_header('Content-ID', '<imagelocal>')
msg.attach(msgImageLocal)


# 調用url,獲取其內容圖像
url = "https://img-blog.csdnimg.cn/20190308091244669.png"
page = requests.get(url)
picture = page.content

msgImageUrl = MIMEImage(picture)
# 定義圖片ID,在 HTML 文本中引用
msgImageUrl.add_header('Content-ID', '<imageurl>')
msg.attach(msgImageUrl)
# 發送郵件

try:
    smtpObj.sendmail(username, recievername, msg.as_string())
    print("郵件發送成功")
except:
    print("Error: 無法發送郵件")

# 退出服務器
smtpObj.quit()

結果如下所示:
基礎郵件發送

1.2.4 添加附件發送郵件

import smtplib
# 設置暗文
import getpass

# 設置郵件編碼格式
from email.header import Header

# 多文件
# 具體見 https://docs.python.org/3/library/email.mime.html
# 詳細說明見 https://blog.csdn.net/qdujunjie/article/details/8995334
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
# 設置圖像
from email.mime.image import MIMEImage
# 設置郵件內容
from email.mime.text import MIMEText
import os


# 連接到SMTP服務器
# SMTP服務器名,服務端口是一個整數值,幾乎總是587
smtpObj = smtplib.SMTP('smtp-mail.outlook.com', 587)

# starttls()讓SMTP 連接處於TLS模式。返回值220告訴你,該服務器已準備就緒。
print(smtpObj.starttls())

# 提示輸入用戶名
username = getpass.getpass(prompt="input username:")
# 提示輸入密碼
password = getpass.getpass(prompt="input password:")


# 收件人
recievername = ['[email protected]', '[email protected]']
# 返回值235表示認證成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)


# 設置多內容
msg = MIMEMultipart()


#郵件正文內容
# 第二個參數爲文件子格式一般都是固定的
msg.attach(MIMEText('正文', 'plain', 'utf-8'))
# 標題
msg['Subject'] = Header('標題', 'utf-8')


# 具體用哪種MIME文件格式看附件格式
# 按照上面提供的鏈接確定函數內容

# 構造附件Text,傳送當前目錄下的 test.txt 文件
# 參數分別是文件路徑,文件子類型,編碼格式
attText = MIMEText(open('test.txt', 'rb').read(), 'base64', 'utf-8')
# 設置http的Content-Type
# 常用Content-Type類型見https://www.cnblogs.com/keyi/p/5833388.html
# 如果Content-Type不知道就設置爲application/octet-stream
attText["Content-Type"] = 'application/octet-stream'
# filename郵件中文件顯示名字
attText["Content-Disposition"] = 'attachment; filename="test.txt"'
msg.attach(attText)

# 構造附件Image,傳送當前目錄下的test.jpg文件
attImage = MIMEImage(open('test.jpg', 'rb').read(), 'jpg')
attImage["Content-Type"] = 'application/x-jpg'
# filename郵件中文件顯示名字
attImage["Content-Disposition"] = 'attachment; filename="test.jpg"'
msg.attach(attImage)

# 構造附件Zip,傳送當前目錄下的test.zip文件
# 防止文件不存在
if os.path.exists('test.zip'):
    attZip = MIMEApplication(open('test.zip', 'rb').read())
    attZip["Content-Type"] = 'application/zip'
    # filename郵件中文件顯示名字
    attZip["Content-Disposition"] = 'attachment; filename="test.zip"'
    msg.attach(attZip)


# 發送郵件
try:
    smtpObj.sendmail(username, recievername, msg.as_string())
    print("郵件發送成功")
except:
    print("Error: 無法發送郵件")

# 退出服務器
smtpObj.quit()

結果如下所示:
基礎郵件發送

2. 處理電子郵件

在Python 中,查找和獲取電子郵件是一個多步驟的過程,需要第三方模塊imapclient 和pyzmail。處理郵件主要步驟如下:

>>> import imapclient
# 連接到IMAP 服務器
>>> imapObj = imapclient.IMAPClient('imap.gmail.com', ssl=True)
# 輸入賬號密碼
>>> imapObj.login('[email protected]', 'MY_SECRET_PASSWORD')
'[email protected] Jane Doe authenticated (Success)'
# 選擇文件夾
>>> imapObj.select_folder('INBOX', readonly=True)
# 執行搜索
>>> UIDs = imapObj.search(['SINCE''05-Jul-2014'])
>>> UIDs0
[40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039, 40040, 40041]
# 取郵件
>>> rawMessages = imapObj.fetch([40041], ['BODY[]', 'FLAGS'])
>>> import pyzmail
# 讀郵件
>>> message = pyzmail.PyzMessage.factory(rawMessages[40041]['BODY[]'])
>>> message.get_subject()
'Hello!'
# 獲得郵件發送者
>>> message.get_addresses('from')
[('Edward Snowden', '[email protected]')]
>>> message.get_addresses('to')
[(Jane Doe', 'jdoe@example.com')]
>>> message.get_addresses('cc')
[]
>>> message.get_addresses('bcc')
[]
>>> message.text_part != None
True
>>> message.text_part.get_payload().decode(message.text_part.charset)
'Follow the money.\r\n\r\n-Ed\r\n'
>>> message.html_part != None
True
>>> message.html_part.get_payload().decode(message.html_part.charset)
'<div dir="ltr"><div>So long, and thanks for all the fish!<br><br></div>-
Al<br></div>\r\n'
# 登出
>>> imapObj.logout()

對於常用的時間模塊具體。python設置時間主要time模塊和datetime模塊。通過import time和import datetime調用time模塊和datetime模塊。常用函數如下:

函數 用途 備註
time.time()函數 返回自Unix紀元時(協調世界時UTC)的秒數 Unix 紀元時間:1970 年1 月1 日0 點,即協調世界時
time.sleep(n) 讓程序暫停一下n秒 按Ctrl-C 不會中斷time.sleep()調用
datetime.datetime.now() 返回當前的日期和時間 包含當前時刻的年、月、日、時、分、秒和微秒
datetime.datetime(2015, 10, 21, 16, 29, 0) 得到特定時刻的datetime 對象
datetime.datetime.fromtimestamp(time) 將Unix 紀元時間戳轉換爲datetime對象
delta = datetime.timedelta(days=11, hours=10, minutes=9, seconds=8) 創建timedelta 數據類型表示一段時間
delta.days/delta.seconds/delta.microseconds 獲得timedelta對象擁有的總時間以天、秒、微秒來表示
delta.total_seconds() 返回只以秒錶示的delta時間
strftime() 將datetime 對象轉換爲字符串
strptime() 將字符串轉換成 datetime 對象

3 參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章