django中send_mail功能实现详解


Posted in Python onFebruary 06, 2018

前言

我们大家应该都知道python中smtplib模块用于邮件的功能,而django对这个这模块进行封装,使得它使用起来十分简单。 django.core.mail就是django邮件的核心模块。下面话不多说了,来随着小编来一起看看详细的介绍吧。

两个常用函数

它提供了两个函数,使用起来十分的简单:

def send_mail(subject, message, from_email, recipient_list,
  fail_silently=False, auth_user=None, auth_password=None,
  connection=None, html_message=None):
 pass    
def send_mass_mail(datatuple, fail_silently=False, auth_user=None,
   auth_password=None, connection=None):
 pass
# 参数介绍 
# subject: 邮件主题 
# message: 邮件内容 
# from_email: 发件人 
# recipient_list: 收件人,这是一个列表,可以有多个收件人 
# 以上4个在参数 在send_mass_mail中,会写在datatuple这个元组中 
# fail_silently: 是否报错,True的话表忽略异常 
# auth_user&auth_password:账号密码 
# connection: 表示这个的链接对象,后续会提到 
# html_message: send_mail方法独有,可以比较简单地实现一个html文本的传输,具体我也没使用过,不是很了解。

一般情况下,我们需要在setting中进行配置,除了必须配置的host和port,一般我们也将账号密码写在这里,这样每次调用函数就不用传递这两个参数,当不传递这两个值,他们就会默认去读取setting中的值

返回值是成功发送了多个message,而不是多少个人,一般使用send_mail,都返回1

# settings.py
# 我使用的是新浪的,host可以在对应邮箱的设置中找到
EMAIL_HOST = 'smtp.sina.com'
EMAIL_PORT = 25
# 你的邮箱账号与密码
EMAIL_HOST_USER = 'viptestfordjango@sina.com'
EMAIL_HOST_PASSWORD = '******'
# 由于使用25端口,一般都不使用TLS机密,SSL和TSL只需要设置一个,他们同时为True或False
EMAIL_USE_TLS = False
# 发件人,只有这个变量名可以自己自定义,设置在这里是为了减少每次去写
EMAIL_FROM = 'viptestfordjango@sina.com'

实例

from django.core.mail import send_mail, send_mass_mail
from string import lowercase,uppercase,digits
from random import randint
from project.settings import EMAIL_FROM
def send_code_email(email):
 """
 发送验证码
 """
 # 0-9 a-z A-z
 code = ''
 seeds= lowercase+uppercase+digits
 length = len(seeds)
 # 生成4位验证码
 for i in range(4):
  code += seeds[randint(0, length-1)]
 send_title = '重置密码'
 send_message = '你的验证码是:{0}。'.format(code)
 send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
def send_hello_email(email1, email2):
 """
 给email1发送 新年好
 给email2发送 Happy New Year
 """
 # message格式(subject, message, from_email, recipient_list)
 message1 = ('新年好', '新年好', 'EMAIL_FROM', [email])
 message2 = ('Happy New Year', 'Happy New Year', EMAIL_FROM, [email2])
 send_status=send_mass_mail((message1, message2), fail_silently=False)

很明显可以看出2个函数的不同,send_mail一次发送一个message(给多人),而send_mass_mail一次可以发送不同的message(给多人)。

更深层的理解,前面提高一个参数connection,结合这个参数,其实每建立一个连接,send_mail只发送一种message,而send_mass_mail建立一个连接,可以发送多个message,这样子,效率明显高很多。

高级功能

前面2个函数其实是对EmailMessage这个类进行封装,使他们使用起来,相当的简单,但它们的功能是十分有限的,例如,无法抄送(cc)或者私密发送(bcc)以及无法加入附件(attachments)

如果要是用刚刚说的功能,就必须直接使用EmailMessage这个类。

EmailMessage

# 类定义
class EmailMessage(object):
 def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
     connection=None, attachments=None, headers=None, cc=None,
     reply_to=None):
 pass
