How to Send Emails with Django
Tags: django, webdev, tutorial, python
Published: 2023-06-05 12:00:00

In today's interconnected world, email remains a vital means of communication for businesses, organizations, and individuals. As a Django developer, understanding how to integrate email functionality into your web applications is essential for enhancing user engagement and delivering critical information. Whether you're looking to send user notifications, password resets, newsletters, or any other type of email, [Django](https://www.ericsdevblog.com/posts/django-for-beginners-1/) provides a robust framework that simplifies the process.

In this article, we will delve into the intricacies of sending emails in Django. From configuring the email settings to leveraging Django's built-in features, this guide will equip you with the knowledge and tools to incorporate email functionality into your Django projects seamlessly. By the end, you'll be empowered to craft and send personalized emails, automating your communication process and providing a delightful experience for your users.

## Configuring the project

First, let us discuss the configuration process. To begin, locate the `settings.py` file within your project directory, and proceed to append the following lines of code:

```python
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '<your_email>'
EMAIL_HOST_PASSWORD = '<your_password>' # Note that this should be the App password rather than your Google account password
EMAIL_PORT = 465
EMAIL_USE_SSL = True
```

In the example provided, we're utilizing the default SMTP backend and Gmail service to handle email sending. To personalize it for your needs, simply replace `<your_email>` with your email address, and `<your_password>` with the App password generated from your Google account.

To generate the App password, you can follow these steps:

- Visit the [Google Account](https://myaccount.google.com/) page.
- Navigate to the **Security** section and select **2-Step Verification**. You must turn on the 2-Step Verification before proceeding to the next step.
- Under **App passwords**, choose the **Mail** app and select the device for which you want to generate the app password.
- Click the **Generate** button to create the app password.

![Generated app password](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1q39xo29hiorf0uhlhw.png)

Following these steps will give you a secure and personalized configuration for sending emails in your Django application.

## Sending your first email

Next, you can proceed to send a test email. Go to views.py:

```python
from django.shortcuts import render
from django.http import HttpResponse
from django.core.mail import send_mail

# Create your views here.


def send(request):
    send_mail(
        "Subject here",
        "Here is the message.",
        "from@example.com",
        ["<your_email_address>"],
        fail_silently=False,
    )
    return HttpResponse("Email sent.")

```

This example uses the default send_mail() method to send an email, which takes the following parameters:

- `subject`: The subject of the email.
- `message`: The actual content of the email.
- `from_email`: The email address that this email is sent from. If not set, Django will use the value of the `DEFAULT_FROM_EMAIL` setting. You may add this setting to the `settings.py` file.
- `recipient_list`: A list of email addresses. Each member of `recipient_list` will see the other recipients in the “To:” field of the email message.
- `fail_silently`: A boolean value. When it’s `False`, `send_mail()` will raise an `smtplib.SMTPException` if an error occurs.

In order to test this code, create a route that points to this `send()` view.

```python
from app import views

urlpatterns = [
    path('send/', views.send),
]
```

Start the Django application and send a request to `http://127.0.0.1:8000/send/`.

```cmd
curl http://127.0.0.1:8000/send/
```

Wait a few seconds, and you should get the following email in your inbox.

![email](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qc7dgg7va7qvbnpz1lny.png)

## Sending emails in bulk

To send multiple emails together, you may use the `send_mass_mail()` method instead.

```python
from django.shortcuts import render
from django.http import HttpResponse
from django.core.mail import send_mass_mail

# Create your views here.


def send(request):

    mails = (
        ("Subject #1", "Message #1", "from@example.com", ["<email_address>"]),
        ("Subject #2", "Message #2", "from@example.com", ["<email_address>"]),
        ("Subject #3", "Message #3", "from@example.com", ["<email_address>"]),
        ("Subject #4", "Message #4", "from@example.com", ["<email_address>"]),
        ("Subject #5", "Message #5", "from@example.com", ["<email_address>"]),
    )
    send_mass_mail(mails)
    return HttpResponse("Emails sent.")

```

The <email_address> placeholder can be different values. Send a request to the route, and you should receive five emails.

![multiple emails](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39o50are3r0d3ehxmdx0.png)

## Sending emails with attachments

Both `send_mail()` and `send_mass_mail()` methods are, in fact, wrappers using the `EmailMessage` class. They provide shortcuts allowing us to send emails more efficiently. However, if you want to do something more complex, for example, an email with attachments, you'll have to use the `EmailMessage` class directly.

```python
def send_attachment(request):
    email = EmailMessage(
        "Hello",
        "Body goes here",
        "from@example.com",
        ["huericnan@gmail.com"],
    )

    image_path = os.path.join('files/image.png')
    with open(image_path, 'rb') as f:
        img_data = f.read()

    email.attach("image.png", img_data, "image/png")

    email.send()

    return HttpResponse("Email sent with attachment.")
```

The `attach()` method takes three arguments: `filename`, `content`, and `mimetype`. `filename` is the name of the file attachment as it will appear in the email, `content` is the binary data that will be contained inside the attachment and `mimetype` is the optional MIME type for the attachment.

![email with attachment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/971vl9agywkwj8ldtck5.png)

Alternatively, you can create an attachment directly using a file in your filesystem without having to read the binary data first.

```python
email.attach_file("path/to/file")
```

## Sending HTML emails

Nowadays, most emails are crafted with HTML to make them more appealing to the readers. And Django also provides a way to send emails written in HTML.

```python
from django.core.mail import EmailMultiAlternatives

def send_html(request):
    subject, from_email, to = "Hello!", "from@example.com", "huericnan@gmail.com"
    text_content = "This is a message written in HTML."
    html_content = "<p>This is an <strong>important</strong> message.</p>"
    email = EmailMultiAlternatives(subject, text_content, from_email, [to])
    email.attach_alternative(html_content, "text/html")
    email.send()

    return HttpResponse("HTML email sent.")
```

The `EmailMultiAlternatives` class offers a way to send emails crafted in different formats. Notice that, in this example, there is a `text_content` and a `html_content`. By default, the body of the email will be `html_content`. However, if the recipient cannot open HTML, the `text_content` will be displayed instead.

![HTML email](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5w3q4x9a70zp4h5yi4s1.png)

## Creating templates for your emails

Sometimes, the email you send to different recipients might be different. For example, if you send account confirmation emails to different users, their usernames should differ. In this case, you should [create a template](https://www.ericsdevblog.com/posts/django-for-beginners-2/#the-django-template-system) for the emails. First, create a `template` directory for your app:

```text
.
├── app
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── templates
│   │   ├── email.html
│   │   └── email.txt
│   ├── tests.py
│   └── views.py
├── djangoEmail
├── files
└── manage.py
```

`email.txt`

```text
Congratulations, {{username}}! Your account has been successfully activated!
```

`email.html`

```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>Congratulations!</title>
</head>
<body>
    <h2>Congratulations, {{username}}!</h2>
    <p>Your account has been successfully activated!</p>
</body>
</html>
```

Modify the `send_html()` view to use the templates instead:

```python
from django.template.loader import get_template

def send_html_template(request):
    subject, from_email, to = "Hello!", "from@example.com", "huericnan@gmail.com"

    text = get_template('email.txt')
    html = get_template('email.html')

    username = 'jack'

    d = { 'username': username }

    text_content = text.render(d)
    html_content = html.render(d)

    email = EmailMultiAlternatives(subject, text_content, from_email, [to])
    email.attach_alternative(html_content, "text/html")
    email.send()

    return HttpResponse("HTML email sent.")
```

![HTML email with template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrq5upjxmf3eya6no56t.png)

## Conclusion

With Django's powerful email capabilities at your fingertips, you can create dynamic and engaging email experiences that enrich your web applications. This guide has provided a step-by-step approach to configuring your email settings, utilizing Django's built-in functions, and exploring advanced techniques for effective email communication.

Hope this article has been of assistance to you. Thanks for reading!