<返回更多

如何使用 Django 发送电子邮件

2021-11-10    章大千
加入收藏

在本教程中,我们将介绍如何使用 Django 发送电子邮件。我们将介绍如何配置 Django SMTP 连接,如何为您的电子邮件提供商设置应用程序密码,以及如何通过 Django shell 发送电子邮件。我们还将研究如何为您的 Django 应用程序设置联系表单,这将允许您的客户与您联系。

大多数 Web 应用程序使用电子邮件来管理关键操作,例如重置密码、帐户激活、接收客户反馈、发送新闻通讯和营销活动。这些任务中的大多数都需要像SendGrid或Mailgun这样的专用服务。但是,如果您不希望您的网站获得大量访问者,您实际上可以通过您的个人电子邮件提供商完成很多工作。

使用您的个人电子邮件发送电子邮件是小型或测试项目的合理选择,因此我们将在此处采用这种方法以保持简单。但是,将您的个人电子邮件服务用于您的生产网站并不是一个好主意。您可以详细了解Gmail 发送限制,或参考您的电子邮件提供商的限制。

注意:本教程的完整代码可在GitHub上找到。

了解 SMTP

SMTP(或简单邮件传输协议)是一组用于确定电子邮件如何从发件人传输到收件人的规则。SMTP 服务器使用此协议来发送和中继外发电子邮件。(请注意,其他协议管理电子邮件的接收方式。)

SMTP 服务器始终具有唯一的地址和用于发送消息的特定端口,在大多数情况下为587。我们将看到在使用 Django 发送电子邮件时端口是如何相关的。

由于我们将使用 Gmail,因此我们将使用的地址是smtp.gmail.com,端口是 587。

现在让我们看看如何使用 Django 发送电子邮件。

创建 Django 项目

每个 Django 项目都应该有一个虚拟环境,因为我们不想弄乱项目依赖项。要创建一个,请运行以下命令:

Python/ target=_blank class=infotextkey>Python -m venv .venv

注意:如果您不熟悉虚拟环境,请务必查看我们的Python 虚拟环境指南。

上面的命令创建了一个名为 的虚拟环境.venv。要激活此虚拟环境,您可以使用以下命令:

source .venv/bin/activate

由于 Django 是第三方包,你必须用 pip 安装它:

pip install django

这将安装最新版本的 Django,您可以使用pip freeze.

要创建 Django 项目,请调用命令行实用程序django-admin:

django-admin startproject EmailProject

使用上面的命令,您正在创建一个名为 的 Django 项目EmailProject,但您可以使用任何您想要的名称创建该项目。

现在,进入项目目录并运行服务器:

cd EmailProject
python manage.py runserver

运行 Django 服务器后,在浏览器中访问http://localhost:8000。您将看到一个自动生成的页面,其中包含最新的 Django 发行说明。

如何使用 Django 发送电子邮件

 

修改设置

您需要在发送电子邮件之前修改设置文件,因此让我们使用以下命令找到该文件tree:

注意:为简单起见,我们将仅使用 UNIX(macOS 或 linux)系统命令。

tree

该tree命令输出目录的文件结构。在这种情况下,由于我们没有给它一个特定的目录路径,如果我们在项目的根文件夹中,我们将得到类似于以下的内容:

├── EmailProject
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

1 directory, 6 files

我们将在本教程中不断修改的文件是文件夹中的settings.pyEmailProject。

settings.py包含您需要的所有项目配置,并允许您设置自定义变量。正如 Django 文档所说,“设置文件只是一个带有模块级变量的 Python 模块”。

让我们看一下使用 Django 发送电子邮件所需的设置。打开EmailProject/settings.py文件并将以下设置粘贴到文件底部:

# EmailProject/settings.py

# Bottom of the file
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = ''
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSword = ''

让我们通过分析这些设置中的每一个来分解上面的代码。

电子邮件后端

该EMAIL_BACKEND设置声明后端我们的Django项目将使用与SMTP服务器连接。

此变量指向smtp.EmailBackend接收发送电子邮件所需的所有参数的类。我强烈建议您直接在Django 源代码上查看类构造函数。你会惊讶于这段代码的可读性。

注意:虽然这个类是默认的EMAIL_BACKEND,但在 Django 设置中显式被认为是一个好习惯。

所有其他电子邮件设置将基于此EmailBackend 类的构造函数。

电子邮件主机

该EMAIL_HOST设置指的是您将使用的 SMTP 服务器域。这取决于您的电子邮件提供商。下表列出了与三个常见提供商对应的 SMTP 服务器主机:

