EZGmail模块,收发GMail。Python中标准的邮件模块smtplib 和 imapclient
通过GMAIL API收发邮件
Gmail占1/3邮件客户端市场,真没想到。
EZGmail是作者基于Gmail API自己写的。
安装模块:
$ pip3 install --user --upgrade ezgmail
首先在Gmail中开一账户,然后访问网页,单击Enable the Gmail API
启用API。
然后下载client configuration,实际是一文件credentials.json
,此文件不可分享他人,因其等同于你的密码,可以访问你的Gmail。
将此JSON文件置于运行Python文件的目录。
>>> import ezgmail, os
>>> os.chdir(r'C:\Users\yyxiao\Downloads')
>>> ezgmail.init() # 授权,成功后提示信息:The authentication flow has completed.
ezgmail.init会打开浏览器,访问Google网站,让Gmail授权给Python应用QuickStart。
授权成功后,会生成token.json,之后就可以直接发送邮件了。
意思到了就好了,感觉有点危险,还是建议用个不重要的账户测试。
等有网再说吧。
SMTP
SMTP = Simple Mail Transfer Protocol,支持模块为smtplib
SMTP只负责发邮件,IMAP负责搜邮件。支持模块为imapclient
发送邮件
本节我们使用的例子是foxmail,邮箱设置帮助见这里。
从这个页面,可知其SMTP服务器为smtp.qq.com
,端口为465(SSL)或587(TLS)。
>>> import smtplib
# 如果smtp server不支持TLS,则需使用smtplib.SMTP_SSL()
>>> smtpObj = smtplib.SMTP('smtp.qq.com', 587) # 连接到smtp server
>>> smtpObj.ehlo() # 发送hello信息,250表示成功
(250, b'newxmesmtplogicsvrszc3.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME')
>>> smtpObj.starttls() # 启动TLS加密
(220, b'Ready to start TLS from 2409:8a00:18b8:f360:ccfc:409d:ad90:bef9 to newxmesmtplogicsvrszc3.qq.com.')
>>> smtpObj.login(我的邮箱, 密码)
...
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (535, b'Login Fail. Please enter your authorization code to login. More information in http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256')
>>> smtpObj.sendmail('发件人','收件人','邮件内容')
>>> smtpObj.quit()
(221, b'Bye.')
login()失败是由于使用第三方客户端登录时,不能直接使用密码,而必须使用16位的授权码,授权码的开通详见这里。
IMAP
imap用来收邮件,官方模块是imaplib,第三方更易用的模块为imapclient。pyzmail模块将复杂的邮件格式转换为字符串。
$ pip3 install --user -U imapclient==2.1.0
$ pip3 install --user -U pyzmail36==1.0.4
通过IMAP收取和删除邮件
由于IMAP只是收邮件,安全级别比SMTP要低。因此可以直接用密码登录,而无需向SMTP那样需要授权码。
>>> import imapclient
>>> import pprint
>>> imapObj = imapclient.IMAPClient('imap.qq.com', ssl=True)
>>> imapObj.login('我的邮箱', '****!')
b'Success login ok'
>>> pprint.pprint(imapObj.list_folders())
[((b'\\NoSelect', b'\\HasChildren'), b'/', '其他文件夹'),
((b'\\HasNoChildren',), b'/', 'INBOX'),
((b'\\HasNoChildren',), b'/', 'Sent Messages'),
((b'\\HasNoChildren',), b'/', 'Drafts'),
((b'\\HasNoChildren',), b'/', 'Deleted Messages'),
((b'\\HasNoChildren',), b'/', 'Junk'),
((b'\\HasNoChildren',), b'/', '其他文件夹/QQ邮件订阅'),
((b'\\HasNoChildren',), b'/', 'Archive')]
# 如果希望fetch的邮件标记为已读,则将readonly设为False
>>> imapObj.select_folder('INBOX', readonly=True)
{b'PERMANENTFLAGS': (), b'EXISTS': 999, b'RECENT': 0, b'UNSEEN': [b'180'], b'UIDVALIDITY': 1384917520, b'UIDNEXT': 6116, b'FLAGS': (b'\\Answered', b'\\Flagged', b'\\Deleted', b'\\Draft', b'\\Seen'), b'READ-ONLY': [b'']}
>>> UIDs = imapObj.search(['SINCE 01-Feb-2020'])
>>> UIDs
[..., 6104, 6105, 6106, 6107, 6108, 6109, 6110, 6112, 6115]
>>> rawMessages = imapObj.fetch([6104], ['BODY[]', 'FLAGS'])
>>> import pyzmail
>>> message = pyzmail.PyzMessage.factory(rawMessages[6104][b'BODY[]'])
>>> message.get_subject()
'已在“****iPhone”上停用“查找”'
>>> message.get_addresses('from')
[('Find My', 'noreply@email.apple.com')]
>>> message.get_addresses('to')
[('我的邮箱', '我的邮箱')]
>>> message.get_addresses('cc')
[]
>>> message.get_addresses('bcc')
[]
>>> message.text_part != None # 有的邮件只有文本正文或HTML正文,或兼而有之
True
>>> message.text_part.get_payload().decode(message.text_part.charset)
'已在“****iPhone”上停用“查找”\r\n\r\n停用“查找”后,此设备便无法再被定位、设为“丢失模式”,或通过 icloud.com/find (https://www.icloud.com/find) 或“查找” App 进行远程抹掉操作。\r\n\r\n此外,其他人将不再需要您的 Apple ID 和密码来抹掉、重新激活和使用您的 iPhone。\r\n\r\niCloud 是 Apple 的一项服务。中国内地的 iCloud 由云上贵州运营。\r\nApple ID: https://appleid.apple.com/choose-your-country/\r\n支持: https://www.apple.com/support/icloud/ww\r\n条款与条件: https://www.apple.com/legal/internet-services/icloud/ww/\r\n客户隐私政策: https://www.apple.com/legal/privacy/szh/'
>>> message.html_part.get_payload().decode(message.html_part.charset)
...
>>> imapObj.logout()
b'LOGOUT received'
此外,IMAPClient.search()功能强大,可以按日期,邮件大小,邮件主题和内容,收发抄送、暗送人,已看未看,是否回复,是否删除等等。详见帮助。
>>> UIDs = imapObj.search(['TEXT "instagram"'])
另外,支持组合搜索。
默认搜索结果限制10000字节,以下可以增加:
imaplib._MAXLINE = 10000000
>>> UIDs = imapObj.search([u'UNSEEN'])
>>> UIDs
[..., 6110]
>>> len(UIDs)
179
>>> rawMessages = imapObj.fetch([6110], ['BODY[]'])
>>> import pprint
>>> pprint.pprint(rawMessages)
删除邮件用delete_messages()
,永久删除用expunge()
项目: 发送会员到期提醒邮件
从Excel表格中读取会员名单,上个月没交费的发个性化提醒邮件。
通过短信邮件网关发生文本消息
这个得购买服务吧。
通过TWILIO发生文本消息
Twilio 提供短信网关服务。
本节只对美国用户有效。
注册账号,获取Authorization Token,然后就可以发消息了。
项目: “JUST TEXT ME” 模块
就是通过短信发通知。