Django Email and Contact Form Tutorial

Let’s build a simple contact form that sends email from a Django 5.0 website. We can take advantage of Django’s built-in email support to make this relatively painless by first outputting emails to our terminal and then sending them in production using an email service like SendGrid.

Initial setup

The first step is to create a dedicated directory for our code. A convenient location is the Desktop. From the command line, execute the following commands to navigate to the Desktop and create a new contact folder with either Windows or macOS.

# Windows
$ cd onedrive\desktop\code
$ mkdir contact
$ cd contact
# macOS
$ cd ~/desktop/code
$ mkdir contact
$ cd contact
# Windows
$ cd onedrive\desktop\code
$ mkdir contact
$ cd contact

# macOS
$ cd ~/desktop/code
$ mkdir contact
$ cd contact
# Windows $ cd onedrive\desktop\code $ mkdir contact $ cd contact # macOS $ cd ~/desktop/code $ mkdir contact $ cd contact

Enter fullscreen mode Exit fullscreen mode

Now we can create and activate a virtual environment called .venv. Then, install the latest version of Django.

# Windows
$ python -m venv .venv
$ .venv\Scripts\Activate.ps1
(.venv) $ python -m pip install django~=5.0
# macOS
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $ python3 -m pip install django~=5.0
# Windows
$ python -m venv .venv
$ .venv\Scripts\Activate.ps1
(.venv) $ python -m pip install django~=5.0

# macOS
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $ python3 -m pip install django~=5.0
# Windows $ python -m venv .venv $ .venv\Scripts\Activate.ps1 (.venv) $ python -m pip install django~=5.0 # macOS $ python3 -m venv .venv $ source .venv/bin/activate (.venv) $ python3 -m pip install django~=5.0

Enter fullscreen mode Exit fullscreen mode

Next, let’s create a new Django project called django_project and within it an app called sendemail:

(.venv) $ django-admin startproject django_project .
(.venv) $ python manage.py startapp sendemail
(.venv) $ django-admin startproject django_project .
(.venv) $ python manage.py startapp sendemail
(.venv) $ django-admin startproject django_project . (.venv) $ python manage.py startapp sendemail

Enter fullscreen mode Exit fullscreen mode

To ensure everything is installed correctly, let’s migrate the initial database and execute runserver to start the local web server.

(.venv) $ python manage.py migrate
(.venv) $ python manage.py runserver
(.venv) $ python manage.py migrate
(.venv) $ python manage.py runserver
(.venv) $ python manage.py migrate (.venv) $ python manage.py runserver

Enter fullscreen mode Exit fullscreen mode

If you open you browser to 127.0.0.1:8000 you should see the following screen:

Update settings.py

We’ve created a new app, so we must explicitly add it to our Django project. Within your settings.py file, under INSTALLED_APPS, add sendemail at the bottom.

<span># django_project/settings.py </span><span>INSTALLED_APPS</span> <span>=</span> <span>[</span>
<span>"</span><span>django.contrib.admin</span><span>"</span><span>,</span>
<span>"</span><span>django.contrib.auth</span><span>"</span><span>,</span>
<span>"</span><span>django.contrib.contenttypes</span><span>"</span><span>,</span>
<span>"</span><span>django.contrib.sessions</span><span>"</span><span>,</span>
<span>"</span><span>django.contrib.messages</span><span>"</span><span>,</span>
<span>"</span><span>django.contrib.staticfiles</span><span>"</span><span>,</span>
<span>"</span><span>sendemail</span><span>"</span><span>,</span> <span># new </span><span>]</span>
<span># django_project/settings.py </span><span>INSTALLED_APPS</span> <span>=</span> <span>[</span>
    <span>"</span><span>django.contrib.admin</span><span>"</span><span>,</span>
    <span>"</span><span>django.contrib.auth</span><span>"</span><span>,</span>
    <span>"</span><span>django.contrib.contenttypes</span><span>"</span><span>,</span>
    <span>"</span><span>django.contrib.sessions</span><span>"</span><span>,</span>
    <span>"</span><span>django.contrib.messages</span><span>"</span><span>,</span>
    <span>"</span><span>django.contrib.staticfiles</span><span>"</span><span>,</span>
    <span>"</span><span>sendemail</span><span>"</span><span>,</span>  <span># new </span><span>]</span>
