最近工作中的一个项目有自动发送一些信息邮件到指定邮箱的需求,那么如何用Python来实现自动发送邮件的功能呢?接下来就简单的来说一下。

Python SMTP发送邮件

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议 ,说白了就是发送邮件的协议,python的smplib库对SMTP协议进行了简单的封装,提供了对SMTP的支持,可以发送纯文本邮件、HTML文件以及带附件的邮件。
首先我们构建一个SendEmailManager类,也是遵循着面向对象编程的思想来做,大体结构如下:

class SendEmailManager(object):def __init__(self, **kwargs):# 初始化参数...def _get_conf(self, key):# 获取配置参数...def _init_conf(self):# 初始化配置参数...def _login_email(self):# 登录邮箱服务器...def _make_mail_msg(self):# 构建文本邮件对象...def do_send_mail(self):# 邮件发送...

def __init__(self, **kwargs)

类的初始化函数,可以用来设置对象属性,并给予初始值,可以是参数或者固定值 ,其中参数 **kwargs 是将一个可变的关键字参数的字典传给函数实参,这里里我们主要是对SMTP服务器(这里使用qq邮箱)、发送邮件的代理邮箱、在邮箱中设置的客户端授权密码、可变参数进行一些初始化。具体代码如下:

# SMTP服务器,这里使用qq邮箱,其他邮箱自行百度
EMAIL_HOST = 'smtp.qq.com'
# 发送邮件的代理邮箱
EMAIL_HOST_USER = 'xxxx@xxxx.com'
# 在邮箱中设置的客户端授权密码, 注意这里不是邮箱密码,关于如何获取邮箱授权码,请自行百度~~~
EMAIL_HOST_PASSWORD = 'xxxxxxxxxxxxx'
def __init__(self, **kwargs):# 初始化参数self.email_host = EMAIL_HOSTself.email_host_user = EMAIL_HOST_USERself.email_host_pass = EMAIL_HOST_PASSWORDself.kwargs = kwargs

def _get_conf(self, key)

主要负责通过key读取 可变参数self.kwargs 字典里的值,供其他函数使用。

def _get_conf(self, key):# 获取配置参数value = self.kwargs.get(key)if key != "attach_file_list" and (value is None or value == ''):raise Exception("configuration parameter '%s' cannot be empty" % key)return value

def _init_conf(self)

该函数主要负责初始化 函数_get_conf 返回的配置参数, 以便接下来的函数可以调用相关配置参数。

def _init_conf(self):# 初始化配置参数print(self._get_conf('receives'))self.receives = self._get_conf('receives')self.msg_subject = self._get_conf('msg_subject')self.msg_content = self._get_conf('msg_content')self.msg_from = self._get_conf('msg_from')# attachmentself.attach_file_list = self._get_conf('attach_file_list')

def _login_email(self)

登录邮件服务器, 我这里登陆的是qq邮箱的服务器,端口号为465,其他邮箱端口号请自行百度,代码如下:

def _login_email(self):# 登录邮箱服务器try:server = smtplib.SMTP_SSL(self.email_host, port=465)# set_debuglevel(1)可以打印出和SMTP服务器交互的所有信息server.set_debuglevel(1)# 登录邮箱server.login(self.email_host_user, self.email_host_pass)return serverexcept Exception as e:print("mail login exception:", e)raise e

def _make_mail_msg(self)

该函数的功能为构建一个邮件实例对象,来处理邮件的内容。一封正常的邮件一般有收发件者信息,邮件主题,邮件正文,有些邮件还附带有附件,具体的设置参见如下代码:

def _make_mail_msg(self):# 构建邮件对象msg = MIMEMultipart()msg.attach(MIMEText(self.msg_content, 'plain', 'utf-8'))# 邮件主题msg['Subject'] = Header(self.msg_subject, "utf-8")# 发件人邮箱信息msg['From'] = "<%s>" % self.msg_from# msg['From'] = Header(self.msg_from + "<%s>" % self.email_host_user, "utf-8")msg['To'] = ",".join(self.receives)print("---", self.attach_file_list)if self.attach_file_list:for i, att in enumerate(self.attach_file_list):# 构造附件,传送当前目录下的文件if not att:breakatt_i = MIMEText(open(att, 'rb').read(), 'base64', 'utf-8')att_i["Content-Type"] = 'application/octet-stream'# 这里的filename可以任意写,写什么名字,邮件中显示什么名字att_i["Content-Disposition"] = 'attachment; filename="%s"' % attmsg.attach(att_i)return msg

def do_send_mail(self)

发送邮件,就是把上几个函数串起来,直接上代码:

