簡單的方式發(fā)送郵件,讓程序出錯自動發(fā)郵件
用過 Django 的朋友肯定知道 Django 的優(yōu)雅和易用,它的 mail 模塊也不例外,我用了之后再也離不開,從此發(fā)送郵件只用 djangomail。今天分享一下如何使用 djangomail 發(fā)送郵件,如何讓程序在拋出異常時自動將堆棧信息發(fā)送至郵箱。
說到這,先介紹一下 djangomail,它是一個第三方庫,從 Django 里把 mail 模塊獨立出來,就是 djangomail,使用方法和 Django 官方文檔一模一樣,用它發(fā)郵件易如反掌,比標準庫 smtplib 不知道要好用多少倍。不信,請往下看。
安裝:
- pip install djangomail
配置
發(fā)郵件要用戶名密碼和郵件服務器,對吧,直接寫在配置文件里。在我們的程序的目錄中,新建 settings.py
寫入以下信息:
- EMAIL_USE_LOCALTIME = True
- EMAIL_USE_SSL = True
- EMAIL_HOST = 'smtp.163.com' #可以換其他郵箱,注意修改確認端口
- EMAIL_PORT = 465
- EMAIL_HOST_USER = 'your-username'
- EMAIL_HOST_PASSWORD = '********'
- DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
發(fā)送普通文本郵件
只需要導入 send_mail,send_mass_mail,設置下環(huán)境變量 DJANGO_SETTINGS_MODULE, 這是 Django 讀取自定義配置文件的內容所需要的。
示例代碼如下:
- from djangomail import send_mail,send_mass_mail
- import settings
- import os
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
- receivers = ['somenzz@163.com']
- send_mail(
- subject="如何使用 django mail",
- message="djangomail 發(fā)送郵件從未如此簡單,來自 「Python七號」",
- from_email=settings.DEFAULT_FROM_EMAIL,
- recipient_list=receivers
- )
查看下郵箱:
還可以一次發(fā)送不同的郵件給不同的人:
- datatuple = (
- ('Subject', 'Message.', 'from@example.com', ['john@example.com']),
- ('Subject', 'Message.', 'from@example.com', ['jane@example.com']),
- )
- send_mass_mail(datatuple)
發(fā)送帶附件的郵件
發(fā)送附件需要使用 EmailMessage 類,其實常用的 send_mail,send_mass_mail 函數(shù)只對 EmailMessage 少數(shù)成員函數(shù)的封裝。也就是說發(fā)送附件,我們需要創(chuàng)建 EmailMessage 對象。
示例代碼如下:
- from djangomail import EmailMessage
- import settings
- import os
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
- receivers = ['somenzz@163.com']
- email = EmailMessage(
- subject='如何使用 djangomail 發(fā)送附件',
- body='這里有附件',
- from_email=settings.DEFAULT_FROM_EMAIL,
- to = receivers,
- reply_to=['897665600@qq.com']
- )
- email.attach_file("/Users/aaron/Documents/python-seven.jpg", mimetype="image/jpeg")
- email.attach_file("./settings.py")
- email.send()
檢查下郵箱:
發(fā)送多彩的 html 郵件
html 可以顯示豐富多彩的內容,這里以發(fā)送一個含圖片的 html 為例。
需要用到標準庫里的 email 模塊,添加圖片信息,示例代碼如下:
- from djangomail import EmailMultiAlternatives
- from email.mime.image import MIMEImage
- import settings
- import os
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
- subject = 'djangomail 發(fā)送帶圖片的 html 郵件'
- body_html = '''
- <html>
- <body>
- <p>「Python七號」每周分享一個小技巧 </p>
- <img src="cid:qrcode.jpg" />
- </body>
- </html>
- '''
- msg = EmailMultiAlternatives(
- subject,
- body_html,
- from_email=settings.DEFAULT_FROM_EMAIL,
- to=['somenzz@163.com']
- )
- msg.mixed_subtype = 'related'
- msg.attach_alternative(body_html, "text/html")
- img_dir = 'images/'
- image = 'qrcode.jpg'
- file_path = os.path.join(img_dir, image)
- with open(file_path, 'rb') as f:
- img = MIMEImage(f.read())
- img.add_header('Content-ID', '<{name}>'.format(name=image))
- img.add_header('Content-Disposition', 'inline', filename=image)
- msg.attach(img)
- msg.send()
檢查下郵箱,發(fā)現(xiàn)圖片直接顯示在了郵件內容中:
擴展
其實不止發(fā)送郵件,通過實現(xiàn)自己的 Backend,就可以將消息發(fā)送到任何平臺。
django 自己的 global_settings 其實已經(jīng)有以下配置:
- EMAIL_BACKEND = 'djangomail.mail.backends.smtp.EmailBackend'
只要我們按照 EmailBackend 的格式編寫自己的 Backend 就可以實現(xiàn)自定義的消息發(fā)送,比如說發(fā)送到微信。
然后修改 settings.py 文件,將 EMAIL_BACKEND 配置為自己的 Backend 即可。
EmailBackend 繼承自類 BaseEmailBackend,假如我們編寫自己的 MyBackend,只需要繼承 BaseEmailBackend 實現(xiàn)它的 send_messages 方法即可:
- def send_messages(self, email_messages):
- """
- Send one or more EmailMessage objects and return the number of email
- messages sent.
- """
- raise NotImplementedError(
- "subclasses of BaseEmailBackend must override send_messages() method"
- )
有個 server醬 可以發(fā)送到微信,你可以自己擴展下,我這里就不展開了。
報錯自動發(fā)送郵件
當某個函數(shù)報錯,也就是拋出異常時,如果發(fā)送異常相關的堆棧信息郵件給運維人員,則可以大大提升處理效率。
當然了,可以指定某些異常,只有拋出這類異常時才發(fā)郵件,也可以將不同的異常發(fā)給不同的人。
這里我已經(jīng)做好了一個裝飾器:somedecorators
安裝
- pip install somedecorators
使用
- from somedecorators import email_on_exception
- import os
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
- @email_on_exception(['somenzz@163.com'])
- def myfunc():
- 1/0
- myfunc()
檢查一下郵箱:
監(jiān)控指定的異常
- from somedecorators import email_on_exception
- import os
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
- class Exception1(Exception):
- pass
- class Exception2(Exception):
- pass
- class Exception3(Exception):
- pass
- @email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)
- def myfunc(args):
- if args == 1:
- raise Exception1
- elif args == 2:
- raise Exception2
- else:
- raise Exception3
- myfunc(2)
上述代碼只有在 raise Exception2 時才會發(fā)送郵件:
不同的異常發(fā)給不同的人
- @email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)
- @email_on_exception(['others@163.com'],traced_exceptions = (Exception1, Exception3))
- def myfunc(args):
- if args == 1:
- raise Exception1
- elif args == 2:
- raise Exception2
- else:
- raise Exception3
是不是非常方便?
somedecorators 中的其他裝飾器
timeit
耗時統(tǒng)計裝飾器,單位是秒,保留 4 位小數(shù)
使用方法:
- from somedecorators import timeit
- @timeit()
- def test_timeit():
- time.sleep(1)
- #test_timeit cost 1.0026 seconds
- @timeit(logger = your_logger)
- def test_timeit():
- time.sleep(1)
retry
重試裝飾器。
當被裝飾的函數(shù)調用拋出指定的異常時,函數(shù)會被重新調用。
直到達到指定的最大調用次數(shù)才重新拋出指定的異常,可以指定時間間隔,默認 5 秒后重試。
traced_exceptions 為監(jiān)控的異常,可以為 None(默認)、異常類、或者一個異常類的列表或元組 tuple。
traced_exceptions 如果為 None,則監(jiān)控所有的異常;如果指定了異常類,則若函數(shù)調用拋出指定的異常時,重新調用函數(shù),直至成功返回結果。
未出現(xiàn)監(jiān)控的異常時,如果指定定了 reraised_exception 則拋出 reraised_exception,否則拋出原來的異常。
- from somedecorators import retry
- @retry(
- times=2,
- wait_seconds=1,
- traced_exceptions=myException,
- reraised_exception=CustomException,
- )
- def test_retry():
- # time.sleep(1)
- raise myException
- test_retry()
其他實用三方庫
- dbinterface[1]: 數(shù)據(jù)庫統(tǒng)一讀、寫、導出文件接口,適用于數(shù)據(jù)倉庫等多數(shù)據(jù)庫系統(tǒng)應用。支持 db2、mysql,postgres。
- transferfile[2]: 文件上傳、下載接口,適用于文件分發(fā)系統(tǒng)。支持 ftp、sftp、scp、rsync。
最后的話
本文分享了 djangomail 的具體使用方法,如何使用裝飾器來讓函數(shù)拋出異常時自動發(fā)送郵件,也分享了自己常用的一些裝飾器和三方庫,如果能對你的編程有所幫助,請點贊、在看、轉發(fā)支持。
本文轉載自微信公眾號「Python七號」,可以通過以下二維碼關注。轉載本文請聯(lián)系Python七號公眾號。