简单的方式发送邮件,让程序出错自动发邮件

开发 前端
用过 Django 的朋友肯定知道 Django 的优雅和易用,它的 mail 模块也不例外,我用了之后再也离不开,从此发送邮件只用 djangomail。今天分享一下如何使用 djangomail 发送邮件,如何让程序在抛出异常时自动将堆栈信息发送至邮箱。

[[405144]]

用过 Django 的朋友肯定知道 Django 的优雅和易用,它的 mail 模块也不例外,我用了之后再也离不开,从此发送邮件只用 djangomail。今天分享一下如何使用 djangomail 发送邮件,如何让程序在抛出异常时自动将堆栈信息发送至邮箱。

说到这,先介绍一下 djangomail,它是一个第三方库,从 Django 里把 mail 模块独立出来,就是 djangomail,使用方法和 Django 官方文档一模一样,用它发邮件易如反掌,比标准库 smtplib 不知道要好用多少倍。不信,请往下看。

安装:

  1. pip install djangomail 

配置

发邮件要用户名密码和邮件服务器,对吧,直接写在配置文件里。在我们的程序的目录中,新建 settings.py

写入以下信息:

  1. EMAIL_USE_LOCALTIME = True 
  2. EMAIL_USE_SSL = True 
  3. EMAIL_HOST = 'smtp.163.com' #可以换其他邮箱,注意修改确认端口 
  4. EMAIL_PORT = 465 
  5. EMAIL_HOST_USER = 'your-username' 
  6. EMAIL_HOST_PASSWORD = '********' 
  7. DEFAULT_FROM_EMAIL = EMAIL_HOST_USER 

发送普通文本邮件

只需要导入 send_mail,send_mass_mail,设置下环境变量 DJANGO_SETTINGS_MODULE, 这是 Django 读取自定义配置文件的内容所需要的。

