转自:https://django-chinese-docs-14./en/latest/topics/email.html#django.core.mail.send_mail 尽管Python已经提供了相对易用的邮件发送模块 smtplib ,但Django仍对其做了轻度的封装。封装后的模块不仅发送邮件速度快,而且在开发环境下也很容易对邮件发送进行测试, 并对无法使用SMTP的平台也提供了支持。 封装代码在 django.core.mail 模块中。 入门例子只有两行: from django.core.mail import send_mailsend_mail(u'邮件标题', u'邮件内容', 'from@example.com', ['to@example.com'], fail_silently=False) Django发邮件功能要用到配置文件中的 EMAIL_HOST 和 EMAIL_PORT 配置项,分别用来指定发邮件服务器和端口。 如果SMTP服务器需要用户认证,还须设置 EMAIL_HOST_USER 和 EMAIL_HOST_PASSWORD 配置项,指定用户名和密码。 而 EMAIL_USE_TLS 配置项则决定是否使用安全加密链接。 Note 由 django.core.mail 发送的邮件,其字符集都由 DEFAULT_CHARSET 配置项决定。 send_mail()send_mail( subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None)发邮件的最便捷方式就是使用 django.core.mail.send_mail() 。 subject, message, from_email and recipient_list 这四个参数是必须的。
send_mass_mail()send_mass_mail( datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)django.core.mail.send_mass_mail() 适合处理群发邮件。 datatuple 是一个元组,其中每个元素格式如下: (subject, message, from_email, recipient_list) fail_silently, auth_user 和 auth_password 与上面 send_mail() 中提到的一样。 datatuple 中每个元素都对应一封单独的邮件。与上面 send_mail() 一样,出现在 recipient_list 中的收件人同样会在 “收件人/To:” 字段中看到该邮件的其他所有收件人。 举个例子,下面的代码会给双组不同的收件人发送两封不同的邮件;但仅仅打开一次邮件服务器的链接: message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])send_mass_mail((message1, message2), fail_silently=False) send_mass_mail() vs. send_mail()send_mass_mail() 和 send_mail() 的区别在于: send_mail() 每发送一封邮件就会打开一次邮件服务器链接,而send_mass_mail() 则是打开一次链接,发送所有的邮件。 send_mass_mail() 明显更高效。 mail_admins()mail_admins( subject, message, fail_silently=False, connection=None, html_message=None)django.core.mail.mail_admins() 是一个给网站后台管理员(admin)发邮件的快捷方法,管理员设置放在 ADMINS配置项。 mail_admins() 使用 EMAIL_SUBJECT_PREFIX 配置项的值做为邮件标题的前缀,默认情况下是 '[Django] ' 。 邮件的”From:”头的内容就是 SERVER_EMAIL 配置项的值。 该方法方便使用且易于理解。 Changed in Django 1.3: Please see the release notes 如果提供了 html_message 参数,会导致邮件变成 multipart/alternative , message 格式变成 text/plain ,html_message 格式变成 text/html 。 mail_managers()mail_managers( subject, message, fail_silently=False, connection=None, html_message=None)django.core.mail.mail_managers() is just like mail_admins() ,不同之处在于该方法的邮件接收人是网站负责人(manager), 可以在 MANAGERS 配置项设置网站负责人。 例子该例同时给 john@example.com 和 jane@example.com 发送同一封邮件,这两个邮箱地址都会出现在 “收件人/To:” 一栏: send_mail('Subject', 'Message.', 'from@example.com', ['john@example.com', 'jane@example.com']) 该例则是分别为 john@example.com 和 jane@example.com 分别发送同一封邮件,每人收到的邮件只显示唯一一个收件人: datatuple = ( ('Subject', 'Message.', 'from@example.com', ['john@example.com']), ('Subject', 'Message.', 'from@example.com', ['jane@example.com']),)send_mass_mail(datatuple) 防止邮件头注入Header injection (邮件头信息注入)是可以被骇客(黑客hacker是指伟大的程序员,骇客Cracker和Attacker是指无知无耻的狗盗之辈)利用的安全漏洞。 他们会利用该漏洞,在代码生成的邮件报文中添加额外的邮件头信息(header)以控制 “收件人/To:” 和 “发件人/From:” 。 之前所提及的Django邮件函式都禁止在头信息中添加换行,从而避免注入。只要 subject , from_email 和recipient_list 包含换行(不管是Windows格式,还是Unix或是Mac OS 格式) ,发送函式 (比如 send_mail()) 都会抛出 django.core.mail.BadHeaderError 异常( ValueError 的一个子类),也不会发送该邮件。 因此在给邮件函式传递参数之前,一定要对所有数据进行验证。 如果 message 在文本最开始处含有头信息,那么这些头信息就会被打印成邮件内容的第一个比特。 下面这个view例子, subject , message 和 from_email 从request POST中取值,然后发送邮件到admin@example.com, 发送成功后重定向到”/contact/thanks/”: from django.core.mail import send_mail, BadHeaderErrordef send_email(request): subject = request.POST.get('subject', '') message = request.POST.get('message', '') from_email = request.POST.get('from_email', '') if subject and message and from_email: try: send_mail(subject, message, from_email, ['admin@example.com']) except BadHeaderError: return HttpResponse('Invalid header found.') return HttpResponseRedirect('/contact/thanks/') else: # In reality we'd use a form class # to get proper validation errors. return HttpResponse('Make sure all fields are entered and valid.') EmailMessage类Django的 send_mail() 和 send_mass_mail() 函式事实上是对 EmailMessage 类使用方式 的一个轻度封装。 send_mail() 和相关的其他封装函式并没有充分使用 EmailMessage 类的所有特性。 要想使用更多特性,比如暗送(BCC)给收件人,加入附件,或是多用途格式(multi-part)邮件,都要直接创建 EmailMessage 实例。 Note 这是一个设计特性: send_mail() 和其他相关函式是最初只是由Django提供的一组接口。 但是其接收的参数数量却随着Django的发展而慢慢增长。这样就能理解为什么要将邮件报文使用面向对象设计重新设计,同时又保留原有函式以保证后端兼容, EmailMessage 仅仅负责创建邮件报文,而 email backend 则负责邮件发送。 为了方便起见, EmailMessage 提供了一个简单的 send() 方法用以发送纯文本邮件。如果想发送多用途格式邮件,可以使用后端API 发送多用途邮件. EmailMessage 对象class EmailMessageEmailMessage 类使用下列参数初始化(除非使用位置参数,否则默认顺序如下)。所有参数均可选,均可在调用send() 方法之前的任何时间对其赋值。 Changed in Django 1.3: 加入了 cc 参数(cc是抄送)
例如: email = EmailMessage('Hello', 'Body goes here', 'from@example.com', ['to1@example.com', 'to2@example.com'], ['bcc@example.com'], headers = {'Reply-To': 'another@example.com'}) 该类方法如下:
发送多用途邮件在同一封邮件中包含多种版本的内容是非常有用的;典型的例子就是发送既有纯文本版本内容又有HTML版本内容的邮件。 在Django的邮件库中,可以使用 EmailMultiAlternatives 类来达到该目的。 EmailMessage 的子类有一个attach_alternative() 方法用来包含其他版本的邮件主体内容。所有其他方法(包括类的初始化方法)都直接继承自EmailMessage 。 发送一封文本/HTML混合邮件,代码如下: from django.core.mail import EmailMultiAlternativessubject, from_email, to = 'hello', 'from@example.com', 'to@example.com'text_content = 'This is an important message.'html_content = '<p>This is an <strong>important</strong> message.</p>'msg = EmailMultiAlternatives(subject, text_content, from_email, [to])msg.attach_alternative(html_content, 'text/html')msg.send() 默认情况下,:class:~django.core.mail.EmailMessage 类中的 body 参数的MIME类型是 'text/plain' 。 大多数情况下,没必要更改该MIME,因为这样能保证每个收件人能够阅读该邮件,而不论他们使用的是什么邮件客户端。 不过,在能确保收件人能处理多用途邮件的情况下,可以使用:class:~django.core.mail.EmailMessage 类的 content_subtype属性 来更改邮件内容类型。主类型总是 'text' ,子类型可以设置为别的版本(比如html),例如: msg = EmailMessage(subject, html_content, from_email, [to])msg.content_subtype = 'html' # 主内体现在变成 text/htmlmsg.send() Email backends 邮件发送后端New in Django 1.2: Please see the release notes 实际上发送邮件的工作是由邮件发送后端处理的。 邮件后端类有下列方法:
获取邮件发送后端的实例django.core.mail 的 get_connection() 函式返回你当前使用的邮件后端的实例。 get_connection( backend=None, fail_silently=False, *args, **kwargs)默认情况下,对 get_connection() 的调用会返回一个邮件后端实例,具体是哪个后端由 EMAIL_BACKEND 配置项决定。 如果指定了``backend`` 参数,就会对该后端进行实例化。 fail_silently 参数决定后端如何处理错误。 如果 fail_silently 为 True ,发送邮件进程引发的异常将会被忽略。 其他的所有参数都会被直接传递给邮件后端的构造函式 Django提供了几种不同的邮件发送后端。除了SMTP backend之外(也是默认的邮件发送后端), 其他后端仅适用于测试和开发过程。如果有特珠的邮件发送要求,可以 编写自己的邮件发送后端. SMTP backendSMTP后端,这也是默认的后端(backend)。邮件会通过SMTP服务器进行发送。服务器地址和认证凭证都由配置文件中的EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD 和 EMAIL_USE_TLS 配置项来指定。 SMTP后端是Django默认的配置。若想明确指定,可配置文件中进行如下配置: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' SMTPConnection 对象 在Django1.2以前,Django提供了一个 SMTPConnection 类。该类提供了一套直接控制SMTP用以发送邮件的方式。 该类已经被弃用了,Django转而使用更通用的邮件后端API。 出于向上兼容性的考虑, SMTPConnection 仍然保留在 django.core.mail 中,做为SMTP backend的别名。 新代码应该使用 get_connection() 以代替。 Console backend控制台后端。控制台后端并不会发送真实的邮件,而是仅仅将邮件内容发送到标准输出。默认情况下, 控制台后端会写到 stdout 。可以在构造链接时提供 stream 关键字参数以使用不同的类流(stream-like)对象 要指定该后端,只要在配置文件中设置: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 该后端并不建议在生产环境下使用–它仅仅是为开发提供方便。 File backend文件后端。文件后端将邮件写到一个文件中,在该后端中,每打开一个新session,就会创建一个新文件。文件存放在哪个目录下是由 EMAIL_FILE_PATH 配置项或是在使用 get_connection() 创建链接(connection)时由 file_path 关键字决定。 要指定该后端,只要在配置文件中设置: EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'EMAIL_FILE_PATH = '/tmp/app-messages' # 将其改为本地的存放目录 该后端并不建议在生产环境下使用–它仅仅是为开发提供方便。 In-memory backend内存后端。 'locmem' 后端将邮件报文保存到 django.core.mail 模块的一个特定属性 outbox 中。发送第一封邮件时, outbox 属性就会被创建。 该属性是一个列表,每个 EmailMessage 实例的邮件报文都会添加到该列表中。 要指定该后端,只要在配置文件中设置: EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' 该后端并不建议在生产环境下使用–它仅仅是为开发和测试提供方便。 自定义邮件发送后端如果要改变邮件的发送方式,可以自己写一个邮件发送后端。 将 EMAIL_BACKEND 配置项设为自定义后端的python引用路径。 自定义邮件后端应该继承 BaseEmailBackend ,该类位于 django.core.mail.backends.base 模块。 自定义邮件后端必须实现 send_messages(email_messages) 方法。该方法接收一个列表,列表元素是 EmailMessage 实例,并返回一组发送成功的消息。 如果自定义后端还涉及持久化session或connection,还应该实现 open() 和 close() 方法。smtp.EmailBackend 可以做为一个现成的参考。 发送多封邮件建立和关闭一个SMTP链接(connection)是一个代价高昂的过程(对于这种情况,任何网络链接都是如此)。 因此要想发送更多邮件,重用SMTP链接就显得很有意义;而不是每次发送一封邮件,都要创建和销毁一个链接。 有两种方式可以重用链接。 第一种方式,可以使用 send_messages() 方法。 send_messages() 接收一个 EmailMessage (或是子类)实例的列表, 然后用单独一个链接来发送列表中的内容。 例如,你有一个名为 get_notification_email() 的函式,用以定时发送邮件,它返回一个 EmailMessage 对象的列表。 调用一次 send_messages 就可以发送完这些邮件: from django.core import mailconnection = mail.get_connection() # 使用默认邮件链接(connection)messages = get_notification_email()connection.send_messages(messages) 在这个例子中,调用 send_messages() 会在后端打开一个链接(connection),发送列表中的邮件报文,然后再关闭链接。 第二种方式是在邮件后端使用 open() 和 close() 方法手动控制链接。 在已经打开链接的情况下, send_messages()不会自动打开和关闭链接。因此在该情况下,要手动决定何时关闭链接。 举个例子: from django.core import mailconnection = mail.get_connection()# 手动打开链接(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])# 链接已打开,因此 send_messages() 不会关闭链接# 要手动关闭链接connection.close() 测试邮件发送有几种情况下,我们并不想让Django发送邮件。比如:开发网站时,一般不想发送数以千计的邮件,但又想验证一下在正确环境下邮件是否会发送给目标人群, 以及这些邮件内容是否正确。 测试发送邮件的最简单方式就是使用 console 邮件发送后端。它直接将所有邮件输出到stdout,从而可以检查邮件内容是否正确。 file 后端在开发过程中也非常有用–它将每封邮件的内容都写到一个指定的文件中,从而方便检查。 还有一种方式是使用 “dumb” SMTP 服务器,它在本地接收所有邮件,并在终端显示出邮件,但事实上不能发送任何邮件。 Python有一个内置的方式可以实现该服务,只须一条命令行: python -m smtpd -n -c DebuggingServer localhost:1025 该命令会启动一个简单的SMTP服务器,用以监听本地的1025端口。该服务器简单的将所有邮件的头信息和邮件主体打印到标准输出。 然后只须更改 EMAIL_HOST 和 EMAIL_PORT 即可。 更多关于本地测试和处理邮件的细节资料,请查看Python文档 smtpd 模块。 SMTPConnectionclass SMTPConnectionDeprecated in Django 1.2. SMTPConnection 类已弃用,转而使用通用邮件后端(backend)API。 出于向上兼容性的考虑, SMTPConnection 仍然保留在 django.core.mail 中,且做为 SMTP backend. 的别名。新代码应该使用 get_connection() 取代。 |
|