def do_send_mail(self):# 邮件发送try:self._init_conf()server = self._login_email()msg = self._make_mail_msg()server.sendmail(self.email_host_user, self.receives, msg.as_string())server.close()print("发送成功!")except Exception as e:print("邮件发送异常", e)

配置参数,测试能否正常发送邮件:

if __name__ == "__main__":mail_conf = {'msg_from': '****@foxmail.com',  # 邮件发送者的地址'receives': ['****@qq.com',],  # 邮件接收者的地址,这是个list,因为邮件的接收者可能不止一个'msg_subject': 'Python发送邮件测试',  # 邮件的主题'msg_content': 'hello',  # 邮件的内容'attach_file_list': {"test.py": "test.py", "test.txt": "./test.txt"},  # 为附件文件路径列表,也可没有这项}manager = SendEmailManager(**mail_conf)manager.do_send_mail()

ok,发送成功,添加附件也是没问题的,现在,我们已经实现了使用Python发送邮件,那么如何实现自动发送邮件呢,接下来,我们来说一下。

自动发送邮件

1、代码硬编码实现

就是在代码里死循环,再加上一个if判断,每隔1小时发送执行一次发送,代码如下:

def delayed_sending(manager):# 参数manager为SendEmailManager对象begin_time = int(time.time())while True:end_time = int(time.time())if end_time - begin_time == 1*60*60:threading.Thread(target=manager.do_send_mail()).start()begin_time = end_timeprint("已发送。。。")

同时为了防止未知原因阻塞程序的正常运行,加了多线程实现异步发送邮件,这样程序执行后就会每1小时向指定邮箱发送一封email,只要程序不停止邮件就会不停的发下去!!

假设我们需要每天8点向指定邮箱发送一封email,那可以这样做:

def delayed_sending(manager):# 参数manager为SendEmailManager对象hour = 8minute = 0second = 0while True:now = datetime.datetime.now()if now.hour == hour and now.minute == minute and now.second == second:threading.Thread(target=manager.do_send_mail()).start()print("已发送。。。")

以上两种方式虽然功能实现了,但是,实现方式实在是low!

2.通过模块来实现定时功能

除了硬编码方式之外,我们还可以通过python中的任务定时运行库schedule模块来实现:

# 使用python任务定时运行库 schedule 模块
def send_mail_by_schedule(manager):schedule.every(20).minutes.do(manager.do_send_mail)  # 每20分钟执行一次schedule.every().hour.do(manager.do_send_mail)  # 每小时执行一次schedule.every().day.at("10:00").do(manager.do_send_mail)  # 每天10:00执行一次schedule.every().monday.do(manager.do_send_mail)  # 每周星期一执行一次schedule.every().friday.at("21:00").do(manager.do_send_mail)  # 每周星期五21:00执行一次while True:schedule.run_pending()time.sleep(1)

schedule其实只是个定时器,在while True死循环中,schedule.run_pending()是保持schedule一直运行,去查询上面那一堆的任务,在任务中,就可以设置不同的时间去运行。这个跟crontab是类似的。

但是,如果是多个定时任务运行的话,实际上它们是按照顺序从上往下挨个执行的。如果上面的任务比较复杂,耗时比较长,就会影响到下面任务的运行时间。 假如每2分钟运行5个任务,每个任务耗时1分钟,总共也就是耗时5分钟,这样在下一个2分钟到来时,上一轮的任务仍在运行,然后又开始了新一轮的任务。 解决方法也很简单:用多线程/多进程。

def run_threaded(manager):threading.Thread(target=manager.do_send_mail()).start()# 使用python任务定时运行库 schedule 模块
def send_mail_by_schedule(manager):schedule.every(1).minutes.do(run_threaded, manager)  # 每20分钟执行一次schedule.every().hour.do(run_threaded, manager)  # 每小时执行一次schedule.every().day.at("10:00").do(run_threaded, manager)  # 每天10:00执行一次schedule.every().monday.do(run_threaded, manager)  # 每周星期一执行一次schedule.every().friday.at("21:00").do(run_threaded, manager)  # 每周星期五21:00执行一次while True:schedule.run_pending()time.sleep(1)

这样,我们就可以为每个定时任务创建一个线程,让任务在线程中运行,从而达到多个任务并行工作效果。 这种方式是不是比第一种省时省力,也完全不需要大量的代码,完美!

总结

其实说白了,自动发送邮件最重要的无非是要实现任务的自动执行,那么实现方案也是非常多的,比如也可以使用类似于celery这种异步任务调度器对队列的监听来实现任务的自动执行等等。

搞定了自动发邮件之后呢,我们也可以让程序每天给我们发送天气预报、每日新闻、鸡汤等等(也可以给男女朋友发送哦)哈哈哈。

用Python做一个自动发送邮件的工具相关推荐

  1. 用Python做一个房价预测小工具!

    哈喽,大家好. 今天给大家介绍一个非常适合新手入门的机器学习实战案例. 这是一个房价预测的案例,来源于 Kaggle 网站,是很多算法初学者的第一道竞赛题目. 该案例有着解机器学习问题的完整流程,包含 ...

  2. 周杰伦演唱会总是抢不到票?教你用Python做一个自动抢票脚本

    相信想去周董演唱会的大家都用过大麦网抢票吧? 可是 抢不到啊 该说不说 我抢到了 那么,今天带大家用Python来制作一个自动抢票的脚本小程序! 知识点: 面向对象编程 selenium 操作浏览器 ...

  3. python的翻译-用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 本文就来自编程教室一位"小"读者的投稿(互助学习1群里的同学 ...

  4. 用html5做一个简单网页_用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 本文就来自编程教室一位"小"读者的投稿(互助学习1群里的同学 ...

  5. 用python做简单的地理聚类分析案例_用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 本文就来自编程教室一位"小"读者的投稿(互助学习1群里的同学 ...

  6. 用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法 ...

  7. python制作查询工具发给别人使用_用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 本文就来自编程教室一位"小"读者的投稿(互助学习1群里的同学 ...

  8. 如何用 Python 做一个简单的翻译工具?

    前言 平时经常在网上翻译一些单词,突发奇想,可不可以直接调某些免费翻译网站的接口呢?然后做一个图形界面的翻译小工具?下面开始实践 (文末送读者福利) 1.先找一下有哪些免费翻译的接口 百度了一下关键字 ...

  9. 周杰伦演唱会总是抢不到票?教你用Python做一个自动抢票脚本!

    相信想去周董演唱会的大家都用过大麦网抢票吧? 可是 抢不到啊 该说不说 我抢到了 那么,今天带大家用Python来制作一个自动抢票的脚本小程序! 知识点: 面向对象编程 selenium 操作浏览器 ...

  10. python翻译-用Python做一个简单的翻译工具

    编程本身是跟年龄无关的一件事,不论你现在是十四五岁,还是四五十岁,如果你热爱它,并且愿意持续投入其中,必定会有所收获. 本文就来自编程教室一位"小"读者的投稿(互助学习1群里的同学 ...

最新文章

  1. linux 模拟生成 CAN 设备
  2. GitLab10安装-部署-汉化-备份-升级
  3. 【转】细说.NET中的多线程 (六 使用MemoryBarrier,Volatile进行同步)
  4. pyecharts添加文字_超燃的文字云效果,用Python就能轻松get!
  5. Oracle命令--如何查看oracle中创建的所有目录
  6. mysql表级锁和行级锁_Mysql的表级锁和行级锁
  7. Linux 下 Git 的源码安装
  8. svn插件下载地址(用于eclipse、myeclipse的svn插件)
  9. 分析11年21部漫威电影,一览导演、主演、口碑票房最佳......
  10. 求助!KeyError:None of [Index(['2017-01-01, ...\n dtype='object', length=365)] are in the [columns]
  11. CentOS7安装CA根证书
  12. 七夕活动浪漫上线,别让网络拖慢和小姐姐的开黑时间
  13. 适合国人的6款免费远程桌面工具,适用于电脑和手机
  14. 笔记本电脑什么牌子好 世界笔记本电脑排名
  15. 根据ASCII 判断一个字符是否是数字
  16. 在服务器上解压压缩文件,在服务器端实现文件自动压缩和解压
  17. Android SERVICE后台服务进程的守护
  18. Android开发工程师笔试题
  19. android获取appname,如何获取Android系统APP的Package Name和Activity Name
  20. android源码集合989个实例 (从网上摘抄,在此记录下)

热门文章

  1. 电脑蓝屏显示(你的电脑遇到问题,需要重新启动,你可以重新启动)
  2. 互联网行业的HR怎么看待30岁以上的基础岗位求职者
  3. vue 中 自定义按钮实现video暂停和播放
  4. 从零读懂CAN总线(上)
  5. 电脑声控 电脑机器人功能
  6. 《实用python程序设计》练习题:向量点积计算
  7. java 编写扑克牌洗牌,java斗地主扑克 扑克牌 洗牌 发牌 Collection 集合练习
  8. “开源和商业化不能形成对立!”
  9. 《众妙之门——用户体验设计的秘密》一第2章 设计“好脾气”的网页2.1 巴赫和他的十二平均律...
  10. 实例分割:R-CNN、Fast R-CNN、Faster R-CNN、Mask R-CNN