82

Can anyone please help me sending html email with dynamic contents. One way is to copy the entire html code into a variable and populate the dynamic code within it in Django views, but that does not seem to be a good idea, as its a very large html file.

I would appreciate any suggestions.

Thanks.

Ankit Jaiswal
  • 821
  • 1
  • 7
  • 3

7 Answers7

171

Django includes the django.core.mail.send_mail method these days (2018), no need to use EmailMultiAlternatives class directly. Do this instead:

from django.core import mail
from django.template.loader import render_to_string
from django.utils.html import strip_tags

subject = 'Subject'
html_message = render_to_string('mail_template.html', {'context': 'values'})
plain_message = strip_tags(html_message)
from_email = 'From <from@example.com>'
to = 'to@example.com'

mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)

This will send an email which is visible in both html-capable browsers and will show plain text in crippled email viewers.

Babken Vardanyan
  • 14,090
  • 13
  • 68
  • 87
76

Example:

from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.html import strip_tags

subject, from_email, to = 'Subject', 'from@xxx.com', 'to@xxx.com'

html_content = render_to_string('mail_template.html', {'varname':'value'}) # render with dynamic value
text_content = strip_tags(html_content) # Strip the html tag. So people can see the pure text at least.

# create the email, and attach the HTML version as well.
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()
alexandernst
  • 14,352
  • 22
  • 97
  • 197
Marvin W
  • 3,423
  • 28
  • 16
  • 1
    +1 EmailMultiAlternatives. Official docs: https://docs.djangoproject.com/en/1.8/topics/email/#sending-alternative-content-types – dokkaebi Aug 31 '15 at 16:33
  • 1
    for simple stuff, we don't need `EmailMultiAlternatives`. Just use `html_message=` with `send_mail`. See @Babken's [answer below](https://stackoverflow.com/a/49894619/1526703) – Anupam May 16 '18 at 10:18
19

For anyone looking at this in 2020 and using django v3.x (I don't know when this was introduced so it might work for earlier versions.

Note: I only wanted to include an html version without a plain text version. My django view:

from django.template.loader import render_to_string 
from django.core.mail import EmailMessage

# import html message.html file
html_template = 'path/to/message.html'

html_message = render_to_string(html_template, { 'context': context, })

message = EmailMessage(subject, html_message, from_email, [to_email])
message.content_subtype = 'html' # this is required because there is no plain text email message
message.send()

My html file (message.html) looked like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>Order received</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body style="margin: 0; padding: 0;">
  <table align="center" border="0" cellpadding="0" cellspacing="0" width="320" style="border: none; border-collapse: collapse; font-family:  Arial, sans-serif; font-size: 14px; line-height: 1.5;">
...
content
...
</table>
</body>
</html>

More details here: Send alternative content types from django docs

alkadelik
  • 526
  • 1
  • 7
  • 18
  • does `{% trans "content" %}` work with the html template? – Pol Frances Jan 14 '21 at 18:24
  • 1
    If you save your template in the template folder of your app, then use: `from django.template.loader import get_template` and `template = get_template('your filepath')` to get the html loaded. From there just add `.render({'content': your data})` to have it rendered. – R. Steigmeier Feb 16 '21 at 11:18
11

This should do what you want:

from django.core.mail import EmailMessage
from django.template import Context
from django.template.loader import get_template


template = get_template('myapp/email.html')
context = Context({'user': user, 'other_info': info})
content = template.render(context)
if not user.email:
    raise BadHeaderError('No email address given for {0}'.format(user))
msg = EmailMessage(subject, content, from, to=[user.email,])
msg.send()

See the django mail docs for more.

blokeley
  • 6,726
  • 9
  • 53
  • 75
8

Try this::::

https://godjango.com/19-using-templates-for-sending-emails/

sample code link

# views.py

from django.http import HttpResponse
from django.template import Context
from django.template.loader import render_to_string, get_template
from django.core.mail import EmailMessage

def email_one(request):
    subject = "I am a text email"
    to = ['buddy@buddylindsey.com']
    from_email = 'test@example.com'

    ctx = {
        'user': 'buddy',
        'purchase': 'Books'
    }

    message = render_to_string('main/email/email.txt', ctx)

    EmailMessage(subject, message, to=to, from_email=from_email).send()

    return HttpResponse('email_one')

def email_two(request):
    subject = "I am an HTML email"
    to = ['buddy@buddylindsey.com']
    from_email = 'test@example.com'

    ctx = {
        'user': 'buddy',
        'purchase': 'Books'
    }

    message = get_template('main/email/email.html').render(Context(ctx))
    msg = EmailMessage(subject, message, to=to, from_email=from_email)
    msg.content_subtype = 'html'
    msg.send()

    return HttpResponse('email_two')
dokkaebi
  • 9,004
  • 3
  • 42
  • 60
vijay
  • 1,475
  • 2
  • 16
  • 26
1

If you want dynamic email templates for your mail then save the email content in your database tables. This is what i saved as HTML code in database =

<p>Hello.. {{ first_name }} {{ last_name }}.  <br> This is an <strong>important</strong> {{ message }}
<br> <b> By Admin.</b>

 <p style='color:red'> Good Day </p>

In your views:

from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template

def dynamic_email(request):
    application_obj = AppDetails.objects.get(id=1)
    subject = 'First Interview Call'
    email = request.user.email
    to_email = application_obj.email
    message = application_obj.message

    text_content = 'This is an important message.'
    d = {'first_name': application_obj.first_name,'message':message}
    htmly = FirstInterviewCall.objects.get(id=1).html_content #this is what i have saved previously in database which i have to send as Email template as mentioned above HTML code

    open("partner/templates/first_interview.html", "w").close() # this is the path of my file partner is the app, Here i am clearing the file content. If file not found it will create one on given path.
    text_file = open("partner/templates/first_interview.html", "w") # opening my file
    text_file.write(htmly) #putting HTML content in file which i saved in DB
    text_file.close() #file close

    htmly = get_template('first_interview.html')
    html_content = htmly.render(d)  
    msg = EmailMultiAlternatives(subject, text_content, email, [to_email])
    msg.attach_alternative(html_content, "text/html")
    msg.send()

This will send the dynamic HTML template what you have save in Db.

Javed
  • 1,613
  • 17
  • 16
1
from django.core.mail import EmailMultiAlternatives

subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to]
msg.attach_alternative(html_content, "text/html")
msg.send()