- 内容提要
- 作者简介
- 技术评审者简介
- 致谢
- 译者序 会编程的人不一样
- 前言
- 本书的读者对象
- 编码规范
- 什么是编程
- 本书简介
- 下载和安装 Python
- 启动 IDLE
- 如何寻求帮助
- 聪明地提出编程问题
- 小结
- 第一部分 Python 编程基础
- 第1章 Python 基础
- 第2章 控制流
- 第3章 函数
- 第4章 列表
- 第5章 字典和结构化数据
- 第6章 字符串操作
- 第二部分 自动化任务
- 第7章 模式匹配与正则表达式
- 第8章 读写文件
- 第9章 组织文件
- 第10章 调试
- 第11章 从 Web 抓取信息
- 第12章 处理 Excel 电子表格
- 第13章 处理 PDF 和 Word 文档
- 第14章 处理 CSV 文件和 JSON 数据
- 第15章 保持时间、计划任务和启动程序
- 第16章 发送电子邮件和短信
- 第17章 操作图像
- 第18章 用 GUI 自动化控制键盘和鼠标
- 附录A 安装第三方模块
- 附录B 运行程序
- 附录C 习题答案
16.5 项目:向会员发送会费提醒电子邮件
假定你一直“自愿”为“强制自愿俱乐部”记录会员会费。这确实是一项枯燥的工作,包括维护一个电子表格,记录每个月谁交了会费,并用电子邮件提醒那些没交的会员。不必你自己查看电子表格,而是向会费超期的会员复制和粘贴相同的电子邮件。你猜对了,让我们编写一个脚本,帮你完成任务。
在较高的层面上,下面是程序要做的事:
· 从Excel电子表格中读取数据。
· 找出上个月没有交费的所有会员。
· 找到他们的电子邮件地址,向他们发送针对个人的提醒。
这意味着代码需要做到以下几点:
· 用openpyxl模块打开并读取Excel文档的单元格(处理Excel文件参见第12章)。
· 创建一个字典,包含会费超期的会员。
· 调用smtplib.SMTP()、ehlo()、starttls()和login(),登录SMTP服务器。
· 针对会费超期的所有会员,调用sendmail()方法,发送针对个人的电子邮件提醒。
打开一个新的文件编辑器窗口,并保存为sendDuesReminders.py。
第1步:打开Excel文件
假定用来记录会费支付的 Excel 电子表格看起来如图 16-2 所示,放在名为duesRecords.xlsx的文件中。可以从http://nostarch.com/automatestuff/下载该文件。
图16-2 记录会员会费支付电子表格
该电子表格中包含每个成员的姓名和电子邮件地址。每个月有一列,记录会员的付款状态。在成员交纳会费后,对应的单元格就记为paid。
该程序必须打开duesRecords.xlsx,通过调用get_highest_column()方法,弄清楚最近一个月的列(可以参考第12章,了解用openpyxl模块访问Excel电子表格文件单元格的更多信息)。在文件编辑器窗口中输入以下代码:
#! python3 # sendDuesReminders.py - Sends emails based on payment status in spreadsheet. import openpyxl, smtplib, sys # Open the spreadsheet and get the latest dues status. ❶ wb = openpyxl.load_workbook('duesRecords.xlsx') ❷ sheet = wb.get_sheet_by_name('Sheet1') ❸ lastCol = sheet.get_highest_column() ❹ latestMonth = sheet.cell(row=1, column=lastCol).value # TODO: Check each member's payment status. # TODO: Log in to email account. # TODO: Send out reminder emails.
导入openpyxl、smtplib和sys模块后,我们打开duesRecords.xlsx文件,将得到的Workbook对象保存在wb中❶。然后,取得Sheet 1,将得到的Worksheet对象保存在sheet中❷。既然有了Worksheet对象,就可以访问行、列和单元格。我们将最后一列保存在lastCol中❸,然后用行号1和lastCol来访问应该记录着最近月份的单元格。取得该单元格的值,并保存在latestMonth 中❹。
第2步:查找所有未付成员
一旦确定了最近一个月的列数(保存在lastCol中),就可以循环遍历第一行(这是列标题)之后的所有行,看看哪些成员在该月会费的单元格中写着paid。如果会员没有支付,就可以从列1和2中分别抓取成员的姓名和电子邮件地址。这些信息将放入unpaidMembers字典,它记录最近一个月没有交费的所有成员。将以下代码添加到sendDuesReminder.py中。
#! python3 # sendDuesReminders.py - Sends emails based on payment status in spreadsheet. --snip-- # Check each member's payment status. unpaidMembers = {} ❶ for r in range(2, sheet.get_highest_row() + 1): ❷ payment = sheet.cell(row=r, column=lastCol).value if payment != 'paid': ❸ name = sheet.cell(row=r, column=1).value ❹ email = sheet.cell(row=r, column=2).value ❺ unpaidMembers[name] = email
这段代码设置了一个空字典unpaidMembers,然后循环遍历第一行之后所有的行❶。对于每一行,最近月份的值保存在payment中❷。如果payment不等于'paid',则第一列的值保存在name中❸,第二列的值保存在email中❹,name和email添加到unpaidMembers中❺。
第3步:发送定制的电子邮件提醒
得到所有未付费成员的名单后,就可以向他们发送电子邮件提醒了。将下面的代码添加到程序中,但要代入你的真实电子邮件地址和提供商的信息:
#! python3 # sendDuesReminders.py - Sends emails based on payment status in spreadsheet. --snip-- # Log in to email account. smtpObj = smtplib.SMTP('smtp.gmail.com', 587) smtpObj.ehlo() smtpObj.starttls() smtpObj.login('my_email_address@gmail.com', sys.argv[1])
调用smtplib.SMTP()并传入提供商的域名和端口,创建一个SMTP对象。调用ehlo()和starttls(),然后调用login(),并传入你的电子邮件地址和sys.argv[1],其中保存着你的密码字符串。在每次运行程序时,将密码作为命令行参数输入,避免在源代码中保存密码。
程序登录到你的电子邮件账户后,就应该遍历unpaidMembers字典,向每个会员的电子邮件地址发送针对个人的电子邮件。将以下代码添加到sendDuesReminders.py:
#! python3 # sendDuesReminders.py - Sends emails based on payment status in spreadsheet. --snip-- # Send out reminder emails. for name, email in unpaidMembers.items(): ❶ body = "Subject: %s dues unpaid.\nDear %s,\nRecords show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!'" % (latestMonth, name, latestMonth) ❷ print('Sending email to %s...' % email) ❸ sendmailStatus = smtpObj.sendmail('my_email_address@gmail.com', email, body) ❹ if sendmailStatus != {}: print('There was a problem sending email to %s: %s' % (email, sendmailStatus)) smtpObj.quit()
这段代码循环遍历unpaidMembers中的姓名和电子邮件。对于每个没有付费的成员,我们用最新的月份和成员的名称,定制了一条消息,并保存在body中❶。我们打印输出,表示正在向这个会员的电子邮件地址发送电子邮件❷。然后调用sendmail(),向它传入地址和定制的消息❸。返回值保存在sendmailStatus中。
回忆一下,如果SMTP服务器在发送某个电子邮件时报告错误,sendmail()方法将返回一个非空的字典值。for循环最后部分在❹行检查返回的字典是否非空,如果非空,则打印收件人的电子邮件地址以及返回的字典。
程序完成发送所有电子邮件后,调用quit()方法,与SMTP服务器断开连接。
如果运行该程序,输出会像这样:
Sending email to alice@example.com... Sending email to bob@example.com... Sending email to eve@example.com...
收件人将收到如图16-3所示的电子邮件。
图16-3 从sendDuesReminders.py自动发送的电子邮件
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论