用Django创建电子邮件模板

我想发送html电子邮件,使用Django模板,像这样:

<html>
<body>
hello <strong>{{username}}</strong>
your account activated.
<img src="mysite.com/logo.gif" />
</body>

我找不到任何关于send_mail的东西,django-mailer只发送HTML模板,没有动态数据。

如何使用Django的模板引擎生成电子邮件?

167869 次浏览

的文档中,要发送HTML电子邮件,你需要使用替代的内容类型,像这样:

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()

你可能需要两个电子邮件模板——一个纯文本模板,看起来像这样,存储在模板目录email.txt下:

Hello \{\{ username }} - your account is activated.

和一个HTMLy的,存储在email.html下:

Hello <strong>\{\{ username }}</strong> - your account is activated.

然后你可以通过使用get_template来使用这两个模板发送电子邮件,就像这样:

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


plaintext = get_template('email.txt')
htmly     = get_template('email.html')


d = Context({ 'username': username })


subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
text_content = plaintext.render(d)
html_content = htmly.render(d)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()

示例....中有一个错误如果你像写的那样使用它,会出现以下错误:

& lt;类型的异常。异常' >:'dict'对象没有属性'render_context'

您将需要添加以下导入:

from django.template import Context

并将字典改为:

d = Context({ 'username': username })

看到http://docs.djangoproject.com/en/1.2/ref/templates/api/#rendering-a-context

我已经做了django-templated-email在努力解决这个问题,灵感来自这个解决方案(在某些时候,需要从使用django模板切换到使用mailchimp等一组模板的事务性,我自己的项目的模板电子邮件)。虽然这仍然是一个正在进行的工作,但对于上面的例子,你可以这样做:

from templated_email import send_templated_mail
send_templated_mail(
'email',
'from@example.com',
['to@example.com'],
{ 'username':username }
)

在settings.py中添加以下内容(以完成示例):

TEMPLATED_EMAIL_DJANGO_SUBJECTS = {'email':'hello',}

它会自动在普通的django模板dirs/loaders中分别为plain部分和html部分寻找名为templated_email/email.txt和templated_email/email.html的模板(如果找不到其中至少一个会报错)。

Django Mail Templated是一个功能丰富的Django应用程序,用Django模板系统发送电子邮件。

安装:

pip install django-mail-templated

配置:

INSTALLED_APPS = (
...
'mail_templated'
)

模板:

{% block subject %}
Hello \{\{ user.name }}
{% endblock %}


{% block body %}
\{\{ user.name }}, this is the plain text part.
{% endblock %}

Python:

from mail_templated import send_mail
send_mail('email/hello.tpl', {'user': user}, from_email, [user.email])

更多信息:https://github.com/artemrizhov/django-mail-templated

使用EmailMultiAlternatives和render_to_string来使用两个可供选择的模板(一个是纯文本,一个是html):

from django.core.mail import EmailMultiAlternatives
from django.template import Context
from django.template.loader import render_to_string


c = Context({'username': username})
text_content = render_to_string('mail/email.txt', c)
html_content = render_to_string('mail/email.html', c)


email = EmailMultiAlternatives('Subject', text_content)
email.attach_alternative(html_content, "text/html")
email.to = ['to@example.com']
email.send()

在Django的1.7版本中,send_email方法添加了html_message参数。

html_message:如果提供了html_message,生成的电子邮件将是 多部分/可选的电子邮件,以消息作为文本/纯内容 输入html_message作为文本/html内容类型

所以你可以:

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




msg_plain = render_to_string('templates/email.txt', {'some_params': some_params})
msg_html = render_to_string('templates/email.html', {'some_params': some_params})


send_mail(
'email title',
msg_plain,
'some@sender.com',
['some@receiver.com'],
html_message=msg_html,
)

我喜欢使用这个工具,允许轻松地发送电子邮件HTML和TXT与简单的上下文处理:https://github.com/divio/django-emailit

我写了一个片段,它允许你用存储在数据库中的模板发送电子邮件。一个例子:

EmailTemplate.send('expense_notification_to_admin', {
# context object that email template will be rendered with
'expense': expense_request,
})

如果你想为你的邮件动态电子邮件模板,然后将电子邮件内容保存在你的数据库表。 这是我保存为HTML代码在数据库=

<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>

在你看来:

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()

