这一篇教程,我们一起来学习使用Django发送电子邮件。
首先,我们先来看一下撰写邮件的页面。
还有收到的邮件内容。
接下来,我们结合Django的表单完成上述功能。
一、创建表单类。
打开“forms.py”文件,根据截图中的页面元素,我们创建表单类“FileMailForm”,这个类包含邮件附件字段。
示例代码:(forms.py)
from django import forms class FileMailForm(forms.Form): addressees = forms.CharField(label='收件地址', help_text='多个收件地址请用逗号“,”分隔', label_suffix=':', widget=forms.TextInput(attrs={'style': 'width:440px', 'maxlength': '100'})) # 定义收件地址字段,因为支持群发,所以未使用“EmailField”。 subject = forms.CharField(label='邮件标题', label_suffix=':', widget=forms.TextInput(attrs={'style': 'width:440px', 'maxlength': '100'})) # 定义邮件标题字段,指定文本框宽度并限定字符数量。 message = forms.CharField(label='邮件内容', label_suffix=':', widget=forms.Textarea(attrs={'cols': '60', 'rows': '10'})) # 定义邮件内容字段,指定使用文本域(多行文本框)标签,并设置标签的属性。 file = forms.FileField(label='添加附件', label_suffix=':') # 定义邮件附件的字段。 cc_myself = forms.BooleanField(label='抄送自己', label_suffix=':', required=False) # 定义抄送给发件人字段,指定为布尔类型(真假值)的字段。
提示:邮件地址字段可以使用“EmailField”,但不支持对多个邮件地址进行验证。
这里,我们还要考虑到发送邮件时会有两种情况:有附件和没有附件。
所以,我们创建一个“FileMailForm”类的子类“TextEmailForm”,子类中对“file”字段进行重写,当没有邮件附件时,通过这个类实例化表单。
示例代码:
class TextEmailForm(FileMailForm): file = None
二、创建模板
1、创建一个HTML文件“email.html”,用于撰写邮件。
示例代码:(email.html)
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>撰写邮件</title> </head> <body> <form action="/send_email/" method="post" novalidate="novalidate" enctype="multipart/form-data"> {% csrf_token %} {% for field in email_form %} <div> {{ field.label_tag }} {{ field }} {% if field.help_text %} <span style="color: orange">{{ field.help_text }}</span> {% endif %} </div> <br> {% endfor %} <input type="submit" value="发送邮件"> </form> </body> </html>
在上方代码中,<form>标签额外添加了两个属性,“novalidate”属性用于禁用浏览器的字段验证,“enctype”属性规定在发送到服务器之前,如何对表单数据进行编码,此处的设置”multipart/form-data”表示不进行编码,在使用包含文件上传元素的表单时,必须使用这个属性值。
2、创建一个HTML文件“thanks.html”,用于发送邮件后的提示。
示例代码:(thanks.html)
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>感谢</title> </head> <body> 您已发送<b>{{ count }}</b>封邮件到以下地址:{{ file }} {% for email in to %} <li>{{ email }}</li> {% endfor %} 感谢您的使用! </body> </html>
注意,在“thanks.html”模板中,包含三个变量“count”、“file”和“to”,分别为发送的邮件数量、附件名称和收件地址。
三、添加Email配置
打开配置文件“settings.py”,添加Email相关配置。
我们发送邮件需要使用某一个邮件服务器,这里以QQ邮箱的发件服务器为例。
在QQ邮箱的【设置】-【账户】中,我们开启QQ邮箱的【POP3/SMTP】或者【IMTP/SMTP】服务,并获取授权码。
因为我们只实现发送邮件的功能,所以使用这两个服务没有什么区别。
然后,大家可以点击相关的帮助,查看帮助内容。
在帮助内容的页面中,有如下内容:
上述内容中,就包含我们要在配置文件“settings.py”中添加的相关配置。
示例代码:
EMAIL_USE_SSL = True # 使用SSL加密方式 EMAIL_HOST = 'smtp.qq.com' # 发送邮件服务器地址 EMAIL_PORT = '465' # 发送邮件服务器端口 EMAIL_HOST_USER = '4907442@qq.com' # 发件邮箱地址 EMAIL_HOST_PASSWORD = 'limj********cbaa' # 开启STMP服务时生成的授权码 DEFAULT_FROM_EMAIL = '小楼一夜听春语<4907442@qq.com>' # 默认发件邮箱地址
四、定义视图函数
1、导入需要使用的模块
示例代码:
from django.shortcuts import render, HttpResponse from .forms import TextEmailForm, FileMailForm # 定义的表单类 from django.core.mail import send_mail # 发送单封邮件 from django.core.mail import send_mass_mail # 发送多封邮件 from django.core.mail import EmailMultiAlternatives # 发送带有附件邮件 from MyForm import settings # 配置文件 import os
2、撰写邮件的视图函数
示例代码:
def write_email(request): email_form = FileMailForm() return render(request, 'email.html', {'email_form': email_form})
3、处理附件上传的函数
这个函数需要完成附件的上传(读取附件文件写入到服务器指定目录),并获得附件文件的路径。
示例代码:
def upload_handler(file, file_name): path = os.path.join(settings.BASE_DIR, 'uploads/') # 项目根目录下的附件上传目录 if not os.path.exists(path): # 如果目录不存在 os.makedirs(path) # 创建目录 with open(path + file_name, 'wb+') as f: # 打开文件 for chunk in file.chunks(): # 读取上传文件 f.write(chunk) # 写入文件 return path + file_name # 返回文件路径
4、发送带有附件邮件的函数
为了让发送邮件的视图函数更清晰,单独将发送带有附件邮件的功能定义为函数。
示例代码:
def file_mail_send(subject, message, sender, addressees, file): email = EmailMultiAlternatives(subject, message, sender, addressees) # 创建邮件对象 file_path = upload_handler(file, str(file)) # 上传附件并获取文件路径 email.attach_file(file_path) # 附加文件到邮件对象 email.send() # 发送邮件
5、发送邮件的视图函数
发送邮件的视图函数中需要考虑以下内容:
- 表单提交是否使用“POST”方法提交,需要进行不同的处理;
- 邮件是否包含附件决定创建不同的表单对象,以及发送邮件的方法;
- 表单对象验证是否成功,需要进行不同的处理;
- 邮件发送是否成功,需要进行不同的处理;
- 邮件的数量(单封或多封)决定不同的发送邮件方法。
示例代码:
def send_email(request): if request.method == 'POST': # 如果表单为“POST”方法提交,则进行邮件发送。 if request.FILES: # 如果包含附件 email_form = FileMailForm(request.POST, request.FILES) # 创建包含附件的表单对象 file = request.FILES['file'] # 获取附件信息 else: email_form = TextEmailForm(request.POST) # 创建不包含附件的表单对象 file = None if email_form.is_valid(): # 如果验证有效 addressees = email_form.cleaned_data['addressees'].split(',') # 获取所有收件地址的列表 subject = email_form.cleaned_data['subject'] # 获取邮件标题 message = email_form.cleaned_data['message'] # 获取邮件内容 cc_myself = email_form.cleaned_data['cc_myself'] # 获取是否抄送发件人 if cc_myself: # 如果抄送发件人 addressees.append(settings.EMAIL_HOST_USER) # 添加发件人的邮件地址到收件地址列表 count = len(addressees) # 获取发件数量 email = [subject, message, settings.DEFAULT_FROM_EMAIL, addressees] # 保存所有发件信息到变量 try: if file: # 如果包含附件 file_mail_send(*email, file) # 调用发送带有附件邮件的函数 file_name = '(附件:%s)' % str(file) # 发送成功信息中的附件信息 else: # 如果不包含附件 if count > 1: # 如果有多个收件地址 send_mass_mail((email,)) # 调用适合发送多封邮件的方法 else: # 否则 send_mail(*email) # 调用适合发送单封邮件的方法 file_name = '' except: # raise # 编写代码时获取异常信息 return HttpResponse('发送失败!') # 如果发送邮件发生异常,则给出提示。 return render(request, 'thanks.html', {'count': count, 'to': addressees, 'file': file_name}) # 正常发送邮件后,页面显示发送邮件的相关信息。 else: # 如果验证失败,则进行提示。 return HttpResponse('验证失败!') else: # 如果表单不是“POST”方法提交,则回到撰写邮件的页面。 email_form = FileMailForm() return render(request, 'email.html', {'email_form': email_form})
在上方代码中,我们使用的“send_mail()”方法和“send_mass_mail()”方法实际上都可以发送单封或多封邮件,区别在于“send_mail()”发送多封邮件时,是一个一个的分开发送,而“send_mass_mail()”方法是多封邮件一起发送。
五、配置URL分发
最后,我们完成URL分发的配置,并启动开发服务器进行测试。
示例代码:(urls.py)
from django.urls import path from FormTest import views as form_views urlpatterns = [ path('email/', form_views.write_email), path('send_email/', form_views.send_email), ]
注意:邮件附件不能够为0字节的空文件,否则会在发送邮件时验证失败。
本节练习源代码:【点此下载】
转载请注明:魔力Python » Django2:Web项目开发入门笔记(19)