1、官方logging包的SMTPHandler不支持ssl的邮箱,修改成兼容ssl以支持大部分国内邮箱。

2、增加一个频率控制的参数,比如要设置一个报警邮件,异常时候通知我们,但假设1分钟内异常几千次,那是不需要发几千次相同日志的,handler自带频率限制,使用的时候一秒钟调用运行logger.waning('某某报警')几万次都没问题,直接自动忽略相同内容的报警信息,不会发送邮件。

3、发邮件时候另开线程,发邮件是需要一段时间的,运气不好时候发邮件需要两三秒,把主线程阻塞两三秒了,另开线程不会有阻塞。

修改成如下:

class CompatibleSMTPSSLHandler(handlers.SMTPHandler):
"""
官方的SMTPHandler不支持SMTP_SSL的邮箱,这个可以两个都支持,并且支持邮件发送频率限制
""" def __init__(self, mailhost, fromaddr, toaddrs: tuple, subject,
credentials=None, secure=None, timeout=5.0, is_use_ssl=True, mail_time_interval=0):
""" :param mailhost:
:param fromaddr:
:param toaddrs:
:param subject:
:param credentials:
:param secure:
:param timeout:
:param is_use_ssl:
:param mail_time_interval: 发邮件的时间间隔,可以控制日志邮件的发送频率,为0不进行频率限制控制,如果为60,代表1分钟内最多发送一次邮件
"""
super().__init__(mailhost, fromaddr, toaddrs, subject,
credentials, secure, timeout)
self._is_use_ssl = is_use_ssl
self._time_interval = mail_time_interval
self._msg_map = dict() # 是一个内容为键时间为值得映射 def emit(self, record: logging.LogRecord):
"""
Emit a record. Format the record and send it to the specified addressees.
"""
from threading import Thread
if sys.getsizeof(self._msg_map) > 10 * 1000 * 1000:
self._msg_map.clear()
Thread(target=self.__emit, args=(record,)).start() def __emit(self, record):
if record.msg not in self._msg_map or time.time() - self._msg_map[record.msg] > self._time_interval:
try:
import smtplib
from email.message import EmailMessage
import email.utils
t_start = time.time()
port = self.mailport
if not port:
port = smtplib.SMTP_PORT
smtp = smtplib.SMTP_SSL(self.mailhost, port, timeout=self.timeout) if self._is_use_ssl else smtplib.SMTP(self.mailhost, port, timeout=self.timeout)
msg = EmailMessage()
msg['From'] = self.fromaddr
msg['To'] = ','.join(self.toaddrs)
msg['Subject'] = self.getSubject(record)
msg['Date'] = email.utils.localtime()
msg.set_content(self.format(record))
if self.username:
if self.secure is not None:
smtp.ehlo()
smtp.starttls(*self.secure)
smtp.ehlo()
smtp.login(self.username, self.password)
smtp.send_message(msg)
smtp.quit()
print(f'[log_manager.py] 发送邮件给 {self.toaddrs} 成功,用时{round(time.time() - t_start,2)} ,发送的内容是--> {record.msg} \033[0;35m!!!请去邮箱检查,可能在垃圾邮件中\033[0m')
self._msg_map[record.msg] = time.time()
except Exception:
self.handleError(record)
else:
pass
print(f'[log_manager.py] 邮件发送太频繁,此次不发送这个邮件内容: {record.msg} ')

python日志,一个改版SMTPHandler的更多相关文章

  1. python日志按天分割,保存近一个月日志,日志自动清理

    python日志按天分割,保存近一个月日志 import os import logging import re from logging.handlers import TimedRotatingF ...

  2. python日志模块logging学习

    介绍 Python本身带有logging模块,其默认支持直接输出到控制台(屏幕),或者通过配置输出到文件中.同时支持TCP.HTTP.GET/POST.SMTP.Socket等协议,将日志信息发送到网 ...

  3. Python日志输出——logging模块

    Python日志输出——logging模块 标签: loggingpythonimportmodulelog4j 2012-03-06 00:18 31605人阅读 评论(8) 收藏 举报 分类: P ...

  4. python日志模块logging

    python日志模块logging   1. 基础用法 python提供了一个标准的日志接口,就是logging模块.日志级别有DEBUG.INFO.WARNING.ERROR.CRITICAL五种( ...

  5. 浅析python日志重复输出问题

    浅析python日志重复输出问题 问题起源: ​ 在学习了python的函数式编程后,又接触到了logging这样一个强大的日志模块.为了减少重复代码,应该不少同学和我一样便迫不及待的写了一个自己的日 ...

  6. python 日志打印之logging使用介绍

    python 日志打印之logging使用介绍 by:授客QQ:1033553122 测试环境: Python版本:Python 2.7   简单的将日志打印到屏幕 import logging lo ...

  7. 用Python编写一个简单的Http Server

    用Python编写一个简单的Http Server Python内置了支持HTTP协议的模块,我们可以用来开发单机版功能较少的Web服务器.Python支持该功能的实现模块是BaseFTTPServe ...

  8. Python 日志输出中添加上下文信息

    Python日志输出中添加上下文信息 除了传递给日志记录函数的参数(如msg)外,有时候我们还想在日志输出中包含一些额外的上下文信息.比如,在一个网络应用中,可能希望在日志中记录客户端的特定信息,如: ...

  9. python日志模块笔记

    前言 在应用中记录日志是程序开发的重要一环,也是调试的重要工具.但却很容易让人忽略.之前用flask写的一个服务就因为没有处理好日志的问题导致线上的错误难以察觉,修复错误的定位也很困难.最近恰好有时间 ...

随机推荐

  1. C#并行Parallel编程模型实战技巧手册

    一.课程介绍 本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高级编程的技巧分享出来给大家进行学习,不断的收集.整理和 ...

  2. Java int转string 长度不足左补0

    最近项目中用到这个需求,我试了两个方法都可以实现 方法一:(推荐) String s=String.format("%010d", 123)//123为int类型,0代表前面要补的 ...

  3. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)

    要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...

  4. spring mvc 异常统一处理

    摘自: http://gaojiewyh.iteye.com/blog/1297746  

  5. Mysql高效插入/更新数据

    从tushare抓取到的财务数据,最开始只是想存下来,用的办法想简单点,是:插入--报错-update 但发现这个方法太蠢,异常会导致大量无效连接,改为: for idx,row in d2.iter ...

  6. 了解 JavaScript (2)- 需要了解的一些概念

    Ajax 是什么 Ajax 是一种创建交互式 Web 应用程序的方式. Ajax 是 Asynchronous JavaScript and XML 缩写(异步的 JavaScript 和 XML), ...

  7. wifipineapple外接SD卡

    通过SSH或者web访问URL, http://172.16.42.1:1471 输入帐号:root  密码:pineapplesareyummy(默认账号密码) ssh连接:ssh root@172 ...

  8. What's the difference between ConcurrentHashMap and Collections.synchronizedMap(Map)?

    来自:http://stackoverflow.com/questions/510632/whats-the-difference-between-concurrenthashmap-and-coll ...

  9. Mac下用zsh

    最近好多实验要跑,有时候Finder切换来切换去,感觉还不如用terminal. Mac默认的shell是bash.所以说我其实今天才弄明白shell和terminal之间的关系.在人和计算机内核之间 ...

  10. [转]/etc/passwd文件解析

    /etc/passwd文件内容如下 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daem ...