[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('bob@example.com', 'MY_SECRET_PASSWORD')
(235, b'2.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, 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 = ['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="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 = ['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="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 = ['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-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('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://www.cnblogs.com/luohenyueji/p/16970292.html
![](https://gitcode.net/LuohenYJ/article_picture_warehouse/-/raw/main/wechat/content/%E5%8A%A0%E6%B2%B9%E9%B8%AD.gif)