Python + Email每天定时自动给女朋友发送天气预报等各种关爱

6 篇文章 1 订阅

一、前言

闲暇之余,想给身边的朋友每天定时发送问候,本来想调微信来实现的,但由于微信处于安全考虑,已将网页授权登录关闭;

所以就想着用邮箱代替来实现一个每日关爱脚本 !!!

下面我们先看一下效果,如图;

好文章 记得收藏+点赞+关注额 !!!

---- Nick.Peng


二、关爱邮件效果图

  • 大概邮件信息以及格式如下,大家可以根据各自的需求微调;
    在这里插入图片描述

三、发送关爱邮件实现步骤

  • 项目依赖
    • Python版本:python3
    • 第三方包:requests、apscheduler

3.1、获取天气方法

  • 定义一个每日关爱邮件类;

  • 定义实例属性,下面会用到;

  • 定义获取天气信息的方法,详情如下,每个步骤都有备注,很容易懂;

    • 调用实例属性天气API;
    • 提取周信息、天气状况、最低最高气温、风向、风力、感冒预警关爱信息;
    • 制定邮件天气模版并填充以上提取的信息;
    class DailyGreeting(object):
    	"""
        每日邮件关爱
        """
        def __init__(self):
            self.cb_link = 'http://open.iciba.com/dsapi/'                       # 金山词霸api提供的每日一句
            self.whether_link = 'http://wthrcdn.etouch.cn/weather_mini?city='   # 天气api
    
        def get_whether(self, city):
            """
            获取天气信息
            :param city: 城市
            :return: msg
            """
            url = self.whether_link + city
            r = requests.get(url).json()
            week = r['data']['forecast'][0]['date'][-3:]            # 周几
            weather = r['data']['forecast'][0]['type']              # 天气
            low_temp = r['data']['forecast'][0]['low'][3:]          # 最低气温
            high_temp = r['data']['forecast'][0]['high'][3:]        # 最高气温
            wind_dir = r['data']['forecast'][0]['fengxiang']        # 风向
            wind_force = r['data']['forecast'][0]['fengli'][9:-3]   # 风力
            warn = r['data']['ganmao']                              # 感冒预提醒
            # 填充天气信息模板
            msg = '<br>亲爱的朋友,' + '今天 ' + week + '<br>' + \
                  '<br><font size=3 color=#0081ff><strong>天气:</strong></font>' + city + ' ' + weather + \
                  '<br><font size=3 color=#0081ff><strong>温度:</strong></font>' + low_temp + '~' + high_temp + \
                  '<br><font size=3 color=#0081ff><strong>风向:</strong></font>' + wind_dir + ',' + wind_force + \
                  '<br><br><font size=3 color=red><strong>注意:</strong></font>' + warn + '<br>'
            return str(msg)
    

3.2、获取词霸每日一句方法

  • 定义get_word方法,并调用实例属性词霸每日一句API;

  • 提取中英文每日一句;

  • 制定邮件每日一句模版并填充以上提取的信息;

    def get_word(self):
        """
        获取金山词霸每日一句
        :return: msg
        """
        r = requests.get(self.cb_link).json()
        en = r['content']
        cn = r['note']
        indent = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' \
                 '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
        # 填充每日一句模板
        msg = '<br><font size=3 color=lightpink><strong><i>' + en + '<br>' + cn + '</strong></font><br>' + \
              '<br>' + indent + '<font size=3 color=#a5673f>—— 最关心你的人儿~' + \
              '<br><html><body><img src={}></body></html>'.format(r['fenxiang_img'])
        return str(msg)
    

3.3、发送邮件方法

  • 指定发件人邮件地址和登录授权码;

  • 创建一个邮件对象,并指定邮件主题,发件人,收件人等;

  • 创建邮件客户端对象,连接邮箱服务器地址,登录认证,并调用sendmail发送邮件,发送完毕断开邮箱服务连接;

    @staticmethod
    def send_email_message(email, message):
        """
        完成发送邮件功能
        :param email: 收件人
        :param message: 邮件发送内容
        :return:
        """
        # 发件人邮箱地址
        sender = 'xxxxxxx@163.com'
        # 客户端授权码:需要在注册邮箱后,登录进入->设置->常规设置->客户端授权码 里面进行设置
        auth_code = 'SISQXKZBXVBDADASD'
        messageObj = MIMEText(message, "html", "utf-8")
        # 设置主题
        messageObj['Subject'] = Header("每日温馨提醒!", "utf-8")
        # 设置发件人
        messageObj['From'] = sender
        # 设置收件人
        messageObj['To'] = email
        try:
            # 建立客户端
            smtpObj = smtplib.SMTP()
            # 连接163邮箱服务器地址
            smtpObj.connect('smtp.163.com')
            # 方法二:服务器上建议使用SSL的方式创建连接, 因为阿里云服务器为了安全起见默认屏蔽25号端口
            # smtpObj = smtplib.SMTP_SSL('smtp.163.com', 465)
            # smtpObj.ehlo()    # 使用EHLO向ESMTP服务器标识自己
            # 登录认证
            smtpObj.login(sender, auth_code)
            # 发送邮件
            smtpObj.sendmail(sender, [email], messageObj.as_string())
            # 断开连接
            smtpObj.close()
            print("Send mail successfully.")
            return True
        except smtplib.SMTPException as e:
            print("Send email failed.")
            print("Error logs: ", e)
            return False
    

