.net 接口调用接口发送文件_[开发]实现邮件发送接口,然后用schedule周期性调用...

1、需求

1)把重要日志通过邮件发出去

2)做成定期任务,比如每日定时发送一次

2、开始有过但后来弃用的思路

Django自带发送邮件的方法send_mail,很简单,原本准备直接用,比如像这样:

  4 from celery import shared_task
  5 from django.core.mail import send_mail
  6 
 10 
 11 from confs.email_settings import EMAIL_HOST_USER
 12 
 13 @shared_task
 14 def send_a_email(subject="默认", message="默认", rec_addr_list=[], sender_addr=EMAIL_HOST_USER):
 15     if rec_addr_list:
 16         send_mail(subject=subject,message=message,from_email=sender_addr,recipient_list=rec_addr_list,fail_silently=False)
 17         print('mail sent')
 18         return 1
 19     else:
 20         return 0

 23 if __name__ == "__main__":
 24     print('begin to send a email')
 25     rec_addr_list=['xxx@qq.com']
 26     res = send_a_email.delay(rec_addr_list=rec_addr_list)
 27     print(res.ready())
 28     print(res.get())

但这段代码用起来很麻烦,行不通:

发送邮件明显是公用功能,不与任何一个具体的app绑定,所以我把她在一个叫做utils的文件夹内,utils是文件夹不是app。

如果直接python运行这个文件会报错,提示找不到Django的环境(因为utils/不是注册app,相当于django环境之外使用django组件,首先需要引入django的环境)更别说celery调用的tasks也要求是在app内的task。

所以放弃这条思路!

3、最终的思路

后来参考这篇文章somenzz:Python运维-分分钟搭建邮件报警接口 ,决定依葫芦画瓢:

把发送邮件单独放在一个app内部,这个app就是一个API功能。

文章内容很丰富,涉及了很多常用的东西,但又浅显能看懂,比如curl、uwsgi、Restful……好评~
理解RESTful架构 - 阮一峰的网络日志 https:// blog.csdn.net/delicious ion/article/details/78062521
爬虫工具之curl

参考上面的文章,我的思路如下:

1)实现一个发送邮件功能的Django app,并作为API对外提供。

2)调用这个API,可以用Python的requests库

3)调动的定期执行,可以用Python的schedule库

4、实现:

1)实现邮件发送API(基本照抄上面)

其中涉及账号密码的隐私配置是单独放在一个文件,没有提交到Git哈。

现在没有做身份认证,只检查参数,还是有点不安全……不过先将就一下吧。。

"""
一个发送邮件的API。
 调用方式:POST+参数
参数有4个:subject message from_email to_emial,除message外不能为空
返回是json:例如{'code':0,'message':'邮件发送成功.'},code为0表示成功发送,其他则为异常
 2019.03.26
"""

import logging
logger = logging.getLogger('mysite.mailapi.info')

from django.http import JsonResponse
# Create your views here.
from django.core.mail import send_mail
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

from utils.get_client_infos import get_visitor_ip
from utils.get_ip_infos import get_location_calling_free_api

 #先禁用防跨站请求伪造功能,方便 curl post 测试和调用
@csrf_exempt
@require_POST
def send_email(request):
    return_data = {'code':0,'message':'邮件发送成功.'}

     subject = request.POST.get('subject', '')
    message = request.POST.get('message', '')
    from_email = request.POST.get('from_email', '')
    to_email = request.POST.get('to_email', '')

     #设置 from_email 的默认值
    if not message:
        message = ''   # 内容留空是允许的吧?


     print("subject",subject)
    print("message",message)
    print("from_email",from_email)

     if subject and to_email and from_email:
        try:
            to_email = to_email.split(';') #多个收件人以;分隔
            print("to_email",to_email)
            send_mail(subject, message, from_email, to_email)
        except BadHeaderError:
            return_data['code'] = 1
            return_data['message'] = '邮件发送失败.'
    else:
        # In reality we'd use a form class
        # to get proper validation errors.
        return_data['code'] = 0
        return_data['message'] = '检查必要字段是否完整'

     ip = get_visitor_ip(request)
    ip_infos = get_location_calling_free_api(ip)
    logger.info(f"ip = {ip}, subject = {subject },message = {message }, from_email = {from_email }, to_email = {to_email }, return_data = {return_data }")
    return JsonResponse(return_data)

先用curl -d 测试:

curl -d "subject=邮件报警测试&message=这是一个邮件测试&to_email=xxx@163.com&from_email=xxx@163.com" "http://localhost:8001/api/sendemail/"

b82c1bf9f8f832d86334730153444066.png
测试成功,邮箱也收到了邮件!

再据此把调用写成Python脚本send_emails.py(脚本放在utils文件夹内,用requests实现http请求):

 19 def send_a_email(subject, message, to_email, from_email='tianweigrace@qq.com'):
 20     url_api = f"http://localhost:{http_port}/api/sendemail/"
 21     request_method = "post"
 22     form_data = {
 23     'subject': subject,
 24     'message': message,
 25     'to_email': to_email,
 26     'from_email': from_email
 27 }
 28     res_json  = get_res(url_api, request_method, form_data=form_data)
 29     return res_json
 30 
 31 
 32 if __name__ == "__main__":
 33     subject = "测试主体"
 34     message = "测试内容"
 35     to_email =  "xxx@qq.com"
 36     res = send_a_email(subject, message, to_email)
 37     print(res)

2)获取当天的日志内容get_log_today:

  1 import sys, os
  2 import datetime
  3 cur_dir = os.path.dirname(os.path.abspath(__file__))
  4 proj_dir = os.path.dirname(cur_dir)
  5 log_dir = os.path.join(proj_dir, 'logs')
  6 
  7 sys.path.append(log_dir)
  8 
  9 def get_date():
 10     today=datetime.date.today() #'2018-01-01'
 11     return str(today)
 12 
 13 
 14 def get_log_today(file_name):
 15     content = ''
 16     today = get_date()
 17 
 18     file_path = os.path.join(log_dir, file_name)
 19     with open (file_path, 'r') as f:
 20         for line in f.readlines():
 21             if today in line:
 22                 content += line
 23     return content
 24 
 25 
 26 
 27 if __name__ == "__main__":
 28     file_name = 'article_infos.log'

3)实现定期任务(用到了Python schedule库)

  1 import sys, os
  2 import schedule
  3 import time
  4 
  5 proj_dir = os.path.dirname(os.path.abspath(__file__))
  6 utils_dir = os.path.join(proj_dir, "utils")
  7 sys.path.append(utils_dir)
  8 
  9 
 10 from get_logs import get_logs_today
 11 from send_emails import send_a_email
 12 
 13 def send_logs_today():
 14     file_name = 'article_infos.log'
 15     subject = "[今天的日志]来自lovelyhouse"
 16     to_email =  "xxx@qq.com"
 17     message = get_logs_today(file_name)
 18     res = send_a_email(subject, message, to_email)
 19 
 20 
 21 
 22 schedule.every().day.at("18:29").do(send_logs_today)
 23 
 24 while True:
 25     schedule.run_pending()
 26     time.sleep(1)

然后按时收到啦~撒花庆祝~

4beb33f0922205ffbdbac5c40f6e331f.png

总的来说,因为大体思路清晰也没什么太大的难点,就是步骤多一点,封装调用来来去去……

5、后续遗留

部署上还是偏手工,不够先进吧。

如何自动化部署,保证每次依赖和环境等等到了生产环境能够不遗漏?

再说吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值