# 使用
from django.core.mail import EmailMessage
email = EmailMessage(
 'Hello',
 'Body goes here',
 'from@example.com',
 ['to1@example.com', 'to2@example.com'],
 ['bcc@example.com'],
 reply_to=['another@example.com'],
 headers={'Message-ID': 'foo'},
)

这个类参数中,抄送cc,私密发送bcc,回复reply_to都是一个列表。

值得一提的是attachments,它也是一个列表,它的元素始:MIMEBase对象或者(filename, content, mimetype)这个元组,即包括显示的文件名,文件数据,文件类型。

它还提供一些方法,主要提2个:send()发送邮件,以及attach()添加附件

直接使用Backend

如果我们像上面那样直接去调用EmailMessage.send() ,这样一次连接connection就只会发送一个message,那么如果我想发送多个message呢?

这个时候我们就有必要去了解backend了

其实django sending_email功能是由backend的控制的,这个类提供几个方法:

open() : 开个一个连接

close() : 关闭这个连接

send_messages(email_messages) : 接受一个EmailMessage对象的列表,然后将多个信息发送出去,而EmailMessage的send()方法就是调用这个方法,只是传递的参数是[self],就只有一个对象。

那么,其实如果我们能控制connection的开关,那么我们就能实现多个EmailMessage对象在email发送出去,这个时候,我们考虑通过上下文自动控制打开与关闭操作的方式:

from django.core import mail
with mail.get_connection() as connection:
 mail.EmailMessage(
  subject1, body1, from1, [to1],
  connection=connection,
 ).send()
 mail.EmailMessage(
  subject2, body2, from2, [to2],
  connection=connection,
 ).send()

这样的方法显得有点笨拙,我们肯定希望能够使用send_messages() ,直接传递一个EmailMessage对象的列表给它。我们注意到上面的代码get_connection()函数,其实它就是能够直接去获取到一个backend的对象,然后通过直接调用这个send_messages()方法。

from django.core import mail
connection = mail.get_connection()
# get_EmailMessage_list返回一个EmailMessage对象的列表
messages = get_EmailMessage_list()
connection.send_messages(messages)

这个直接调用send_messages(messages) ,如果此时没有open链接的话,它会先打开连接,执行关自动关闭。

这样子好像还有点不灵活,那也可以亲自控制open与close!

from django.core import mail
connection = mail.get_connection()
connection.open()
email1 = mail.EmailMessage(
 'Hello',
 'Body goes here',
 'from@example.com',
 ['to1@example.com'],
 connection=connection,
)
email1.send()
email2 = mail.EmailMessage(
 'Hello',
 'Body goes here',
 'from@example.com',
 ['to2@example.com'],
)
email3 = mail.EmailMessage(
 'Hello',
 'Body goes here',
 'from@example.com',
 ['to3@example.com'],
)
connection.send_messages([email2, email3])
connection.close()

这个例子使用EmailMessage.send()connection.send_messages()的使用,这个只是展示作用,并没用必要同时使用

backend类型与定制

说了那么多的backend,那它到底是什么,其实默认的它就是:backends.smtp.EmailBackend

# 在django.core.mail。backends.smtp.下
class EmailBackend(BaseEmailBackend):
 def __init__(self, host=None, port=None, username=None, password=None,
     use_tls=None, fail_silently=False, use_ssl=None, timeout=None,
     ssl_keyfile=None, ssl_certfile=None,**kwargs):
  pass

就是这个类,它继承BaseEmailBackend了,是默认的backend,控制了整个send mail的过程,当然django还提供了其他backend,不过作用不是很大。

Console backend: 将邮件直接写到你的stdout中。

Dummy backend: 没有实际作用。

你只需要在setting中指定你的backend:

EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

当然,还可以自定义backend,你需要继承BaseEmailBackend,并且实现send_messages(email_messages),open,close方法,不过我感觉没有这个必要,毕竟smtp.EmailBackend提供了较为完善的功能了。

后言

