最新消息:欢迎光临 魔力 • Python!大家可以点开导航菜单中的【学习目录】,这个目录类似图书目录,更加方便学习!

Django2:Web项目开发入门笔记(19)

Django教程 小楼一夜听春语 5104浏览 0评论

这一篇教程,我们一起来学习使用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)

头像
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网站 (可选)

网友最新评论 (1)

  1. 头像
    100T种子交出来,我们还是好朋友
    东京烧烤大师李梅5年前 (2019-03-22)回复