每月18号左右,我都会接收到来自于公寓的缴费通知,提醒是时候预缴下个月的房租了,哈哈,真贴(心)心(痛)啊!
我在想在提醒用户缴费时,公寓的工作人员不会是一个个发信息通知的吧?如果是这样,这操作也太 low 了,如果有上百个人没有预缴,岂不是要累死工作人员啊。那么,Python 是不是可以提升办公的效率呢。因此,研究研究 Python 如何实现电子邮件通知用户及时缴费的?
1、数据源准备:
首先,肯定得有数据源啊。那可以理解为,公寓管理系统上应该能导出一份用户待缴费信息的 Excel 表格,假设数据是这样的:
从导出的表格可以看到,下个月的房租只有小张和二王没有及时的缴纳,那么就向未缴纳8月份房租的用户发送电子邮件,提醒他们!
接着,读取表格的数据并判断要发送邮件的对象,以及邮件发送的提醒信息模板,假设模板是这样的:
模板上的xxx,yyy,zz都可以从表格拿到,今天日期使用time模块就行,这样万事俱备,只差发送邮件了。
2、邮件发送测试:
我们可以用 Python 内置的 smtplib 模块和 mail 模块实现自动发送邮件的功能。先来测试一下本地是否支持发送邮件,测试代码如下:
- import smtplib
- import time
- from email.header import Header
- from email.mime.text import MIMEText
-
- def send_mails_localhost(from_mail, to_mail_list, user_name, note_content, part, sub):
- msg = MIMEText(note_content, 'plain', 'utf-8')
- msg['From'] = Header(part, 'utf-8')
- msg['To'] = Header(user_name, 'utf-8')
- msg['Subject'] = Header(sub, 'utf-8')
- with smtplib.SMTP('localhost') as smtObj:
- smtObj.sendmail(from_mail, to_mail_list, msg.as_string())
- print('邮件成功发送!')
- if __name__ == '__main__':
- from_mail = '86*****97@qq.com'
- to_mail_list = ['150******50@163.com']
- user_name = '小张'
- room_no = '509'
- month = '8'
- part = '公寓财务处'
- sub = f'公寓用户{month}月份缴费通知提醒'
- note_content = f'亲爱的{user_name},你好:系统显示,您所在的房间号{room_no}还没有及时缴纳{month}月份的房租,收到邮件通知后,请及时缴纳,谢谢配合!\
- {part}\
- {time.strftime("%Y-%m-%d %H:%M", time.localtime())}'
- # 本机支持SMTP服务的话,则使用localhost发送
- send_mails_localhost(from_mail, to_mail_list, user_name, note_content, part, sub)
从测试结果看,本地无法使用 SMTP 服务:
那就使用邮件服务商(如QQ,网易等)提供的 SMTP 服务发送邮件。以QQ邮箱为例,先登陆 QQ 邮箱,开启 SMTP 服务,步骤如下:
设置-账户-POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务:
开启 SMTP 服务,并发送短信进行邮件客户端配置,最终成功开启 POP3/SMTP 服务,在第三方客户端登录时,密码框请输入以下授权码:xxxxxxxxx。
改进上面的测试代码,加入QQ邮件服务器的相关配置:(这里的密码是配置生成的授权码)
- def send_mails_QQsmtp(from_mail, to_mail_list, user_name, note_content, part, sub,
- mail_host, mail_port, mymail_user, mymail_pwd):
- # mail msg 设置
- msg = MIMEText(note_content, 'plain', 'utf-8')
- msg['From'] = Header(part, 'utf-8')
- msg['To'] = Header(user_name, 'utf-8')
- msg['Subject'] = Header(sub, 'utf-8')
- with smtplib.SMTP_SSL(mail_host, mail_port) as smtObj:
- # 登陆发件人邮箱(公寓财务处邮箱)
- smtObj.login(mymail_user, mymail_pwd)
- # 发送
- smtObj.sendmail(from_mail, to_mail_list, msg.as_string())
- print('邮件成功发送!')
-
-
- if __name__ == '__main__':
- ......
- # 使用邮件服务商提供的SMTP服务,需要设置服务器/端口号/用户名/口令(即授权码)等
- QQmail_host, QQmail_port, QQmail_user, QQmail_pwd = 'smtp.qq.com', 465, from_mail, 'xxxxxxxx'
- send_mails_QQsmtp(from_mail, to_mail_list, user_name, note_content, part, sub,
- QQmail_host, QQmail_port, QQmail_user, QQmail_pwd)
公寓使用 QQ 邮箱发送给用户邮箱发送邮件,QQ 邮箱测试结果:
基于上述的测试结果,最终通过 pandas 提取出 Excel 表格需要的数据,通过公寓的 QQ 邮箱发送给不同的邮箱用户。
3、实现发邮件的完整代码:
完整实现的代码,如下:
-
- import smtplib
- import time
- import pandas as pd
- from email.header import Header
- from email.mime.text import MIMEText
-
- """
- QQ邮箱发邮件
- """
- def send_mails_QQsmtp(from_mail, to_mail, note_content, apartment_name, subject,
- user_name, mail_host, mail_port, mymail_user, mymail_pwd):
- print(f'正在向{to_mail}发生邮件......')
- # mail msg 设置
- msg = MIMEText(note_content, 'plain', 'utf-8')
- msg['From'] = Header(apartment_name, 'utf-8')
- msg['To'] = Header(user_name, 'utf-8')
- msg['Subject'] = Header(subject, 'utf-8')
- with smtplib.SMTP_SSL(mail_host, mail_port) as smtObj:
- # 登陆发件人邮箱(公寓财务处邮箱)
- smtObj.login(mymail_user, mymail_pwd)
- # 发送
- smtObj.sendmail(from_mail, to_mail, msg.as_string())
- print('邮件成功发送!')
-
- """
- 从Excel读取未缴费的用户信息,并封装返回用户信息
- 例如:[['15077925650@163.com', '小张', 509, '未缴费'], ['862980997@qq.com', '二王', 511, '未缴费']]
- """
- def get_excelInfo(excel_path):
- lists = []
- df = pd.read_excel(excel_path)
- # 按列查询,筛选出需要的列
- df = df[['姓名', '房间号', '邮件', "八月"]]
- # 取满足'未缴费'的行记录
- rows = df.loc[df["八月"] == '未缴费']
- for index in rows.index.values:
- values = [rows.loc[index]['邮件'], rows.loc[index]['姓名'], rows.loc[index]['房间号'], rows.loc[index]['八月']]
- lists.append(values)
- return lists
-
- if __name__ == '__main__':
- """读取Excel"""
- user_infos = get_excelInfo('C:\\Users\\weixiangxiang\\Desktop\\公寓用户缴费名单202108.xlsx')
- print(user_infos)
- """公寓信息"""
- apartment_dict = {
- 'from_mail': '2402637412@qq.com',
- #密码pwd
- '密码': '',
- 'sub': '公寓用户月份缴费通知提醒',
- 'apartment_name': '公寓财务处'
- }
- """查询用户信息发送邮件"""
- for user_info in user_infos:
- #使用邮件服务商提供的SMTP服务,需要设置服务器/端口号/用户名/口令(即授权码)等
- QQmail_host, QQmail_port = 'smtp.qq.com', 465
- QQmail_user = apartment_dict.get('from_mail')
- QQmail_pwd = apartment_dict.get('pwd')
- apartment_name = apartment_dict.get('apartment_name')
- sub = apartment_dict.get('sub')
- to_mail = user_info[0] # 收件邮箱
- user_name = user_info[1] # 亲爱的xxx用户
- room_no = user_info[2] # 房间号
- note_content = f'亲爱的{user_name},你好:系统显示,您所在的房间号{room_no}还没有及时缴纳8月份的房租,收到邮件通知后,请及时缴纳,谢谢配合!\
- \n{apartment_name}\
- \n{time.strftime("%Y-%m-%d %H:%M", time.localtime())}'
- send_mails_QQsmtp(QQmail_user, to_mail, note_content, apartment_name, sub,
- user_name, QQmail_host, QQmail_port, QQmail_user, QQmail_pwd)
测试结果,如下:
二王收到的邮件:
小张收到的邮件:
这是功能我去年周末琢磨的,目前仍亲测可用。Python 实现发送电子邮件也是很常见的操作,可以提升办公效率~