这将发送您保存在Db中的动态HTML模板。

我已经创建Django Simple Mail有一个简单的,可定制的和可重用的模板,每一个事务性的电子邮件你想发送。

邮件内容和模板可以直接从django的管理编辑。

在你的例子中,你会注册你的电子邮件:

from simple_mail.mailer import BaseSimpleMail, simple_mailer




class WelcomeMail(BaseSimpleMail):
email_key = 'welcome'


def set_context(self, user_id, welcome_link):
user = User.objects.get(id=user_id)
return {
'user': user,
'welcome_link': welcome_link
}




simple_mailer.register(WelcomeMail)

然后用这种方式发送:

welcome_mail = WelcomeMail()
welcome_mail.set_context(user_id, welcome_link)
welcome_mail.send(to, from_email=None, bcc=[], connection=None, attachments=[],
headers={}, cc=[], reply_to=[], fail_silently=False)

我很乐意得到任何反馈。

我知道这是一个老问题,但我也知道有些人就像我一样,总是在寻找最新的答案,因为旧的答案如果不更新,有时会有过时的信息。

现在是2020年1月,我使用的是Django 2.2.6和Python 3.7

注意:我使用DJANGO REST FRAMEWORK,下面的代码用于发送电子邮件是在模型视图集在我的views.py

所以在看了很多不错的答案之后,我就这么做了。

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


def send_receipt_to_email(self, request):


emailSubject = "Subject"
emailOfSender = "email@domain.com"
emailOfRecipient = 'xyz@domain.com'


context = ({"name": "Gilbert"}) #Note I used a normal tuple instead of  Context({"username": "Gilbert"}) because Context is deprecated. When I used Context, I got an error > TypeError: context must be a dict rather than Context


text_content = render_to_string('receipt_email.txt', context, request=request)
html_content = render_to_string('receipt_email.html', context, request=request)


try:
#I used EmailMultiAlternatives because I wanted to send both text and html
emailMessage = EmailMultiAlternatives(subject=emailSubject, body=text_content, from_email=emailOfSender, to=[emailOfRecipient,], reply_to=[emailOfSender,])
emailMessage.attach_alternative(html_content, "text/html")
emailMessage.send(fail_silently=False)


except SMTPException as e:
print('There was an error sending an email: ', e)
error = {'message': ",".join(e.args) if len(e.args) > 0 else 'Unknown Error'}
raise serializers.ValidationError(error)
那么render_to_string如何得到receipt_email.txtreceipt_email.html呢? 在我的settings.py中,我有TEMPLATES,下面是它的样子

注意DIRS,有这一行os.path.join(BASE_DIR, 'templates', 'email_templates') 这一行使我的模板可访问。在我的project_dir中,我有一个名为templates的文件夹和一个名为email_templates的子目录,就像这样project_dir->templates->email_templates。我的模板receipt_email.txtreceipt_email.htmlemail_templates子目录下。< / p >
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'email_templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

让我补充一下,我的recept_email.txt是这样的;

Dear \{\{name}},
Here is the text version of the email from template

我的receipt_email.html是这样的;

Dear \{\{name}},
<h1>Now here is the html version of the email from the template</h1>

send_emai()不适合我,所以我用了EmailMessage 这里是django docs

我有两个版本的答案:

  1. 只提供html电子邮件版本
  2. 与纯文本电子邮件和html电子邮件版本
from django.template.loader import render_to_string
from django.core.mail import EmailMessage


# import file with html content
html_version = 'path/to/html_version.html'


html_message = render_to_string(html_version, { '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 version
message.send()

如果你想包含一个纯文本版本的电子邮件,修改如下:

from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives # <= EmailMultiAlternatives instead of EmailMessage


plain_version = 'path/to/plain_version.html' # import plain version. No html content
html_version = 'path/to/html_version.html' # import html version. Has html content


plain_message = render_to_string(plain_version, { 'context': context, })
html_message = render_to_string(html_version, { 'context': context, })


message = EmailMultiAlternatives(subject, plain_message, from_email, [to_email])
message.attach_alternative(html_message, "text/html") # attach html version
message.send()
我的普通和html版本看起来像这样: plain_version.html: < / p >
Plain text \{\{ context }}

html_version.html

<!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>
...
</head>
<body>
<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;">
...
\{\{ context }}
...
</table>
</body>
</html>