3.4、调度方法实现

  • 对调用传递的好友练习方式进行遍历,并调用send_email_message分别发送邮件;

    def main(self, friend_list):
        """
        调度方法
        :return: Boole
        """
        for friend in friend_list:
            mail = friend.get('mail')
            city = friend.get('city')
            cur_whether = self.get_whether(city)
            cur_word = self.get_word()
            # 构造邮件的正文内容
            msg = '您的贴心小秘上线啦 !!!<br>' + cur_whether + cur_word
            print("=========={}: {}".format(friend.get('mail'), msg))
            self.send_email_message(mail, msg)
    

3.5、定时任务实现

  • 方法一:使用 apscheduler 定时任务框架

    import traceback
    from apscheduler.schedulers.blocking import BlockingScheduler
    
    try:
        # 初始化一个阻塞式调度器
        scheduler = BlockingScheduler()
        daily_greeting = DailyGreeting()
        # 添加定时任务:每天8点执行一次
        scheduler.add_job(daily_greeting.main, 'cron', day='*', hour=8, args=friend_list)
        scheduler.start()
    except Exception as e:
        print(e)
        traceback.format_exc()
    
  • 方法二:自定义定时任务

    SECONDS_PER_DAY = 24 * 60 * 60  # 一天时间(秒)
    SET_TIME = 7                    # 定时每日7点执行一次
    is_first = True                 # 是否第一次执行任务
    now = datetime.datetime.now()   # 第一次执行获取当前时间
    # 定时执行任务逻辑
    while True:
        cur_s = now.hour * 60 * 60 + now.minute * 60 + now.second   # 当前时间(时+分+秒)--> 秒
        first_gap_s = 0     # 第一次等待的时间(秒)
        if now.hour > SET_TIME:
            # 当前时间小时数 大于 7点
            first_gap_s = 24 * 60 * 60 - cur_s + SET_TIME * 60 * 60 # 差距 --> 秒
        elif now.hour < SET_TIME:
            # 当前时间小时数 小于 7点
            first_gap_s = SET_TIME * 60 * 60 - cur_s
        if is_first:
            # 第一次执行需要等待的时间,即first_gap_s秒后调用main()发送邮件
            time.sleep(first_gap_s)
        else:
            time.sleep(SECONDS_PER_DAY)     # 每24H执行一次
        DailyGreeting().main(friend_list)
        is_first = False    # 第一次执行完后将is_first置False
    

