项目背景
新公司要求每天都要写日报表,每周五写周报表,每月最后一个周五写月报表。具体流程如下:
- 复制Excel报表模板,修改名称为当天日期
- 打开Excel填写当天的工作,并保存;
- 复制Excel表格内容,并打开Foxmail;
- 新建邮件,并填写收件人、抄送人、主题、邮件内容,每天都一样,只需要更改日期就可以。
- 粘贴第3步中复制的Excel内容;
- 添加第2步中创建的Excel为附件,后来得知新政策实施后不需要添加这个附件了,anyway,程序已经写完了当时。但是周报和月报还是需要添加附件的。
- 点击发送
作为前程序员,无法忍受这重复性的,每次修改都不大的无意义的劳动,遂决定写个程序将所有重复性的劳动搞定。
基础知识
- Python,该程序是基于python编程语言来进行编写的,好处就不多说了
- email,这个是python自带的包,可以直接使用,作用是对邮件内容进行编码
- smtplib,同样也是python自带的包,作用是进行邮件的发送,常见的邮件服务器都支持smtp协议,该包就是利用该协议进行邮件的发送,由于我公司邮件服务器支持ssl加密,所以使用的是smtplib中SMTP_SSL(),这也导致了一个bug,后面再说
- openpyxl 这个包是第三方包,可以使用pip命令进行安装,作用主要是进行Excel文件的操作,而且操作方法比较简单,本文只关心邮件,openpyxl的使用方法回头再说。
Talk is cheap,show me your code
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#导入需要用到的包
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
def send_email(email_content, userinfo):
sender = '发送者的邮箱'
# 接收邮箱,可设置为你的QQ邮箱或者其他邮箱
# 接收者的邮箱是一个数组,即可以设置多个接受人 ,同时向多个邮箱进行发送
receivers = ["接收者的邮箱"]
# 出于兼容性的考虑
# 一般在发送超文本格式内容的同时会同时发送一个纯文本内容的副本
# 如果邮件中同时存在纯文本和超文本内容
# 则邮件需要在Content-Type域中定义multipart/alternative类型
message = MIMEMultipart('alternative')
# 设置发送人,注意此处仅仅是一个字符串作为邮件解析展示使用
message['From'] = "发件人"
# 设置收件人
message['To'] = "收件人"
# 设置抄送人,抄送人每个接收到邮件的人都可以看到
message['Cc'] = "抄送人"
# 设置密送人,密送人为秘密抄送,收件人看不到该人的信息
message['Bcc'] = "vvaa00@126.com"
# MIMEText方法接受三个参数:
# 第一个为文本内容,即需要发送的内容
# 第二个设置文本格式,plain代表纯文本、html表示富文本等
# 第三个设置文本编码,常见的入utf-8、unicode、gb2312等
msg = MIMEText(email_content, 'html', 'utf-8')
# 添加邮件正文内容
message.attach(msg)
# 设置邮件标题
subject = '邮件标题'
message['Subject'] = subject
# 第三方 SMTP 服务
mail_host = "mail.XXXX.cn" # 设置服务器
mail_user = 用户名 # 用户名
mail_pass = 密码 # 口令
# 由于公司使用ssl加密,所以此处使用SMTP_SSL()创建对象
smtpObj = smtplib.SMTP_SSL()
# 使用connect创建连接,ssl加密服务器使用的465端口
smtpObj.connect(mail_host, 465) # 25 为 SMTP 端口号
try:
# 登陆服务器
smtpObj.login(mail_user, mail_pass)
#发送邮件
smtpObj.sendmail(sender, receivers, message.as_string())
print("success")
except smtplib.SMTPException:
print("failed")
# 无论是否发送成功都要执行quit()方法,断开连接
smtpObj.quit()
input("回车退出")
def main():
print("日总结邮件发送系统0.1版本正式上线运行")
print("没有的内容直接回车就可以")
print("内容较多时,请不要回车换行")
content = Content()
# 使用input输入日志内容
content.didian = input("请输入工作地点:")
email_content = "邮件内容"
userinfo = {
"email": xxx,
"pwd":xxx
}
# modify_excel(content)
send_email(email_content, userinfo)
if __name__ == '__main__':
main()
坑
上述示例代码,是在python3.6.4环境下进行编写,直到最近(2018年9月27日)换了工作电脑,安装了python3.7.0环境,再运行此代码便出现错误,具体信息记不清楚,大体错误内容如下:
server_host can not be empty or start with a dot
直译:服务主机不能为空或以“.”开头
然后开启调试模式,找来找去,终于找到问题。
在python3.7.0版本中,smtplib包确实还存在connect()方法,但是,当使用SMTP_SSL()创建对象时,由于没有对host、port等信息进行初始化,所以在执行connect()方法时,其中的host参数为空。且,在创建SMTP_SSL()对象时如果进行初始化后,便不再需要调用connect()方法进行连接,所以修改代码如下:
# python3.6.4版本创建连接如下
smtpObj = smtplib.SMTP_SSL()
smtpObj.connect(mail_host, 465) # 25 为 SMTP 端口号
# python3.7.0版本创建连接如下
# 不再需要执行connect()方法进行连接
smtpObj = smtplib.SMTP_SSL(mail_host, 465)
网友评论