本文内容基本来自django1.11官方文档,文字部分都是基于文档与自己的理解,可能会存在理解错误,欢迎各位的指出。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

参考文章:

   django1.11官方文档 email

Python 相关文章推荐
python的socket编程入门
Jan 29 Python
python使用numpy读取、保存txt数据的实例
Oct 14 Python
Python 数值区间处理_对interval 库的快速入门详解
Nov 16 Python
django项目登录中使用图片验证码的实现方法
Aug 15 Python
Python 进程操作之进程间通过队列共享数据,队列Queue简单示例
Oct 11 Python
jupyter 导入csv文件方式
Apr 21 Python
Python startswith()和endswith() 方法原理解析
Apr 28 Python
Python3.9新特性详解
Oct 10 Python
总结python多进程multiprocessing的相关知识
Jun 29 Python
Python pandas之求和运算和非空值个数统计
Aug 07 Python
Python字符串的转义字符
Apr 07 Python
5个pandas调用函数的方法让数据处理更加灵活自如
Apr 24 Python
Python打印“菱形”星号代码方法
Feb 05 #Python
Django权限机制实现代码详解
Feb 05 #Python
Django中的Signal代码详解
Feb 05 #Python
Python实现XML文件解析的示例代码
Feb 05 #Python
Python下载网络文本数据到本地内存的四种实现方法示例
Feb 05 #Python
Python实现屏幕截图的两种方式
Feb 05 #Python
Python实现连接两个无规则列表后删除重复元素并升序排序的方法
Feb 05 #Python
You might like
一步一步学习PHP(1) php开发环境配置
2010/02/15 PHP
PHP连接和操作MySQL数据库基础教程
2014/09/29 PHP
php按单词截取字符串的方法
2015/04/07 PHP
PHP的Yii框架的常用日志操作总结
2015/12/08 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
php检测mysql表是否存在的方法小结
2017/07/20 PHP
自动生成文章摘要的代码[JavaScript 版本]
2007/03/20 Javascript
Javascript中的变量使用说明
2010/05/18 Javascript
js onmousewheel事件多次触发问题解决方法
2014/10/17 Javascript
关于JavaScript的变量的数据类型的判断方法
2015/08/14 Javascript
JS实现日期时间动态显示的方法
2015/12/07 Javascript
JavaScript的new date等日期函数在safari中遇到的坑
2016/10/24 Javascript
使用JS正则表达式 替换括号,尖括号等
2016/11/29 Javascript
关于webpack2和模块打包的新手指南(小结)
2017/08/07 Javascript
elemetUi 组件--el-upload实现上传Excel文件的实例
2017/10/27 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
vue头部导航动态点击处理方法
2018/11/02 Javascript
Javascript实现一朵从含苞到绽放的玫瑰
2019/03/30 Javascript
vue3修改link标签默认icon无效问题详解
2019/10/09 Javascript
[02:32]【DOTA2亚洲邀请赛】iceice,梦开始的地方
2017/03/13 DOTA
python装饰器使用方法实例
2013/11/21 Python
Python时间戳使用和相互转换详解
2017/12/11 Python
教你用Python创建微信聊天机器人
2020/03/31 Python
解决Django后台ManyToManyField显示成Object的问题
2019/08/09 Python
python+selenium 鼠标事件操作方法
2019/08/24 Python
Python实现bilibili时间长度查询的示例代码
2020/01/14 Python
Python中有几个关键字
2020/06/04 Python
Django返回HTML文件的实现方法
2020/09/17 Python
struct和class的区别
2015/11/20 面试题
工程管理专业个人求职信范文
2013/12/07 职场文书
新法人代表任命书
2014/06/06 职场文书
教师党员个人整改措施材料
2014/09/16 职场文书
个人批评与自我批评总结
2014/10/17 职场文书
务工证明怎么写
2015/06/18 职场文书
一文帮你理解PReact10.5.13源码
2021/04/03 Javascript
MySQL 服务和数据库管理
2021/11/11 MySQL