电子邮件提供商

SMTP 服务器主机

Gmail

smtp.gmail.com

Outlook/Hotmail

smtp-mail.outlook.com

雅虎

smtp.mail.yahoo.com

我们暂时将此设置留空,因为我们稍后将使用.env文件来避免硬编码敏感密钥或每个站点的配置。您永远不应该将凭据直接设置到代码中。

我们将使用Django Environ来解决这个问题。

电子邮件端口

该EMAIL_PORT设置必须设置为 ,587因为它是大多数 SMTP 服务器的默认端口。对于个人电子邮件提供商而言,情况仍然如此。

此端口与 TLS 加密一起使用,以确保电子邮件发送的安全性。

电子邮件使用 TLS

传输层安全(TLS) 是一种跨 Web 使用的安全协议,用于加密 Web 应用程序 (Django) 和服务器 (SMTP 服务器) 之间的通信。

最初,我们将EMAIL_USE_TLS变量设置为True。这意味着 Django 将使用传输层安全连接到 SMTP 服务器并发送电子邮件。(对于个人电子邮件提供商,这是强制性的。)

电子邮件主机用户

该EMAIL_HOST_USER设置是您的个人电子邮件地址。现在将其留空,因为我们将使用它django-environ来设置所有这些凭据。

电子邮件主机密码

该EMAIL_HOST_PASSWORD设置是您将从您的电子邮件帐户中获得的应用密码 - 我们将在本节之后立即执行此过程。

同样的故事:将此设置留空,因为我们稍后将使用环境变量。

在 Gmail 中设置应用密码

要使用该EMAIL_HOST_PASSWORD设置,您需要激活安全性较低的应用访问权限,并从您的个人电子邮件地址获得应用密码。

如果您不激活安全性较低的应用程序访问权限,您可能会得到一个SMTPAuthenticationError,因为 Django 无法遵守 google 安全协议。

您可以选择使用普通密码,但这比使用应用密码风险更大。我的建议是创建一个新的 Gmail 帐户或使用“测试”电子邮件地址。

考虑到这一点,您可以通过以下步骤获取Gmail 应用密码。请注意,如果您使用的是现有帐户并启用了两步验证,则可以跳过第 2 步和第 3 步:

  1. 创建或登录 Gmail 帐户
  2. 转到myaccount.google.com/lesssecureApps并打开安全性较低的应用程序选项。
  3. 启用双因素身份验证,因为需要获取应用密码。
  4. 现在您已启用双因素身份验证,是时候获取应用密码了。为此,您可以转到Google 帐户的安全部分,向下滚动到登录 Google 部分,然后点击应用密码

在被重定向到应用程序密码页面之前,您需要重新提示您的密码(帐户密码)。

进入后,单击select app,您将为该应用程序密码选择一个自定义名称 - 例如“Django Send Email” - 然后单击GENERATE

如何使用 Django 发送电子邮件

 

将显示一个新窗口,其中包含 16 个字符的密码。复制它,因为我们需要它来配置我们的 Django 项目。

如何使用 Django 发送电子邮件

 

如果您使用其他电子邮件提供商,请务必阅读以下指南:

  • 雅虎应用密码
  • Outlook 或 Hotmail 应用程序密码

使用 Django Environ 隐藏敏感键

即使您只是在开发中发送电子邮件,也不应该将密码直接写入源代码。当使用版本控制系统和 GitHub 来托管您的项目时,这一点变得更加重要。您不希望人们访问您的数据。

让我们看看如何通过使用Django-environ来防止这种情况发生。

使用以下命令.env在EmailProject目录(settings.py文件所在的位置)内创建一个文件:

cd EmailProject/
ls

settings.py # The settings file must be here

touch .env

现在,打开该.env文件并输入以下键值对:

EMAIL_HOST=smtp.gmail.com
EMAIL_HOST_USER=YourEmail@address
EMAIL_HOST_PASSWORD=YourAppPassword
RECIPIENT_ADDRESS=TheRecieverOfTheMails

分解此文件的内容:

  • EMAIL_HOST:您的电子邮件提供商 SMTP 服务器地址。请参阅上面的电子邮件主机表以获取快速指导。在本例中,我使用的smtp.gmail.com是 Gmail SMTP 地址。
  • EMAIL_HOST_USER: 您的电子邮件地址。
  • EMAIL_HOST_PASSWORD:您刚刚生成的应用密码。请记住,它不包含任何空格。
  • RECIPIENT_ADDRESS:您将收到邮件的电子邮件地址。这是我们稍后将创建的自定义设置,用于将所有电子邮件发送给同一收件人。

