[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 参考

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