Створення шаблонів електронної пошти за допомогою Django


206

Я хочу надсилати HTML-листи, використовуючи такі шаблони Django:

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

Я нічого не можу знайти send_mail, і django-mailer надсилає лише шаблони HTML, без динамічних даних.

Як використовувати механізм шаблонів Django для створення електронних листів?


3
Примітка Джанго 1.7пропозиції html_messageв send_email stackoverflow.com/a/28476681/953553
andilabs

Привіт @anakin, я довго боровся з цією проблемою і вирішив створити пакет для цього. Буду дуже радий отримати ваш відгук: github.com/charlesthk/django-simple-mail
Charlesthk

Відповіді:


385

З Документів , щоб відправити 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()

40
Я думаю, ви можете спростити це за допомогою render_to_string , що дозволить вам втратити окремі рядки, призначаючи шаблони до plaintextта htmly, і просто встановлювати шаблони та контексти, коли ви визначаєте text_contentта html_content.
cms_mgr

@cms_mgr Ви можете пояснити, що ви хочете сказати, і як ми можемо це використовувати
akki

3
@akki дивіться відповідь Анді нижче, що також спрощує альтернативну частину завдяки доданому html_message параму send_email () у Django 1.7
Mike S

Вибачте, але чому ми використовуємо txt і htmly одночасно для пошти. Я не зрозумів цю логіку
Шашанк Вівек

вони є лише прикладами для показу різного роду методів, ви можете використовувати будь-який з них @ShashankVivek
erdemlal

242

Хлопчики та дівчатка!

Оскільки метод Django 1.7 у send_emailhtml_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,
)

1
Зверніть увагу, якщо 'email.txt' і 'email.html' є у шаблонах каталогу, визначених у налаштуваннях, ніж просто виконувати render_to_string ('email.txt', {'some_params': some_params} _
Бруно Вермеулен

Дякую за render_to_stringпідказку, дуже зручно.
гофлінг

1
Гарне рішення! Однак, send_mailНЕ представляється можливим встановити деякі користувальницький заголовок , як то є , Return-Pathякий може бути встановлений зEmailMultiAlternatives's constructor header parameter
Qlimax

26

Я створив електронну пошту з шаблоном django, намагаючись вирішити цю проблему, надихнувшись цим рішенням (і потрібно, щоб у якийсь момент перейти від використання шаблонів 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',}

Це автоматично шукає шаблони з назвою "templated_email / email.txt" та "templated_email / email.html" для простої та html частини відповідно у звичайному django шаблоні dirs / loader (скаржиться, якщо він не зможе знайти хоча б одного з них) .


1
Мені добре виглядає. Я обрізав це і кинув у квиток, щоб додати django.shortcuts.send_templated_mail: code.djangoproject.com/ticket/17193
Том Крісті,

Класно, рада бачити, що його пропонують як інструмент для ядра джанго. Мій випадок використання / фокус для lib трохи більший, ніж просто ярлик (легке перемикання між постачальниками пошти, які мають ключ / значення api для відправки пошти), але це відчуває, як відсутня функція з ядра
Darb

15

Використовуйте 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()

5

Я створив 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)

Я хотів би отримати будь-які відгуки.


Це дуже допоможе, якщо ви завантажите демонстраційну програму свого пакету на репо.
ans2human

Привіт @ ans2human дякую за цю пропозицію, я додаю її до списку покращень!
Charlesthk

3

У прикладі є помилка .... якщо ви використовуєте її як написано, виникає така помилка:

<type 'exceptions.Exception'>: '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


Спасибі - це зараз виправлено.
Домінік Роджер

3

Джанго поштою шаблоновано - це багатофункціональний додаток 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 %}

Пітон:

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

Більше інформації: https://github.com/artemrizhov/django-mail-templated


Це було дуже просто у використанні. Дякую.
cheenbabes

Привіт, як я можу встановити всіх своїх одержувачів до BCC?
альдесабідо

@aldesabido Це просто обгортка навколо стандартного класу Django по електронній пошті. Таким чином , ви повинні прочитати офіційну документацію при пошуку таких ознак: docs.djangoproject.com/en/1.10/topics/email Також зверніть увагу на таке запитання: stackoverflow.com/questions/3470172 / ...
raacer

Якщо точніше, стандартний EmailMessage не завершується, а передається у спадок. Тобто це розширення для стандартного класу :)
гонщик

Можливо включити JS / CSS в шаблон?
Даніель Шац

3

Я знаю, що це старе питання, але я також знаю, що деякі люди такі, як я, і завжди шукають оновлених відповідей. оновлених , оскільки старі відповіді іноді можуть мати застарілу інформацію, якщо її не оновлювати.

Це вже січень 2020 року, і я використовую Django 2.2.6 та Python 3.7

Примітка. Я використовую рамку DJANGO REST, введений нижче код для надсилання електронної пошти був у наборі перегляду моделей у моєму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.txtі receipt_email.html? По-моєму settings.py, у мене є TEMPLATESі нижче, як це виглядає

Зверніть увагу DIRS, є ця лінія os.path.join(BASE_DIR, 'templates', 'email_templates') . Ця лінія - це те, що робить мої шаблони доступними. У своєму проект_dir у мене папка, що називається templates, і підкаталог, який називається email_templatesтак project_dir->templates->email_templates. Мої шаблони receipt_email.txtі receipt_email.htmlзнаходяться під email_templatessub_directory.

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>

0

Я написав фрагмент, який дозволяє надсилати електронні листи, надані з шаблонами, що зберігаються в базі даних. Приклад:

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

0

Якщо ви хочете динамічні шаблони електронної пошти для вашої пошти, тоді збережіть вміст електронної пошти у таблицях бази даних. Це те, що я зберегла як 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()

Це дозволить відправити динамічному шаблону HTML те, що ви зберегли в Db.


0

send_emai()не працювало для мене, тому я використовував EmailMessage тут у документах про джанго .

Я включив дві версії anser:

  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:

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>

-1

Мені подобається використовувати цей інструмент, щоб легко надсилати HTML та TXT електронної пошти за допомогою простої обробки контексту: https://github.com/divio/django-emailit

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.