要使用这些环境变量,我们需要安装Django-environ:

pip install django-environ

注意:确保您的虚拟环境已激活。

现在,打开settings.py位于EmailProject目录中的 并使用以下代码:

# EmailProject/settings.py
# This should be at the start of the file
import environ

env = environ.Env()
environ.Env.read_env()

# Previous settings ...
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')

# Custom setting. To email
RECIPIENT_ADDRESS = env('RECIPIENT_ADDRESS')

首先,我们在environ设置文件的顶部导入包。请记住,所有导入都应在开头。

然后我们创建一个env变量,该变量将包含.env.

该env('KEY')语句意味着我们正在查找该键的值。确保.env在继续之前设置了文件,因为如果ImproperlyConfigured未设置某些环境变量,您将收到 Django错误。

请注意,这RECIPIENT_ADDRESS是一个自定义设置,我们将使用它来将电子邮件发送到我们可以访问的地址。

如果您使用 Git 和 GitHub .env,请不要忘记在.gitignore中包含该文件。您只需打开它并添加以下行即可完成此操作:

.env

1. 使用 Django Shell 发送电子邮件

最后,我们进入了文章的精彩部分!是时候向 Django 发送您的第一封电子邮件了。

打开终端,激活虚拟环境,然后运行:

python manage.py shell

这将创建一个 shell,其中包含已为我们配置的所有 Django 设置。在那个全新的 shell 中,粘贴以下代码:

>>> from django.core.mail import send_mail
>>> from django.conf import settings
>>> send_mail(
...     subject='A cool subject',
...     message='A stunning message',
...     from_email=settings.EMAIL_HOST_USER,
...     recipient_list=[settings.RECIPIENT_ADDRESS])
1

我们也可以在不指定参数的情况下制作单行:

>>> send_mail('A cool subject', 'A stunning message', settings.EMAIL_HOST_USER, [settings.RECIPIENT_ADDRESS])
1

让我们分解上面的代码:

  • 我们导入 Django send_mail函数。
  • 然后我们导入settings包含所有全局设置和每个站点设置(settings.py文件内的设置)的对象。
  • 最后,我们将所有需要的参数传递给send_mail函数。此函数返回发送的电子邮件数量,在本例中为1

请注意我们如何使用settings对象来获取from_email(您用来发送电子邮件的电子邮件)和recipient_list(RECIPIENT_ADDRESS我们在 中定义的自定义设置.env)。

现在,如果我检查我的收件箱——当我将RECIPIENT_ADDRESS环境变量设置为我的电子邮件地址时——我将收到 Django 发送的消息。

如何使用 Django 发送电子邮件

 

2. 使用 Django 构建自动联系表单

在本节中,我们将使用 Django 表单和内置send_mail函数构建一个自动联系表单。此外,我们将send()在联系表单中创建一个自定义函数 ,以便在视图中更容易实现它。

让我们从创建联系人应用程序开始。进入项目根目录——所在manage.py的位置——并运行:

python manage.py startapp contact

然后,将其安装在文件INSTALLED_APPS内的变量中EmailProject/settings.py:

# EmailProject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    ...

    # Custom
    'contact',
]

在推进contact应用程序之前,让我们配置文件的urlpatterns内部EmailProject/urls.py。为此,请导入该django.urls.include函数并在整个项目中包含联系人 URL。别担心;我们稍后将配置联系人 URL:

# EmailProject/urls.py

from django.contrib import admin
from django.urls import path, include # New import

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('contact.urls')) # Include Contact URLs
]

联系表

进入contact应用程序文件夹并创建一个forms.py文件。在forms.py文件中定义所有表单是一种很好的做法,但这不是强制性的。这就是 Django 默认不包含这个文件的原因。

您可以使用以下命令创建表单文件:

cd ../contact/
# You were inside the EmailProject folder
touch forms.py

打开您刚刚创建的文件并进行以下导入:

# contact/forms.py
from django import forms
from django.conf import settings
from django.core.mail import send_mail

Django表单模块为我们提供了创建联系表单所需的所有类和字段。我们再次导入settings对象和send_mail发送电子邮件的函数。

我们的联系表单将包含多个字段并使用两种自定义方法:get_info(),用于格式化用户提供的信息,以及send(),将发送消息。

让我们看看这在代码中的实现:

