美文网首页
ubuntu定时任务发送邮件

ubuntu定时任务发送邮件

作者: Stevent | 来源:发表于2018-09-19 14:22 被阅读87次

    最近,有个任务要天天给同事传文件,实在是麻烦了,便想能不能自动发送,用python折腾了下,邮件发送实现了,可是在ubuntu定时任务发送时却出现了一些问题,后面朋友提示解决问题了,记录下。

    0x01 用python发送邮件

    先上代码

    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
    
    
    import smtplib
    from email.mime.text import MIMEText
    from email.mime.multipart import MIMEMultipart
    from email.mime.base import MIMEBase
    from email import encoders
    from pathlib import Path
    from datetime import datetime
    import sys
    import os
    
    
    class MailSender:
        _from = None
        _attachments = []
    
        def __init__(self, smtpSvr, port):
            self.smtp = smtplib.SMTP()
            print("connecting...")
            self.smtp.connect(smtpSvr, port)
            print("connected!!!")
    
        def login(self, user, pwd):
            self._from = user
            print("login ...")
            self.smtp.login(user, pwd)
    
        def add_attachment(self, filename):
            '''
                添加附件
            '''
            attr_name = Path(filename).parts[-1]
            att = MIMEBase('application', 'octet-stream')
            att.set_payload(open(filename, 'rb').read())
            att.add_header('Content-Disposition', 'attachment',
                           filename=('gbk', '', attr_name))
            encoders.encode_base64(att)
    
            self._attachments.append(att)
    
        def send(self, subject, content, to_addr):
            '''
                发送邮件
            '''
            msg = MIMEMultipart('alternative')
            contents = MIMEText(content, "html", _charset='utf-8')
            msg['Subject'] = subject
            msg['From'] = self._from
            msg['To'] = to_addr
            for att in self._attachments:
                msg.attach(att)
            msg.attach(contents)
            try:
                self.smtp.sendmail(self._from, to_addr.split(','), msg.as_string())
                return True
            except Exception as e:
                print(str(e))
                return False
    
        def close(self):
            self.smtp.quit()
            print("logout.")
    
    
    def check_latest_file(p, today):
        counter = 0
        for file in p.glob('*.csv'):
            if today in file.name:
                counter += 1
        return counter
    
    
    def main(date=''):
        user = os.environ.get('EMAIL_NAME')
        pwd = os.environ.get('EMAIL_PWD')
        to_addr = 'email@email.com'
        smtpSvr = 'smtp.exmail.qq.com' #这里用的是腾讯的邮箱所以是这个,其它邮箱请按相关邮箱设置
        content = '请查看附件'
    
        if date == '':
            today = datetime.now().strftime('%Y-%m-%d')
        else:
            today = date
    
        if os.name == 'nt':
            p = Path(r"E:\销售情况")
        else:
            p = Path("/home/steven/sales_collect")
    
        subject = today + '销售情况'
        m = MailSender(smtpSvr, 25)
        m.login(user, pwd)
        for file in p.glob('*.csv'):
            if today in file.name:
                m.add_attachment(file)
    
        m.send(subject, content, to_addr)
        m.close()
    
    
    if __name__ == '__main__':
        if len(sys.argv) > 1:
            main(sys.argv[1])
        else:
            main()
    
    

    内容其实不复杂,主要用到了smtplib作为发送邮件的库,email库用来构建邮件, 整体代码之前是参考的liaoxuefeng, 后面从另外一个网友那儿又做了一定的修改,不好意思,当时没有记录下网址,后期找到了才贴上链接。
    定义了一个MailSender类,方法实现了邮件的创建和附件的添加,还有最后的发送。

     user = os.environ.get('EMAIL_NAME')
     pwd = os.environ.get('EMAIL_PWD')
    

    这里为什么要这样写,因为我的代码是托管在github上的,但是测试时又要用到这些比较敏感的内容,比如密码,所以比较安全的方式就是把敏感信息放到系统环境变量中,这样push的时候就不用担心又有什么不该公开的信息放上去了。不过也就是因为这里的设置,后面在ubuntu中出现一个坑,在win里面很正常,但是在ubuntu中却是不太好弄,这个后面再讲。

     if os.name == 'nt':
            p = Path(r"E:\销售情况")
        else:
            p = Path("/home/steven/sales_collect")
    

    这一段代码是为了实现,linux和window的兼容,由于我是在win下写的代码和测试的,但是使用的时候是要放在服务器的,所以这里做了个判断。如果是win系统就把文件存到E盘下面的文件夹,如果是linux就存到/home/steven/sales_collect下面。

        if date == '':
            today = datetime.now().strftime('%Y-%m-%d')
        else:
            today = date
    

    这里是为了能按需求取要发送的文件,如果没有传入日期就按最新的日期来取文件,也就是今天,如果有日期,就按照传入的日期取文件,注意我的文件都是按照日期加文件名的方式命名的,所以很方便的按照日期选取。

    0x02 sh脚本配置

    python脚本写好后经过测试,能够正常运行。是时候写sh脚本了。

    #!/usr/bin/env bash
    cd /home/steven/sales_collect
    /usr/bin/python3.6 send_mail.py
    

    这是我最开始写的sh脚本,更改文件权限chmod 700 send_mail.sh后可以直接运行。可是后面加入定时任务后,却总是取不到系统环境变量。这个就是前面所说的在ubuntu中的坑。几经周折,经Q群朋友 @不再留戀 提醒,做了以下修改:

    #!/bin/bash
    cd /home/steven/sales_collect/ && /usr/bin/python3.6 send_mail.py
    

    经过测试,终于没有问题了。修改了几个地方,#!后面我之前的内容是参考python写的,有可能是错的。还有 cd 进入与后面的执行操作最好用 && 连接一起使用。

    0x03 定时任务设置

    crontab -e #进入编辑模式
    # 添加内容
    00 20 * * * /home/steven/send_email.sh # 最开始的设置
    00 20 * * * /bin/bash /home/steven/send_email.sh # 经朋友提醒后修改
    

    这里可能是和上面的sh脚本的#!问题一起的,按照最开始的设置,python脚本始终没有取到系统环境变量,加上/bin/bash后,python脚本正常取到系统环境变量,测试邮箱收到邮件。

    邮件发送情况
    之前为了测试的时候,设置的每过2分钟发送一次。至此任务终于完成,后面有时间再研究下,到底是#!写错的原因还是定时任务时应该加上/bin/bash

    相关文章

      网友评论

          本文标题:ubuntu定时任务发送邮件

          本文链接:https://www.haomeiwen.com/subject/ouhinftx.html