这一篇教程,我们一起来学习使用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字节的空文件,否则会在发送邮件时验证失败。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试



