This article will guide you through building a simple contact form using Django and SendGrid.
When running a web service or a blog, implementing a mail delivery system is often necessary. However, building such a system is not easy, and many difficulties are involved in creating one on your own.
I once built and operated a service that combined Django and Gmail to deliver emails. However, even though I believed the settings were done correctly, emails were not delivered as expected on many occasions. This is where SendGrid comes in. As a cloud-based email delivery system, it is easy to set up, and in my experience, email delivery problems rarely occur when using SendGrid.
Furthermore, SendGrid is very easy to integrate with your existing web application. It is currently one of the most popular email delivery systems among web developers.
In this article, I will show you how to use SendGrid in Django to easily send emails through a contact form.
About SendGrid's Free Tier
SendGrid offers both free and paid plans. The free plan is limited to sending 100 emails per day.
While there are some additional limitations beyond email volume between the free and paid plans, the free tier should be sufficient for testing and verification purposes.
Two Ways to Integrate SendGrid into Django
There are two primary ways to integrate SendGrid with Django: using an SMTP server or leveraging the Web API. Most online tutorials demonstrating Django and SendGrid tend to focus on the SMTP solution.
However, SMTP delivery has some drawbacks that make it less suitable for modern web applications. It can be slower than the Web API and offers limited error messages, making debugging more difficult. Therefore, if you're integrating email sending into your Django project, building a system around the Web API is generally preferred.
This article will demonstrate how to send emails using SendGrid's Web API with Django's built-in email functions via the django-sendgrid-v5 package.
This approach is arguably the easiest way to use SendGrid with Django while establishing a foundation for a scalable and robust email delivery system.
Environment for application development
After creating a basic Django application, we'll integrate SendGrid. The process of creating a basic Django application won't be covered here.
If you're using Docker, please refer to this article to set up a basic Django application within a Docker container.
Application Overview
We will create an application that generates a simple form and sends an email to the site owner when the form is submitted with valid input.
To confirm the implementation of SendGrid, we will only create the Form, Template, and corresponding View for this simple application. We will not create a Model.
We will use the following package to forward mail via web API.
Project file structure
The project is named django_08
, and the app is named "send_test".
( At the end of this article, you'll find a link to the project's GitHub repository. Note that the project and app names have been changed in the repository. )
When using SendGrid, an API key is required. This key should be written in the .env file, which will be described later.
Implementation Process
The process might involve some back and forth, but generally, it follows these steps:
1. Setting up SendGrid
To start, go to the SendGrid website and obtain an API key.
The process of obtaining an API key has been covered in various tutorials, so I'll just show you a screenshot of the page to get it in this blog. It can be found in the settings at the bottom of the sidebar navigation.
2. Installing the Package
Please install the packages listed in the accompanying list, assuming that the basic package for running Django and Django itself have already been installed.
django-environ
django-sendgrid-v5
3. settings.py
Add the following code in settings.py
to use the web API in a local environment.
Setting SENDGRID_SANDBOX_MODE_IN_DEBUG
to False
ensures that emails are sent to the designated email address even during development, rather than being routed to the console. I prefer this approach as it's more practical.
EMAIL_BACKEND = "sendgrid_backend.SendgridBackend"
SENDGRID_API_KEY = os.getenv('SENDGRID_API_KEY')
SENDGRID_SANDBOX_MODE_IN_DEBUG=False
Additionally, create an .env
file and enter the value of the SendGrid API_KEY.
SENDGRID_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
4. urls.py
Create two files: urls.py
in the Django root directory and urls.py
in the application folder.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('send_test.urls', namespace='send_app')),
]
You might encounter an error related to the line from send_test import views
. You can safely ignore this error and continue with the next steps.
from django.urls import path
from send_test import views
app_name = 'send_app'
urlpatterns = [
path('', views.home, name='send_test'),
]
Only include very basic content in the view. Write the code as shown below.
from django.shortcuts import render
def home(request):
return render(request, 'send_test/home.html')
5. forms.py
Create a form as follows. Create a forms.py
file inside your application directory.
from django import forms
class SendForm(forms.Form):
email = forms.EmailField(label="Email", max_length=100)
content = forms.CharField(label="Content", max_length=200)
6. Templates
Next, let's create the template files. Refer to the previously mentioned file structure and create base.html
and home.html
.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
{% extends 'base.html' %}
{% block content %}
<h1>SendGrid Test App</h1>
<form id="TestForm" method="post" action="{% url 'send_app:send_test' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" value="Test">send message</button>
</form>
{% endblock %}
http://127.0.0.1:8000/
(the URL and port may differ depending on the environment). When you access it, the accompanying image will be displayed:
7. views.py
This section is the most important in this tutorial.
Below the try
block in this view, there is a function called send_mail
that sends an email using SendGrid after validating the submitted data.
This single line of code is all that is needed to send an email.
The rest appears to be handled by django-sendgrid-v5
.
Regarding the send_mail
function, please note that the fourth argument is used to specify the email address of the recipient.
To avoid hardcoding email addresses directly in your code, assign the email address to an environment variable and then use recipients = os.getenv('TO_EMAIL')
, replacing TO_EMAIL
with the name of your environment variable.
import os
from django.http import HttpResponse
from django.shortcuts import render
from .forms import SendForm
from django.core.mail import send_mail, BadHeaderError
def home(request):
if request.method == "POST":
form = SendForm(request.POST)
if form.is_valid():
subject = 'Message from TestAccount'
message = form.cleaned_data['content']
sender = form.cleaned_data['email']
recipients = os.getenv('TO_EMAIL')
try:
send_mail(subject, message, sender, [recipients], fail_silently=False)
return HttpResponse('Successfully sent a message!')
except BadHeaderError:
return HttpResponse('Error!')
else:
form = SendForm()
return render(request, 'send_test/home.html', {'form':form })
That's all! With SendGrid, you can create a reliable email delivery environment with a simple setup and code, as shown above. There's no reason not to use it, so let's all start using it actively.
I've also created a GitHub repository for this application, which you can access here.
Happy coding!