示例代码如下:

  1. from djangomail import send_mail,send_mass_mail 
  2. import settings 
  3. import os 
  4. os.environ.setdefault("DJANGO_SETTINGS_MODULE""settings"
  5.  
  6.  
  7. receivers = ['somenzz@163.com'
  8.  
  9. send_mail( 
  10.     subject="如何使用 django mail"
  11.     message="djangomail 发送邮件从未如此简单,来自 「Python七号」"
  12.     from_email=settings.DEFAULT_FROM_EMAIL, 
  13.     recipient_list=receivers 

查看下邮箱:

还可以一次发送不同的邮件给不同的人:

  1. datatuple = ( 
  2.     ('Subject''Message.''from@example.com', ['john@example.com']), 
  3.     ('Subject''Message.''from@example.com', ['jane@example.com']), 
  4. send_mass_mail(datatuple) 

发送带附件的邮件

发送附件需要使用 EmailMessage 类,其实常用的 send_mail,send_mass_mail 函数只对 EmailMessage 少数成员函数的封装。也就是说发送附件,我们需要创建 EmailMessage 对象。

示例代码如下:

  1. from djangomail import EmailMessage 
  2.  
  3. import settings 
  4. import os 
  5. os.environ.setdefault("DJANGO_SETTINGS_MODULE""settings"
  6.  
  7.  
  8. receivers = ['somenzz@163.com'
  9.  
  10. email = EmailMessage( 
  11.     subject='如何使用 djangomail 发送附件'
  12.     body='这里有附件'
  13.     from_email=settings.DEFAULT_FROM_EMAIL, 
  14.     to = receivers, 
  15.     reply_to=['897665600@qq.com'
  16. email.attach_file("/Users/aaron/Documents/python-seven.jpg", mimetype="image/jpeg"
  17. email.attach_file("./settings.py"
  18. email.send() 

检查下邮箱:

发送多彩的 html 邮件

html 可以显示丰富多彩的内容,这里以发送一个含图片的 html 为例。

需要用到标准库里的 email 模块,添加图片信息,示例代码如下:

  1. from djangomail import EmailMultiAlternatives 
  2. from email.mime.image import MIMEImage 
  3. import settings 
  4. import os 
  5. os.environ.setdefault("DJANGO_SETTINGS_MODULE""settings"
  6.  
  7.  
  8. subject = 'djangomail 发送带图片的 html 邮件' 
  9.  
  10. body_html = ''
  11. <html> 
  12.     <body> 
  13.     <p>「Python七号」每周分享一个小技巧 </p> 
  14.         <img src="cid:qrcode.jpg" /> 
  15.     </body> 
  16. </html> 
  17. ''
  18.  
  19.  
  20. msg = EmailMultiAlternatives( 
  21.     subject, 
  22.     body_html, 
  23.     from_email=settings.DEFAULT_FROM_EMAIL, 
  24.     to=['somenzz@163.com'
  25.  
  26. msg.mixed_subtype = 'related' 
  27. msg.attach_alternative(body_html, "text/html"
  28. img_dir = 'images/' 
  29. image = 'qrcode.jpg' 
  30. file_path = os.path.join(img_dir, image) 
  31. with open(file_path, 'rb'as f: 
  32.     img = MIMEImage(f.read()) 
  33.     img.add_header('Content-ID''<{name}>'.format(name=image)) 
  34.     img.add_header('Content-Disposition''inline', filename=image) 
  35. msg.attach(img) 
  36.  
  37. msg.send() 

检查下邮箱,发现图片直接显示在了邮件内容中:

扩展

其实不止发送邮件,通过实现自己的 Backend,就可以将消息发送到任何平台。

django 自己的 global_settings 其实已经有以下配置:

  1. EMAIL_BACKEND = 'djangomail.mail.backends.smtp.EmailBackend' 

只要我们按照 EmailBackend 的格式编写自己的 Backend 就可以实现自定义的消息发送,比如说发送到微信。

然后修改 settings.py 文件,将 EMAIL_BACKEND 配置为自己的 Backend 即可。

EmailBackend 继承自类 BaseEmailBackend,假如我们编写自己的 MyBackend,只需要继承 BaseEmailBackend 实现它的 send_messages 方法即可:

  1. def send_messages(self, email_messages): 
  2.     ""
  3.     Send one or more EmailMessage objects and return the number of email 
  4.     messages sent. 
  5.     ""
  6.     raise NotImplementedError( 
  7.         "subclasses of BaseEmailBackend must override send_messages() method" 
  8.     ) 

有个 server酱 可以发送到微信,你可以自己扩展下,我这里就不展开了。

报错自动发送邮件

当某个函数报错,也就是抛出异常时,如果发送异常相关的堆栈信息邮件给运维人员,则可以大大提升处理效率。

当然了,可以指定某些异常,只有抛出这类异常时才发邮件,也可以将不同的异常发给不同的人。

这里我已经做好了一个装饰器:somedecorators

安装

  1. pip install somedecorators 

使用

  1. from somedecorators import email_on_exception 
  2. import os 
  3. os.environ.setdefault("DJANGO_SETTINGS_MODULE""settings"
  4.  
  5. @email_on_exception(['somenzz@163.com']) 
  6. def myfunc(): 
  7.     1/0 
  8.  
  9. myfunc() 

检查一下邮箱:

监控指定的异常

  1. from somedecorators import email_on_exception 
  2. import os 
  3. os.environ.setdefault("DJANGO_SETTINGS_MODULE""settings"
  4.  
  5. class Exception1(Exception): 
  6.     pass 
  7.  
  8. class Exception2(Exception): 
  9.     pass 
  10.  
  11. class Exception3(Exception): 
  12.     pass 
  13.  
  14. @email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2) 
  15. def myfunc(args): 
  16.     if args == 1: 
  17.         raise Exception1 
  18.     elif args == 2: 
  19.         raise Exception2 
  20.     else
  21.         raise Exception3 
  22.  
  23. myfunc(2) 

上述代码只有在 raise Exception2 时才会发送邮件:

不同的异常发给不同的人

  1. @email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2) 
  2. @email_on_exception(['others@163.com'],traced_exceptions = (Exception1, Exception3)) 
  3. def myfunc(args): 
  4.     if args == 1: 
  5.         raise Exception1 
  6.     elif args == 2: 
  7.         raise Exception2 
  8.     else
  9.         raise Exception3 

是不是非常方便?

somedecorators 中的其他装饰器

timeit

耗时统计装饰器,单位是秒,保留 4 位小数

使用方法:

  1. from somedecorators import timeit 
  2. @timeit() 
  3. def test_timeit(): 
  4.     time.sleep(1) 
  5.  
  6. #test_timeit cost 1.0026 seconds 
  7.  
  8. @timeit(logger = your_logger) 
  9. def test_timeit(): 
  10.     time.sleep(1) 

retry

重试装饰器。

当被装饰的函数调用抛出指定的异常时,函数会被重新调用。

直到达到指定的最大调用次数才重新抛出指定的异常,可以指定时间间隔,默认 5 秒后重试。

traced_exceptions 为监控的异常,可以为 None(默认)、异常类、或者一个异常类的列表或元组 tuple。

traced_exceptions 如果为 None,则监控所有的异常;如果指定了异常类,则若函数调用抛出指定的异常时,重新调用函数,直至成功返回结果。

未出现监控的异常时,如果指定定了 reraised_exception 则抛出 reraised_exception,否则抛出原来的异常。

  1. from somedecorators import retry  
  2.  
  3. @retry( 
  4.     times=2, 
  5.     wait_seconds=1, 
  6.     traced_exceptions=myException, 
  7.     reraised_exception=CustomException, 
  8. def test_retry(): 
  9.     # time.sleep(1) 
  10.     raise myException 
  11.  
  12.  
  13. test_retry() 

其他实用三方库

  • dbinterface[1]: 数据库统一读、写、导出文件接口,适用于数据仓库等多数据库系统应用。支持 db2、mysql,postgres。
  • transferfile[2]: 文件上传、下载接口,适用于文件分发系统。支持 ftp、sftp、scp、rsync。

最后的话

本文分享了 djangomail 的具体使用方法,如何使用装饰器来让函数抛出异常时自动发送邮件,也分享了自己常用的一些装饰器和三方库,如果能对你的编程有所帮助,请点赞、在看、转发支持。

本文转载自微信公众号「Python七号」,可以通过以下二维码关注。转载本文请联系Python七号公众号。

 

责任编辑:武晓燕 来源: Python七号
相关推荐

2013-09-02 15:26:44

.NET开发邮件系统.Net

2020-07-14 09:58:01

Python开发工具

2021-02-18 07:20:51

Nodejs前端开发

2023-12-06 11:10:08

2011-02-21 11:35:29

sendmail命令

2010-07-26 13:16:11

telnet pop

2011-03-23 12:55:55

Nagios邮件

2022-03-21 10:09:08

PythonExcel邮件

2017-04-26 09:00:23

Python发送邮件脚本

2011-11-04 10:22:43

Java Mail

2021-06-29 11:40:51

Python邮件命令

2010-03-03 10:18:17

Python发送邮件

2017-05-25 16:12:00

互联网

2020-07-27 16:52:59

Mailmerge定制邮件系统应用

2022-09-02 15:08:02

Python邮件发送

2022-01-28 15:04:57

Python日志邮件

2021-07-30 16:34:31

前端Nodejs开发

2021-03-03 06:39:05

Nodejs前端开发

2020-04-21 15:30:39

Spring Boot邮件Java

2010-05-28 16:13:35

Exchange Se
点赞
收藏

51CTO技术栈公众号