Learn to Django send an email with an attachment. Django Email Attachment comes with in-built, ready to use Email System. Sending Email using Django is a Really Simple Task. In Django, we just need to import django.core.mail. You will learn how to send an email with multiple attachments in Django.
How to Send Email With Attachments in Django
In this tutorial, you will learn how to send an email with multiple attachments in Django. You will also learn how to send an email with a single attachment. Here, I will explain how to set up your SendGrid Account for Sending Emails for your Django Application. You’ll also find code bellow for Django Send Email with Attachment. I will also explain how to set your Email Host in the settings.py file, in your application:
- EMAIL_HOST − SMTP server.
- EMAIL_HOST_USER − Login credentials for the SMTP server.
- EMAIL_HOST_PASSWORD − Password credential for the SMTP server.
- EMAIL_PORT − SMTP server port.
- EMAIL_USE_TLS or _SSL − True if secure connection.
Lets get started by setting up SendGrid Account Free Plan.
Setup SendGrid Account for Email API
Go to the SendGrid Website. On the homepage, you will find Try For Free Button. It will take you to the Create Account Page. After creating your account, you should activate your account. Activation Email is sent on Register Email Address. Click on the link and it will activate your account.
Create SendGrid API Key
- In the Sendgrid dashboard, head to Settings -> API Keys and click on ‘Create API Key’.
- Next, name your API key and make sure to set permissions to Full Access. Click ‘Create & View’ when you are ready.
- Next, click on the API key to copy it to your clipboard.
Configure Django for SendGrid SMTP server
Go to your settings.py file and add the following parameters
# Email EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.sendgrid.net' EMAIT_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = 'apikey' EMAIL_HOST_PASSWORD = 'SG.oDN9basdaECvH5asdasw.gXVEgtD1asqSkn-EW'
Please change EMAIL_HOST_PASSWORD with your SendGrid Password.
Note: It is risky to directly put sensitive data directly in settings.py. For putting sensitive data, we should you Environment Variable or Python Decouple. For the testing purpose, this is absolutely fine.
Sending Emails from your Django Applications
Setup your initial Django Project. I have a tutorial where I install Django Application in Virtual Environment. Once you setup your initial project then we can go further. I hope you people have already created because above you have edited your settings.py file.
I am also sharing the GitHub link of the project at the end of the blog. The bellow is the final application will look like:

Here I am sharing Views, Forms, HTML file, and URLs Snippet. The actual email is sent because we have imported from django.core.mail import EmailMessage
.
This the main logic which sends email in our Django App.
mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email]) mail.attach(attach.name, attach.read(), attach.content_type) mail.send()
Views.py
# views.py from django.http import HttpResponseRedirect from django.shortcuts import render from django.views import View from django.core.mail import EmailMessage from django.conf import settings from .forms import EmailForm class EmailAttachementView(View): form_class = EmailForm template_name = 'emailattachment.html' def get(self, request, *args, **kwargs): form = self.form_class() return render(request, self.template_name, {'email_form': form}) def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request.FILES) if form.is_valid(): subject = form.cleaned_data['subject'] message = form.cleaned_data['message'] email = form.cleaned_data['email'] files = request.FILES.getlist('attach') try: mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email]) for f in files: mail.attach(f.name, f.read(), f.content_type) mail.send() return render(request, self.template_name, {'email_form': form, 'error_message': 'Sent email to %s'%email}) except: return render(request, self.template_name, {'email_form': form, 'error_message': 'Either the attachment is too big or corrupt'}) return render(request, self.template_name, {'email_form': form, 'error_message': 'Unable to send email. Please try again later'}) # Single File Attachment # def post(self, request, *args, **kwargs): # form = self.form_class(request.POST, request.FILES) # if form.is_valid(): # subject = form.cleaned_data['subject'] # message = form.cleaned_data['message'] # email = form.cleaned_data['email'] # attach = request.FILES['attach'] # try: # mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email]) # mail.attach(attach.name, attach.read(), attach.content_type) # mail.send() # return render(request, self.template_name, {'email_form': form, 'error_message': 'Sent email to %s'%email}) # except: # return render(request, self.template_name, {'email_form': form, 'error_message': 'Either the attachment is too big or corrupt'}) # return render(request, self.template_name, {'email_form': form, 'error_message': 'Unable to send email. Please try again later'})
The above comment code post
is for sending a mail with a single attachment.
Forms.py
# forms.py from django import forms class EmailForm(forms.Form): email = forms.EmailField() subject = forms.CharField(max_length=100) attach = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True})) message = forms.CharField(widget = forms.Textarea)
This the form which we have displayed on our webpage. I am using widget=forms.ClearableFileInput(attrs={'multiple': True})
for multiple attachments. If you are using a single attachment email then remove that line.
emailattchment.html
{% load crispy_forms_tags %} <!DOCTYPE html> <html lang="en"> <head> <title>Email Attachment - Django and Python</title> <!-- Bootstrap core CSS --> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <!-- Page Content --> <div class="container"> <div class="row"> <div class="col-lg-12"> <h1 class="mt-5 mb-3">Django Email Attachment</h1> {% if error_message %} <div class="alert alert-primary" role="alert"> {{error_message}} </div> {% endif %} {% if email_form %} <form method="POST" action ="" enctype="multipart/form-data"> {% csrf_token %} {{email_form|crispy}} <button type="submit" class="btn btn-primary">Send Email</button> </form> {% endif %} </div> </div> </div> <!-- Bootstrap core JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html>
I am using the Bootstrap4 and django_crispy_form library for good UI.
Urls.py
from django.urls import path from emailattachment.views import EmailAttachementView urlpatterns = [ path('', EmailAttachementView.as_view(), name='emailattachment') ]
The route to display our view.
Conclusion for Django send Email with Attachment
The above code is able to send attachments like images, files via emails. We have shared the code which will send single and multiple email attachments at the same time. Run your Django Server and go to http://localhost:8000/
This is also available on GitHub – https://github.com/studygyaan/how-to-send-email-with-attachments-in-django