# contact/forms.py
class ContactForm(forms.Form):

    name = forms.CharField(max_length=120)
    email = forms.EmailField()
    inquiry = forms.CharField(max_length=70)
    message = forms.CharField(widget=forms.Textarea)

    def get_info(self):
        """
        Method that returns formatted information
        :return: subject, msg
        """
        # Cleaned data
        cl_data = super().clean()

        name = cl_data.get('name').strip()
        from_email = cl_data.get('email')
        subject = cl_data.get('inquiry')

        msg = f'{name} with email {from_email} said:'
        msg += f'n"{subject}"nn'
        msg += cl_data.get('message')

        return subject, msg

    def send(self):

        subject, msg = self.get_info()

        send_mail(
            subject=subject,
            message=msg,
            from_email=settings.EMAIL_HOST_USER,
            recipient_list=[settings.RECIPIENT_ADDRESS]
        )

这是一个巨大的类,所以让我们分解我们在每个部分中所做的事情。首先,我们定义了发送消息所需的四个字段:

  • name和enquiry是表示联系消息的名称和原因的CharFields。
  • email是一个EmailField,代表试图与您联系的人的电子邮件。考虑到电子邮件不会由用户的电子邮件地址发送,而是由您在 Django 项目中设置的发送电子邮件的电子邮件地址发送。
  • message是另一个CharField例外,我们使用的是Textarea小部件。这意味着,当显示表单时,它将呈现一个<textarea>标签而不是一个简单的<input>.

进入自定义方法,我们只使用该get_info方法来格式化用户提供的信息并返回两个变量:subject,它只是inquiry字段,以及message,它将是 Django 发送的实际消息。

另一方面,该send()方法仅从函数中获取格式化信息get_info并发送消息send_mail。

尽管本节非常大,但您将看到我们如何通过将所有发送逻辑实现到ContactForm自身来简化联系人视图。

联系人视图

打开contact/views.py文件并添加以下导入:

# contact/views.py
from django.views.generic import FormView, TemplateView
from .forms import ContactForm
from django.urls import reverse_lazy

如您所见,我们将使用Django 通用视图,这在执行简单任务时为我们节省了大量时间——例如,在FormView使用TemplateView.

此外,我们正在导入ContactForm我们在上一节中构建的 以及在使用基于类的视图时使用的reverse_lazy函数。

继续查看视图,让我们编写ContactView:

# contact/views.py

class ContactView(FormView):
    template_name = 'contact/contact.html'
    form_class = ContactForm
    success_url = reverse_lazy('contact:success')

    def form_valid(self, form):
        # Calls the custom send method
        form.send()
        return super().form_valid(form)

如您所见,我们正在使用我们创建的构建一个简单的FormViewContactForm。我们也在设置template_name和success_url。我们稍后将编写 HTML 模板并设置 URL。

该形式有效的方法,让我们用发送电子邮件ContactForm.send()只有在形式的所有字段都是有效的方法。这意味着如果用户输入无效的输入——例如未格式化的电子邮件地址——消息将不会被发送。

form_valid在基于函数的视图中,上述方法实现将等效于以下内容:

# Previous function based contact_view ...

if request.method == 'POST':
    form = ContactForm(request.POST)
    if form.is_valid():
        form.send()
        return redirect('contact:success')
else:
    form = ContactForm())

在本节结束时,我们将编写一个ContactSucessView,它将向用户显示一条成功消息。由于我们已经导入了TemplateView类,我们只需要继承它并定义template_name属性:

# contact/views.py
class ContactSuccessView(TemplateView):
    template_name = 'contact/success.html'

如果您有任何疑问,可以查看GitHub 存储库views.py上的文件。

联系网址

是时候创建contact应用程序的 URL 模式了。由于 Djangourls.py默认不给我们文件,我们需要使用以下命令创建它(确保在contactapp 文件夹中):

pwd
# /path/to/project/EmailProject/contact
touch urls.py

打开该文件并设置app_name和urlpatterns变量:

from django.urls import path
from .views import ContactView, ContactSuccessView

app_name = 'contact'

urlpatterns = [
    path('', ContactView.as_view(), name="contact"),
    path('success/', ContactSuccessView.as_view(), name="success"),
]

我们使用路径将路由及其对应视图包含到应用程序的 URL 配置中。当我们将app_name变量设置为 时'contact',这意味着应用程序的 URL命名空间将如下所示:

contact:name_of_path
# For ContactView
contact:contact
# For ContactSuccessView
contact:success

注意:命名空间是我们在 Django 模板和视图中动态调用的 URL。

您可以在官方文档中了解有关 Django URL 调度程序的更多信息。

编写模板

Django 模板是动态显示数据的首选方式,使用HTML和 Django 模板语言给我们的特殊标签。

