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#高级编程9 第16章 错误和异常

    C#高级编程9 第16章 错误和异常 了解这章可以学会如何处理系统异常以及错误信息. System.Exception类是.NET运行库抛出的异常,可以继承它定义自己的异常类. try块代码包含的代码 ...

  2. Delphi识别读取验证码

    unit OCR; interface uses Windows, SysUtils, Graphics, Classes, PNGImage, GIFImage, JPEG, Math, Asphy ...

  3. 最近IOS10.2.1 iphone6 无法通过appStore 来更新 下载任何APP。好烦啊。

    今天打开爱思助手,查看事实日志,发现了原因: Mar :: iPhone6 appstored(StoreServices)[] <Notice>: SSSQLiteDatabase: C ...

  4. JavaScript 编码规范(中文/Airbnb公司版)

    Airbnb 是一家位于美国旧金山的公司,本文是其内部的 JavaScript编码规范,写得比较全面,在 Github 上有 16,686 + Star,3,080 + fork,前端开发人员可参考. ...

  5. jquery操作radio,checkbox

    1. 获取radio选中的value. $('input:radio[name=sex]:checked').val(); 2. 选择 radio 按钮 (Male). $('input:radio[ ...

  6. Android学习笔记(11):线性布局LinearLayout

    线性布局LinearLayout是指在横向或是竖向一个接一个地排列.当排列的组件超出屏幕后,超出的组件将不会再显示出来. LinearLayout支持的XML属性和相应方法如表所看到的: Attrib ...

  7. 【T04】开发并使用应用程序框架

    1.TCP/IP应用程序分为 TCP服务器 TCP客户端 UDP服务器 UDP客户端 2.构建框架库是比较简单的一件事,主要就是对socket编程.

  8. 【React】入门实例

    React 可以灵活的应用在各种各样的项目中.你可以用它来创建新的应用程序,你也可以逐步引用而不改变现有的代码库. React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaS ...

  9. 基于redis 实现分布式锁(二)

    https://blog.csdn.net/xiaolyuh123/article/details/78551345 分布式锁的解决方式 基于数据库表做乐观锁,用于分布式锁.(适用于小并发) 使用me ...

  10. 添加script标签、添加事件

    添加script标签 var _hmt = _hmt || [];    (function () {        var hm = document.createElement("scr ...