# django_project/settings.py INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "sendemail", # new ]

Enter fullscreen mode Exit fullscreen mode

The send_email function is what sends our emails, and its required parameters include subject, message, from_email, and recipient_list.

At the bottom of the same settings.py file, specify the EMAIL_BACKEND we’ll use, which should be console for local development. We also need to add a DEFAULT_FROM_EMAIL. And since send_email requires a recipient_list, we will add a new setting, NOTIFY_EMAIL for that purpose.

<span># django_project/settings.py </span><span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.console.EmailBackend</span><span>"</span>
<span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span># django_project/settings.py </span><span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.console.EmailBackend</span><span>"</span>
<span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
# django_project/settings.py EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" DEFAULT_FROM_EMAIL = "will@learndjango.com" NOTIFY_EMAIL = "will@learndjango.com"

Enter fullscreen mode Exit fullscreen mode

Update urls.py

Since we’ve added an app to our Django project, we need to update the root django_project/urls.py file, importing include at the top and listing a new urlpattern for the app at the empty string, "":

<span># django_project/urls.py </span><span>from</span> <span>django.contrib</span> <span>import</span> <span>admin</span>
<span>from</span> <span>django.urls</span> <span>import</span> <span>path</span><span>,</span> <span>include</span> <span># new </span>
<span>urlpatterns</span> <span>=</span> <span>[</span>
<span>path</span><span>(</span><span>"</span><span>admin/</span><span>"</span><span>,</span> <span>admin</span><span>.</span><span>site</span><span>.</span><span>urls</span><span>),</span>
<span>path</span><span>(</span><span>""</span><span>,</span> <span>include</span><span>(</span><span>"</span><span>sendemail.urls</span><span>"</span><span>)),</span> <span># new </span><span>]</span>
<span># django_project/urls.py </span><span>from</span> <span>django.contrib</span> <span>import</span> <span>admin</span>
<span>from</span> <span>django.urls</span> <span>import</span> <span>path</span><span>,</span> <span>include</span>  <span># new </span>
<span>urlpatterns</span> <span>=</span> <span>[</span>
    <span>path</span><span>(</span><span>"</span><span>admin/</span><span>"</span><span>,</span> <span>admin</span><span>.</span><span>site</span><span>.</span><span>urls</span><span>),</span>
    <span>path</span><span>(</span><span>""</span><span>,</span> <span>include</span><span>(</span><span>"</span><span>sendemail.urls</span><span>"</span><span>)),</span>  <span># new </span><span>]</span>
# django_project/urls.py from django.contrib import admin from django.urls import path, include # new urlpatterns = [ path("admin/", admin.site.urls), path("", include("sendemail.urls")), # new ]

Enter fullscreen mode Exit fullscreen mode

Next, create a new file called sendemail/urls.py and add the following code so that the main contact form is at contact/ and a successful submission redirects to success/. We have yet to create the corresponding views: SuccessView and ContactView.

<span># sendemail/urls.py </span><span>from</span> <span>django.urls</span> <span>import</span> <span>path</span>
<span>from</span> <span>.views</span> <span>import</span> <span>SuccessView</span><span>,</span> <span>ContactView</span>
<span>urlpatterns</span> <span>=</span> <span>[</span>
<span>path</span><span>(</span><span>"</span><span>contact/</span><span>"</span><span>,</span> <span>ContactView</span><span>.</span><span>as_view</span><span>(),</span> <span>name</span><span>=</span><span>"</span><span>contact</span><span>"</span><span>),</span>
<span>path</span><span>(</span><span>"</span><span>success/</span><span>"</span><span>,</span> <span>SuccessView</span><span>.</span><span>as_view</span><span>(),</span> <span>name</span><span>=</span><span>"</span><span>success</span><span>"</span><span>),</span>
<span>]</span>
<span># sendemail/urls.py </span><span>from</span> <span>django.urls</span> <span>import</span> <span>path</span>

<span>from</span> <span>.views</span> <span>import</span> <span>SuccessView</span><span>,</span> <span>ContactView</span>

<span>urlpatterns</span> <span>=</span> <span>[</span>
    <span>path</span><span>(</span><span>"</span><span>contact/</span><span>"</span><span>,</span> <span>ContactView</span><span>.</span><span>as_view</span><span>(),</span> <span>name</span><span>=</span><span>"</span><span>contact</span><span>"</span><span>),</span>
    <span>path</span><span>(</span><span>"</span><span>success/</span><span>"</span><span>,</span> <span>SuccessView</span><span>.</span><span>as_view</span><span>(),</span> <span>name</span><span>=</span><span>"</span><span>success</span><span>"</span><span>),</span>
<span>]</span>
# sendemail/urls.py from django.urls import path from .views import SuccessView, ContactView urlpatterns = [ path("contact/", ContactView.as_view(), name="contact"), path("success/", SuccessView.as_view(), name="success"), ]

Enter fullscreen mode Exit fullscreen mode

Create forms.py

Still, within our sendemail app, create a new file named sendemail/forms.py. It will have a ContactForm class containing the fields in our contact form: from_email, subject, and message.

<span># sendemail/forms.py </span><span>from</span> <span>django</span> <span>import</span> <span>forms</span>
<span>class</span> <span>ContactForm</span><span>(</span><span>forms</span><span>.</span><span>Form</span><span>):</span>
<span>email</span> <span>=</span> <span>forms</span><span>.</span><span>EmailField</span><span>(</span>
<span>widget</span><span>=</span><span>forms</span><span>.</span><span>TextInput</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Your e-mail</span><span>"</span><span>})</span>
<span>)</span>
<span>subject</span> <span>=</span> <span>forms</span><span>.</span><span>CharField</span><span>(</span><span>widget</span><span>=</span><span>forms</span><span>.</span><span>TextInput</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Subject</span><span>"</span><span>}))</span>
<span>message</span> <span>=</span> <span>forms</span><span>.</span><span>CharField</span><span>(</span>
<span>widget</span><span>=</span><span>forms</span><span>.</span><span>Textarea</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Your message</span><span>"</span><span>})</span>
<span>)</span>
<span># sendemail/forms.py </span><span>from</span> <span>django</span> <span>import</span> <span>forms</span>


<span>class</span> <span>ContactForm</span><span>(</span><span>forms</span><span>.</span><span>Form</span><span>):</span>
    <span>email</span> <span>=</span> <span>forms</span><span>.</span><span>EmailField</span><span>(</span>
        <span>widget</span><span>=</span><span>forms</span><span>.</span><span>TextInput</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Your e-mail</span><span>"</span><span>})</span>
    <span>)</span>
    <span>subject</span> <span>=</span> <span>forms</span><span>.</span><span>CharField</span><span>(</span><span>widget</span><span>=</span><span>forms</span><span>.</span><span>TextInput</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Subject</span><span>"</span><span>}))</span>
    <span>message</span> <span>=</span> <span>forms</span><span>.</span><span>CharField</span><span>(</span>
        <span>widget</span><span>=</span><span>forms</span><span>.</span><span>Textarea</span><span>(</span><span>attrs</span><span>=</span><span>{</span><span>"</span><span>placeholder</span><span>"</span><span>:</span> <span>"</span><span>Your message</span><span>"</span><span>})</span>
    <span>)</span>
# sendemail/forms.py from django import forms class ContactForm(forms.Form): email = forms.EmailField( widget=forms.TextInput(attrs={"placeholder": "Your e-mail"}) ) subject = forms.CharField(widget=forms.TextInput(attrs={"placeholder": "Subject"})) message = forms.CharField( widget=forms.Textarea(attrs={"placeholder": "Your message"}) )

Enter fullscreen mode Exit fullscreen mode

We’re using Django’s built-in Forms API to create three fields and add placeholder text.

Create views.py

Now, let’s create the view that will do the bulk of the work for our contact form. Update the existing sendemail/views.py file, and we’ll review the code below.

<span># sendemail/views.py </span><span>from</span> <span>django.conf</span> <span>import</span> <span>settings</span>
<span>from</span> <span>django.core.mail</span> <span>import</span> <span>send_mail</span>
<span>from</span> <span>django.shortcuts</span> <span>import</span> <span>reverse</span>
<span>from</span> <span>django.views.generic</span> <span>import</span> <span>TemplateView</span><span>,</span> <span>FormView</span>
<span>from</span> <span>.forms</span> <span>import</span> <span>ContactForm</span>
<span>class</span> <span>SuccessView</span><span>(</span><span>TemplateView</span><span>):</span>
<span>template_name</span> <span>=</span> <span>"</span><span>success.html</span><span>"</span>
<span>class</span> <span>ContactView</span><span>(</span><span>FormView</span><span>):</span>
<span>form_class</span> <span>=</span> <span>ContactForm</span>
<span>template_name</span> <span>=</span> <span>"</span><span>contact.html</span><span>"</span>
<span>def</span> <span>get_success_url</span><span>(</span><span>self</span><span>):</span>
<span>return</span> <span>reverse</span><span>(</span><span>"</span><span>contact</span><span>"</span><span>)</span>
<span>def</span> <span>form_valid</span><span>(</span><span>self</span><span>,</span> <span>form</span><span>):</span>
<span>email</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>email</span><span>"</span><span>)</span>
<span>subject</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>subject</span><span>"</span><span>)</span>
<span>message</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>message</span><span>"</span><span>)</span>
<span>full_message</span> <span>=</span> <span>f</span><span>"""</span><span> Received message below from </span><span>{</span><span>email</span><span>}</span><span>, </span><span>{</span><span>subject</span><span>}</span><span> ________________________ </span><span>{</span><span>message</span><span>}</span><span> </span><span>"""</span>
<span>send_mail</span><span>(</span>
<span>subject</span><span>=</span><span>"</span><span>Received contact form submission</span><span>"</span><span>,</span>
<span>message</span><span>=</span><span>full_message</span><span>,</span>
<span>from_email</span><span>=</span><span>settings</span><span>.</span><span>DEFAULT_FROM_EMAIL</span><span>,</span>
<span>recipient_list</span><span>=</span><span>[</span><span>settings</span><span>.</span><span>NOTIFY_EMAIL</span><span>],</span>
<span>)</span>
<span>return</span> <span>super</span><span>(</span><span>ContactView</span><span>,</span> <span>self</span><span>).</span><span>form_valid</span><span>(</span><span>form</span><span>)</span>
<span># sendemail/views.py </span><span>from</span> <span>django.conf</span> <span>import</span> <span>settings</span>
<span>from</span> <span>django.core.mail</span> <span>import</span> <span>send_mail</span>
<span>from</span> <span>django.shortcuts</span> <span>import</span> <span>reverse</span>
<span>from</span> <span>django.views.generic</span> <span>import</span> <span>TemplateView</span><span>,</span> <span>FormView</span>

<span>from</span> <span>.forms</span> <span>import</span> <span>ContactForm</span>


<span>class</span> <span>SuccessView</span><span>(</span><span>TemplateView</span><span>):</span>
    <span>template_name</span> <span>=</span> <span>"</span><span>success.html</span><span>"</span>


<span>class</span> <span>ContactView</span><span>(</span><span>FormView</span><span>):</span>
    <span>form_class</span> <span>=</span> <span>ContactForm</span>
    <span>template_name</span> <span>=</span> <span>"</span><span>contact.html</span><span>"</span>

    <span>def</span> <span>get_success_url</span><span>(</span><span>self</span><span>):</span>
        <span>return</span> <span>reverse</span><span>(</span><span>"</span><span>contact</span><span>"</span><span>)</span>

    <span>def</span> <span>form_valid</span><span>(</span><span>self</span><span>,</span> <span>form</span><span>):</span>
        <span>email</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>email</span><span>"</span><span>)</span>
        <span>subject</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>subject</span><span>"</span><span>)</span>
        <span>message</span> <span>=</span> <span>form</span><span>.</span><span>cleaned_data</span><span>.</span><span>get</span><span>(</span><span>"</span><span>message</span><span>"</span><span>)</span>

        <span>full_message</span> <span>=</span> <span>f</span><span>"""</span><span> Received message below from </span><span>{</span><span>email</span><span>}</span><span>, </span><span>{</span><span>subject</span><span>}</span><span> ________________________ </span><span>{</span><span>message</span><span>}</span><span> </span><span>"""</span>
        <span>send_mail</span><span>(</span>
            <span>subject</span><span>=</span><span>"</span><span>Received contact form submission</span><span>"</span><span>,</span>
            <span>message</span><span>=</span><span>full_message</span><span>,</span>
            <span>from_email</span><span>=</span><span>settings</span><span>.</span><span>DEFAULT_FROM_EMAIL</span><span>,</span>
            <span>recipient_list</span><span>=</span><span>[</span><span>settings</span><span>.</span><span>NOTIFY_EMAIL</span><span>],</span>
        <span>)</span>
        <span>return</span> <span>super</span><span>(</span><span>ContactView</span><span>,</span> <span>self</span><span>).</span><span>form_valid</span><span>(</span><span>form</span><span>)</span>
# sendemail/views.py from django.conf import settings from django.core.mail import send_mail from django.shortcuts import reverse from django.views.generic import TemplateView, FormView from .forms import ContactForm class SuccessView(TemplateView): template_name = "success.html" class ContactView(FormView): form_class = ContactForm template_name = "contact.html" def get_success_url(self): return reverse("contact") def form_valid(self, form): email = form.cleaned_data.get("email") subject = form.cleaned_data.get("subject") message = form.cleaned_data.get("message") full_message = f""" Received message below from {email}, {subject} ________________________ {message} """ send_mail( subject="Received contact form submission", message=full_message, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[settings.NOTIFY_EMAIL], ) return super(ContactView, self).form_valid(form)

Enter fullscreen mode Exit fullscreen mode

The first thing we do is create a SuccessView that displays a template, success.html. The ContactView is where the real work happens: it extends Django’s FormView and refers to the corresponding form, ContactForm, and template that should be used, contact.html. Next, we have to set get_success_url, which takes the URL name of our success form from the sendemail/urls.py file.

And then we come to form_valid, meaning if the form is successfully submitted, what should happen next? Django provides excellent support for form and field validation, so the main task for us, as developers, is to ensure each field is cleaned, layout the format of the message we want to receive, and then use send_email to send the subject, message, from email, and recipient list. It is worth reading the Django docs on forms and validation for a fuller picture of all that happens behind the scenes, but suffice it to say that forms are an incredibly deep and difficult area of web development that Django handles elegantly for us.

Create templates

The final step is to create the templates for our contact and success pages. I like to make a project-level templates folder and put all of my templates in there. So, create a new directory called templates in the project directory.

(.venv) $ mkdir templates
(.venv) $ mkdir templates
(.venv) $ mkdir templates

Enter fullscreen mode Exit fullscreen mode

Next, update our settings.py file to tell Django to look in this directory for templates. Update the DIRS settings within TEMPLATES with a one-line change.

<span># django_project/settings.py </span><span>TEMPLATES</span> <span>=</span> <span>[</span>
<span>{</span>
<span>...</span>
<span>"</span><span>DIRS</span><span>"</span><span>:</span> <span>[</span><span>BASE_DIR</span> <span>/</span> <span>"</span><span>templates</span><span>"</span><span>],</span> <span># new </span> <span>...</span>
<span>},</span>
<span>]</span>
<span># django_project/settings.py </span><span>TEMPLATES</span> <span>=</span> <span>[</span>
    <span>{</span>
        <span>...</span>
        <span>"</span><span>DIRS</span><span>"</span><span>:</span> <span>[</span><span>BASE_DIR</span> <span>/</span> <span>"</span><span>templates</span><span>"</span><span>],</span>  <span># new </span>        <span>...</span>
    <span>},</span>
<span>]</span>
# django_project/settings.py TEMPLATES = [ { ... "DIRS": [BASE_DIR / "templates"], # new ... }, ]

Enter fullscreen mode Exit fullscreen mode

Now create a new file called templates/contact.html and update it with the following code:

<span><!-- templates/contact.html --></span>
<span><h1></span>Contact Us<span></h1></span>
<span><form</span> <span>method=</span><span>"post"</span><span>></span>
{% csrf_token %}
{{ form }}
<span><div</span> <span>class=</span><span>"form-actions"</span><span>></span>
<span><button</span> <span>type=</span><span>"submit"</span><span>></span>Send<span></button></span>
<span></div></span>
<span></form></span>
<span><!-- templates/contact.html --></span>
<span><h1></span>Contact Us<span></h1></span>
<span><form</span> <span>method=</span><span>"post"</span><span>></span>
  {% csrf_token %}
  {{ form }}
  <span><div</span> <span>class=</span><span>"form-actions"</span><span>></span>
    <span><button</span> <span>type=</span><span>"submit"</span><span>></span>Send<span></button></span>
  <span></div></span>
<span></form></span>
<!-- templates/contact.html --> <h1>Contact Us</h1> <form method="post"> {% csrf_token %} {{ form }} <div class="form-actions"> <button type="submit">Send</button> </div> </form>

Enter fullscreen mode Exit fullscreen mode

Send first email

Make sure the server is running with python manage.py runserver and load http://127.0.0.1:8000/email/ in your web browser, fill out the form, and click the Send button.

If the email goes through, you will be redirected to the http://127.0.0.1:8000/success/.

And in your console/terminal, you can see that the email was sent:

(.venv) $ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
January 26, 2024 - 15:49:19
Django version 5.0.1, using settings 'django_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Received contact form submission
From: will@learndjango.com
To: will@learndjango.com
Date: Fri, 26 Jan 2024 15:49:28 -0000
Message-ID: <170628416888.90389.17657223448384564388@1.0.0.127.in-addr.arpa>
Received message below from will@email.com, Hello
________________________
Does this work?
-------------------------------------------------------------------------------
[26/Jan/2024 15:49:28] "POST /contact/ HTTP/1.1" 302 0
[26/Jan/2024 15:49:28] "GET /success/ HTTP/1.1" 200 43
(.venv) $ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
January 26, 2024 - 15:49:19
Django version 5.0.1, using settings 'django_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Received contact form submission
From: will@learndjango.com
To: will@learndjango.com
Date: Fri, 26 Jan 2024 15:49:28 -0000
Message-ID: <170628416888.90389.17657223448384564388@1.0.0.127.in-addr.arpa>


            Received message below from will@email.com, Hello
            ________________________


            Does this work?

-------------------------------------------------------------------------------
[26/Jan/2024 15:49:28] "POST /contact/ HTTP/1.1" 302 0
[26/Jan/2024 15:49:28] "GET /success/ HTTP/1.1" 200 43
(.venv) $ python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). January 26, 2024 - 15:49:19 Django version 5.0.1, using settings 'django_project.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Received contact form submission From: will@learndjango.com To: will@learndjango.com Date: Fri, 26 Jan 2024 15:49:28 -0000 Message-ID: <170628416888.90389.17657223448384564388@1.0.0.127.in-addr.arpa> Received message below from will@email.com, Hello ________________________ Does this work? ------------------------------------------------------------------------------- [26/Jan/2024 15:49:28] "POST /contact/ HTTP/1.1" 302 0 [26/Jan/2024 15:49:28] "GET /success/ HTTP/1.1" 200 43

Enter fullscreen mode Exit fullscreen mode

Production Email Service

To send actual emails, we first must switch the EMAIL_BACKEND from console to SMTP.

<span># django_project/settings.py </span><span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.smtp.EmailBackend</span><span>"</span> <span># new </span>
<span># django_project/settings.py </span><span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.smtp.EmailBackend</span><span>"</span>  <span># new </span>
# django_project/settings.py DEFAULT_FROM_EMAIL = "will@learndjango.com" NOTIFY_EMAIL = "will@learndjango.com" EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" # new

Enter fullscreen mode Exit fullscreen mode

All of the managed email services like SendGrid, mailgun, or SES have the option to send emails via SMTP.

When you sign up for an account, you will be assigned an email host, username, and password. The update to settings.py is nearly identical and looks like the one below, which uses SendGrid as an example.

<span># django_project/settings.py </span><span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.smtp.EmailBackend</span><span>"</span>
<span>EMAIL_HOST</span> <span>=</span> <span>"</span><span>smtp.sendgrid.net</span><span>"</span> <span># new </span><span>EMAIL_HOST_USER</span> <span>=</span> <span>"</span><span>apikey</span><span>"</span> <span># new </span><span>EMAIL_HOST_PASSWORD</span> <span>=</span> <span>"</span><span><sendgrid_password></span><span>"</span> <span># new </span><span>EMAIL_PORT</span> <span>=</span> <span>587</span> <span># new </span><span>EMAIL_USE_TLS</span> <span>=</span> <span>True</span> <span># new </span>
<span># django_project/settings.py </span><span>DEFAULT_FROM_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>NOTIFY_EMAIL</span> <span>=</span> <span>"</span><span>will@learndjango.com</span><span>"</span>
<span>EMAIL_BACKEND</span> <span>=</span> <span>"</span><span>django.core.mail.backends.smtp.EmailBackend</span><span>"</span>
<span>EMAIL_HOST</span> <span>=</span> <span>"</span><span>smtp.sendgrid.net</span><span>"</span>  <span># new </span><span>EMAIL_HOST_USER</span> <span>=</span> <span>"</span><span>apikey</span><span>"</span>  <span># new </span><span>EMAIL_HOST_PASSWORD</span> <span>=</span> <span>"</span><span><sendgrid_password></span><span>"</span>  <span># new </span><span>EMAIL_PORT</span> <span>=</span> <span>587</span>  <span># new </span><span>EMAIL_USE_TLS</span> <span>=</span> <span>True</span>  <span># new </span>
# django_project/settings.py DEFAULT_FROM_EMAIL = "will@learndjango.com" NOTIFY_EMAIL = "will@learndjango.com" EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = "smtp.sendgrid.net" # new EMAIL_HOST_USER = "apikey" # new EMAIL_HOST_PASSWORD = "<sendgrid_password>" # new EMAIL_PORT = 587 # new EMAIL_USE_TLS = True # new

Enter fullscreen mode Exit fullscreen mode

For more advanced usage, django-anymail is a popular package that makes it much easier to switch between email providers.

It is also worth noting that your email apikey and password should be kept secret and stored with environment variables, not in the source code and searchable via Git.

Conclusion

With this configuration in place, you can send real emails from your Django app. Often, this is used when a user signs up for the first time, needs to reset a password, and so on. All these steps, including implementing environment variables and customizing emails are covered in the Django for Beginners book.

原文链接:Django Email and Contact Form Tutorial

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
If you don't enjoy your life, sorrow, sadness, fear, shame and guilt will.
如果你不好好享受生活,你的悲伤、难过、害怕、羞愧和内疚会代替你享受
评论 抢沙发

请登录后发表评论

    暂无评论内容