[python]《Python编程快速上手:让繁琐工作自动化》学习笔记6
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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, bmx.example.com at your service, [216.172.148.131]\\nSIZE 35882577\\
n8BITMIME\\nSTARTTLS\\nENHANCEDSTATUSCODES\\nCHUNKING)
# 开始TLS 加密
smtpObj.starttls()
(220, b2.0.0 Ready to start TLS)
# 登陆账号
smtpObj.login(bob@example.com, MY_SECRET_PASSWORD)
(235, b2.7.0 Accepted)
# 发送邮件
smtpObj.sendmail(bob@example.com, alice@example.com, Subject: So
long.\\nDear Alice, so long and thanks for all the fish. Sincerely, Bob)
# 断开连接
smtpObj.quit()
(221, b2.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 服务器常用域名见:
在邮件主体中会常常包含 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 = [abc@example.com, 123456@qq.com]
# 返回值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 = [abc@example.com, 123456@qq.com]
# 返回值235表示认证成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)
mail_msg = """
<p>邮件正文</p>
<p><a href的博客</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
# 详细说
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 = [abc@example.com, 123456@qq.com]
# 返回值235表示认证成功
loginStatus = smtpObj.login(username, password)
print(loginStatus)
# 邮件的 HTML 文本中一般邮件服务商添加外链是无效的,但不是绝对的
# 添加图像方式如下:
# 正文内容
# cid表示content-id
mail_msg = """
<p>邮件正文</p>
<p><a href="我的博客</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
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
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 = [abc@example.com, 123456@qq.com]
# 返回值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-Typ
# 如果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(my_email_address@gmail.com, MY_SECRET_PASSWORD)
my_email_address@gmail.com 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, esnowden@nsa.gov)]
>>> 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 参考
- https://docs.python.org/3/library/email.mime.html
- https://www.runoob.com/python/python-email.html
-
- https://www.liaoxuefeng.com/wiki/1016959663602400/1017790702398272
- https://tools.ietf.org/html/rfc3501.html#section-6.4.4
以上是关于[python]《Python编程快速上手:让繁琐工作自动化》学习笔记6的主要内容,如果未能解决你的问题,请参考以下文章
Python编程快速上手-让繁琐工作自动化-第二章习题及其答案