四、完整源代码

  • 同学们期待的完整源码来啦 !!!赶紧撸下来吧。^o^ ~ ^o^

  • 有了它,我们就可以将其上传到服务器,使用以下命令运行即可实现每日给亲朋好友发送邮件啦;

  • 后台运行命令: nohup python3 Send_greeting.py >message.out 2>&1 &

  • 在这里顺便 送大家 一套2020最有趣的Pyhon项目实战视频教程视频地址: 点击进去就能免费拿,希望大家一起进步!

    # -*- coding: utf-8 -*-
    # @Author: Nick
    # @Last Modified by:   Nick
    # @Last Modified time: 2020-03-31 16:21:36
    
    import time
    import datetime
    import requests
    import smtplib
    from email.mime.text import MIMEText
    from email.header import Header
    import traceback
    from apscheduler.schedulers.blocking import BlockingScheduler
    
    
    class DailyGreeting(object):
        """
        每日邮件关爱
        """
        def __init__(self, friend_list):
            self.cb_link = 'http://open.iciba.com/dsapi/'                       # 金山词霸api提供的每日一句
            self.whether_link = 'http://wthrcdn.etouch.cn/weather_mini?city='   # 天气api
            self.friend_list = friend_list
    
        def get_whether(self, city):
            """
            获取天气信息
            :param city: 城市
            :return: msg
            """
            url = self.whether_link + city
            r = requests.get(url).json()
            week = r['data']['forecast'][0]['date'][-3:]            # 周几
            weather = r['data']['forecast'][0]['type']              # 天气
            low_temp = r['data']['forecast'][0]['low'][3:]          # 最低气温
            high_temp = r['data']['forecast'][0]['high'][3:]        # 最高气温
            wind_dir = r['data']['forecast'][0]['fengxiang']        # 风向
            wind_force = r['data']['forecast'][0]['fengli'][9:-3]   # 风力
            warn = r['data']['ganmao']                              # 感冒预提醒
            # 填充天气信息模板
            msg = '<br>亲爱的朋友,' + '今天 ' + week + '<br>' + \
                  '<br><font size=3 color=#0081ff><strong>天气:</strong></font>' + city + ' ' + weather + \
                  '<br><font size=3 color=#0081ff><strong>温度:</strong></font>' + low_temp + '~' + high_temp + \
                  '<br><font size=3 color=#0081ff><strong>风向:</strong></font>' + wind_dir + ',' + wind_force + \
                  '<br><br><font size=3 color=red><strong>注意:</strong></font>' + warn + '<br>'
            return str(msg)
    
        def get_word(self):
            """
            获取金山词霸每日一句
            :return: msg
            """
            r = requests.get(self.cb_link).json()
            en = r['content']
            cn = r['note']
            indent = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' \
                     '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
            # 填充每日一句模板
            msg = '<br><font size=3 color=lightpink><strong><i>' + en + '<br>' + cn + '</strong></font><br>' + \
                  '<br>' + indent + '<font size=3 color=#a5673f>—— 最关心你的人儿~' + \
                  '<br><html><body><img src={}></body></html>'.format(r['fenxiang_img'])
            return str(msg)
    
        @staticmethod
        def send_email_message(email, message):
            """
            完成发送邮件功能
            :param email: 收件人
            :param message: 邮件发送内容
            :return:
            """
            # 发件人邮箱地址
            sender = 'xxxxxxx@163.com'
            # 客户端授权码:需要在注册邮箱后,登录进入->设置->常规设置->客户端授权码 里面进行设置
            auth_code = 'SISQXKZBXVBDADASD'
            messageObj = MIMEText(message, "html", "utf-8")
            # 设置主题
            messageObj['Subject'] = Header("每日温馨提醒!", "utf-8")
            # 设置发件人
            messageObj['From'] = sender
            # 设置收件人
            messageObj['To'] = email
            try:
                # 建立客户端
                smtpObj = smtplib.SMTP()
                # 连接163邮箱服务器地址
                smtpObj.connect('smtp.163.com')
                # 方法二:利用SSL的方式发送
                # smtpObj = smtplib.SMTP_SSL('smtp.163.com', 465)
                # smtpObj.ehlo()    # 使用EHLO向ESMTP服务器标识自己
                # 登录认证
                smtpObj.login(sender, auth_code)
                # 发送邮件
                smtpObj.sendmail(sender, [email], messageObj.as_string())
                # 断开连接
                smtpObj.close()
                print("Send mail successfully.")
                return True
            except smtplib.SMTPException as e:
                print("Send email failed.")
                print("Error logs: ", e)
                return False
    
        def main(self):
            """
            调度方法
            :return: Boole
            """
            for friend in self.friend_list:
                mail = friend.get('mail')
                city = friend.get('city')
                cur_whether = self.get_whether(city)
                cur_word = self.get_word()
                # 构造邮件的正文内容
                msg = '您的贴心小秘上线啦 !!!<br>' + cur_whether + cur_word
                print("=========={}: {}".format(friend.get('mail'), msg))
                self.send_email_message(mail, msg)
                print("========== 每日华丽分割线 ==========")
    
    
    if __name__ == '__main__':
        # 需要发送邮件的联系方式
        friend_list = [{'mail': '2911111111@qq.com', 'city': '郑州'}]
        # DailyGreeting(friend_list).main()
    	
        try:
            # 初始化一个阻塞式调度器
            scheduler = BlockingScheduler()
            daily_greeting = DailyGreeting(friend_list)
            # 添加定时任务:每天8点执行一次
            scheduler.add_job(daily_greeting.main, 'cron', day='*', hour=8)
            scheduler.start()
        except Exception as e:
            print(e)
            traceback.format_exc()
            
    
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值