对于这个特定的应用程序,我们将使用三个模板:

  • base.html: 所有其他模板都将从它继承。它将包含所有模板必须具有的所有 HTML 框架,以及指向 Bootstrap 的链接。
  • contact.html:显示联系表格。
  • success.html: 显示成功消息。

让我们从创建联系人的应用程序模板结构开始(确保您在联系人应用程序文件夹中):

mkdir -p templates/contact/
cd templates/contact
touch base.html contact.html success.html

上面的命令创建了可重用 Django 应用程序的典型模板结构appname/templates/appname——以及我之前提到的树模板文件。

应用程序文件结构现在应该如下所示:

.
├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── templates
│   └── contact
│       ├── base.html
│       ├── contact.html
│       └── success.html
├── tests.py
├── urls.py
└── views.py

让我们进入base.html模板的内容:

<!-- contact/templates/contact/base.html -->

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Django Email Send</title>
    <link href="https://cdn.jsdelivr.NET/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet"
      integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
  </head>

  <body>
    {% block body %}

    {% endblock %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous">
    </script>
  </body>

</html>

如您所见,它是包含Bootstrap 5链接的 HTML 文件的简单框架。这允许我们在不使用 CSS 文件的情况下对我们的联系人应用程序进行风格化。

该{% block name-of-block %}标签允许我们设置一个“子模板”将使用的占位符。使用此标记使模板继承成为一项简单的任务。

在进入表单之前,您需要安装Django 脆皮表单包,它允许我们轻松地对它们进行样式化:

pip install django-crispy-forms

再一次,crispy_forms是一个 Django 应用程序,我们需要将它包含在INSTALLED_APPS列表中:

# config/settings.py

INSTALLED_APPS = [
    ...

    # 3rd party apps
    'crispy_forms',

    # Custom apps
    'contact',
]

# Indicates the frontend framework django crispy forms use
CRISPY_TEMPLATE_PACK = 'bootstrap4'

我们使用 Bootstrap 4 的模板包,因为 Bootstrap 表单类在第 4 版和第 5 版之间兼容(在撰写本文时)。

现在,让我们处理contact.html模板:

<!-- contact/templates/contact/contact.html -->

{% extends 'contact/base.html' %}
{% load crispy_forms_tags %}

{% block body %}
<div class="mx-auto my-4 text-center">
    <h1>Contact Us</h1>
</div>
<div class="container">
    <form action="" method="post">
        {% csrf_token %}
        {{ form | crispy }}
    <button class="btn btn-success my-3" type="submit">Send message</button>
    </form>
</div>
{% endblock %}

请注意我们如何扩展基本模板并使用块占位符。这就是 Django 模板语言如此高效的原因,因为它让我们节省了大量的 HTML 复制和粘贴。

谈到表单,我们使用了方法"post",这意味着我们ContactView将处理用户提供的数据,如果表单有效,我们将发送电子邮件。

的{% csrf_token %}是,由于安全原因,所有形式的强制性。Django 的文档有一个关于CSRF 令牌的专用页面以及在处理表单时使用它们的原因。

我们将使用crispy模板标签渲染表单,这就是为什么我们用{% load crispy_forms_tags %}.

最后,让我们编写success.html模板:

{% extends 'contact/base.html' %}

{% block body %}
<div class="mx-auto my-4 text-center">
    <h1 class="fw-bolder text-success">We sent your message</h1>
    <p class="my-5">You can send another in the <a href="{% url 'contact:contact' %}">contact page</a></p>
</div>
{% endblock %}

如您所见,这是一个简单的成功公告,其中包含指向联系表单的链接,以防用户想要发送另一条消息。

让我们再次运行服务器并访问http://localhost:8000(确保您已.venv激活并且您在项目根文件夹中):

python manage.py runserver

下图显示了最终联系表格的样子。

如何使用 Django 发送电子邮件

 

这是成功消息的图像。

如何使用 Django 发送电子邮件

 

这是收件箱中电子邮件的图像。

如何使用 Django 发送电子邮件

 

包起来

恭喜!您已经学习了如何使用 Django 发送电子邮件以及如何构建 Django 联系表单。

使用 Django 发送电子邮件的方法有很多种。在本教程中,您已使用个人电子邮件地址完成此操作,但我希望您探索其他工具并将它们集成到您的项目中。

在本教程中,我们介绍了以下内容:

  • 如何设置 Django 设置以提供电子邮件
  • 小项目中如何使用个人邮箱发送邮件
  • 如何.env在 Django 项目中使用文件来使用敏感数据
  • 如何构建自动联系表单
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>