Erstellen von E-Mail-Vorlagen mit Django

205

Ich möchte HTML-E-Mails mit Django-Vorlagen wie diesen senden:

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

Ich kann nichts darüber send_mailfinden und django-mailer sendet nur HTML-Vorlagen ohne dynamische Daten.

Wie verwende ich die Template-Engine von Django, um E-Mails zu generieren?

Anakin
quelle
3
Hinweis Django 1.7bietet html_messagein send_email stackoverflow.com/a/28476681/953553
andilabs
Hallo @anakin, ich habe lange mit diesem Problem zu kämpfen und beschlossen, ein Paket dafür zu erstellen. Ich würde mich sehr über Ihr Feedback freuen: github.com/charlesthk/django-simple-mail
Charlesthk

Antworten:

384

Aus der Dokumentation , HTML - E-Mail , die Sie alternativ verwenden Content-Typen senden möchten, wie folgt aus :

from django.core.mail import EmailMultiAlternatives

subject, from_email, to = 'hello', '[email protected]', '[email protected]'
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()

Sie möchten wahrscheinlich zwei Vorlagen für Ihre E-Mail - eine einfache Textvorlage, die ungefähr so ​​aussieht und in Ihrem Vorlagenverzeichnis unter gespeichert ist email.txt:

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

und ein HTMLy, gespeichert unter email.html:

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

Sie können dann eine E-Mail mit diesen beiden Vorlagen senden, indem Sie Folgendes verwenden 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', '[email protected]', '[email protected]'
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()
Dominic Rodger
quelle
40
Ich glaube , Sie dies mit vereinfachen render_to_string , die Sie die einzelnen Linien Vorlagen verlieren lassen würde , um die Zuweisung plaintextund htmly, und nur Vorlagen und Kontexte gesetzt , wenn Sie definieren text_contentund html_content.
cms_mgr
@cms_mgr Können Sie näher erläutern, was Sie sagen möchten und wie wir das verwenden können
akki
3
@akki siehe andis Antwort unten, die auch den alternativen Teil vereinfacht, da der Parameter html_message zu send_email () in Django 1.7 hinzugefügt wurde
Mike S
Verzeihung, aber warum verwenden wir txt und htmly beide gleichzeitig für eine Mail? Ich habe diese Logik nicht verstanden
Shashank Vivek
Sie sind nur Beispiele, um verschiedene Arten von Methoden zu zeigen. Sie können jede dieser Methoden verwenden. @ShashankVivek
erdemlal
241

Jungen und Mädchen!

Seit Djangos 1.7 in der send_email- Methode wurde der html_messageParameter hinzugefügt.

html_message: Wenn html_message bereitgestellt wird, ist die resultierende E-Mail eine mehrteilige / alternative E-Mail mit einer Nachricht als Text- / Nur-Inhaltstyp und einer html_message als Text- / HTML-Inhaltstyp.

Sie können also einfach:

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,
    '[email protected]',
    ['[email protected]'],
    html_message=msg_html,
)
Andilabs
quelle
1
Beachten Sie, dass sich 'email.txt' und 'email.html' in einer Verzeichnisvorlage befinden, wie in den Einstellungen definiert, als nur render_to_string ('email.txt', {'some_params': some_params} _
Bruno Vermeulen
Danke für den render_to_stringHinweis, sehr praktisch.
Hacke
1
Gute Lösung! Es send_mailist jedoch nicht möglich, einen benutzerdefinierten Header wie dh Return-Pathfestzulegen, der mit demEmailMultiAlternatives's constructor header parameter
Qlimax
26

Ich habe Django-Vorlagen-E-Mails erstellt , um dieses Problem zu lösen, inspiriert von dieser Lösung (und der Notwendigkeit, irgendwann von der Verwendung von Django-Vorlagen zur Verwendung eines Mailchimp-Satzes usw. für Vorlagen für transaktionsbezogene Vorlagen-E-Mails zu wechseln mein eigenes Projekt). Es ist zwar noch in Arbeit, aber für das obige Beispiel würden Sie Folgendes tun:

from templated_email import send_templated_mail
send_templated_mail(
        'email',
        '[email protected]',
        ['[email protected]'],
        { 'username':username }
    )

Mit dem folgenden Zusatz zu settings.py (um das Beispiel zu vervollständigen):

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

Dadurch wird automatisch nach Vorlagen mit den Namen "templated_email / email.txt" und "templated_email / email.html" für den einfachen bzw. den HTML-Teil in den normalen Django-Vorlagenverzeichnissen / -ladern gesucht (Beschwerde, wenn mindestens eine davon nicht gefunden werden kann). .

Darb
quelle
1
Sieht gut für mich aus. Ich habe dies gekürzt und in ein Ticket geworfen, um es hinzuzufügen django.shortcuts.send_templated_mail: code.djangoproject.com/ticket/17193
Tom Christie
Cool, froh zu sehen, dass es als Werkzeug für den Django-Kern vorgeschlagen wird. Mein Anwendungsfall / Fokus für die Bibliothek ist etwas größer als nur die Verknüpfung (einfacher Wechsel zwischen Mail-Anbietern, die Schlüssel- / Wert-APIs für den Mail-Versand haben), aber es scheint eine fehlende Funktion im Kern zu sein
Darb
15

Verwenden Sie EmailMultiAlternatives und render_to_string, um zwei alternative Vorlagen zu verwenden (eine im Klartext und eine in 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 = ['[email protected]']
email.send()
Rick Westera
quelle
5

Ich habe Django Simple Mail erstellt , um eine einfache, anpassbare und wiederverwendbare Vorlage für jede Transaktions-E- Mail zu haben, die Sie senden möchten.

E-Mail-Inhalte und -Vorlagen können direkt vom Administrator von django bearbeitet werden.

Mit Ihrem Beispiel würden Sie Ihre E-Mail registrieren:

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)

Und senden Sie es so:

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)

Ich würde gerne Feedback bekommen.

Charlesthk
quelle
Es wäre sehr hilfreich, wenn Sie eine Demo-Anwendung Ihres Pakets auf Ihr Repo hochladen würden.
ans2human
Hallo @ ans2human, danke für diesen Vorschlag, ich füge ihn der Liste der Verbesserungen hinzu!
Charlesthk
3

Im Beispiel ist ein Fehler aufgetreten. Wenn Sie ihn wie geschrieben verwenden, tritt der folgende Fehler auf:

<Typ 'Ausnahmen.Ausnahme'>: Objekt 'dict' hat kein Attribut 'render_context'

Sie müssen den folgenden Import hinzufügen:

from django.template import Context

und ändern Sie das Wörterbuch wie folgt:

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

Siehe http://docs.djangoproject.com/de/1.2/ref/templates/api/#rendering-a-context

idbill
quelle
Danke - das ist jetzt behoben.
Dominic Rodger
3

Django Mail Templated ist eine funktionsreiche Django-Anwendung zum Senden von E-Mails mit dem Django-Vorlagensystem.

Installation:

pip install django-mail-templated

Aufbau:

INSTALLED_APPS = (
    ...
    'mail_templated'
)

Vorlage:

{% 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])

Weitere Informationen: https://github.com/artemrizhov/django-mail-templated

Raacer
quelle
Das war wirklich einfach zu bedienen. Vielen Dank.
Cheenbabes
Hallo, wie kann ich alle meine Empfänger auf BCC einstellen?
Aldesabido
@aldesabido Dies ist nur ein Wrapper um die Standard-EmailMessage-Klasse von Django. Lesen Sie daher die offizielle Dokumentation, wenn Sie nach solchen Funktionen suchen: docs.djangoproject.com/de/1.10/topics/email Schauen Sie sich auch eine ähnliche Frage an: stackoverflow.com/questions/3470172/…
raacer
Genauer gesagt wird die Standard-EmailMessage nicht verpackt, sondern vererbt. Dh dies ist eine Erweiterung für die Standardklasse :)
Raacer
Kann JS / CSS in die Vorlage aufgenommen werden?
Daniel Shatz
3

Ich weiß, dass dies eine alte Frage ist, aber ich weiß auch, dass einige Leute genau wie ich sind und immer nach aktuellen Antworten suchen , da alte Antworten manchmal veraltete Informationen enthalten können, wenn sie nicht aktualisiert werden.

Es ist jetzt Januar 2020 und ich verwende Django 2.2.6 und Python 3.7

Hinweis: Ich verwende DJANGO REST FRAMEWORK . Der folgende Code zum Senden von E-Mails befand sich in einem Modell-Viewset in meinemviews.py

Nachdem ich mehrere nette Antworten gelesen hatte, tat ich dies.

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 protected]"
    emailOfRecipient = '[email protected]'

    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)

Wichtig! Also wie kommt render_to_stringman receipt_email.txtund receipt_email.html? In meinem habe settings.pyich TEMPLATESund unten ist, wie es aussieht

Achten Sie darauf DIRS, dass es diese Zeile gibt. Diese Zeile os.path.join(BASE_DIR, 'templates', 'email_templates')macht meine Vorlagen zugänglich. In meinem Projektverzeichnis habe ich einen Ordner mit dem Namen templatesund ein Unterverzeichnis email_templateswie dieses project_dir->templates->email_templates. Meine Vorlagen receipt_email.txtund receipt_email.htmlbefinden sich im email_templatesUnterverzeichnis.

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',
        ],
    },
},
]

Lassen Sie mich das einfach hinzufügen, mein recept_email.txtAussehen sieht so aus;

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

Und mein receipt_email.htmlsieht so aus;

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

Ich habe ein Snippet geschrieben , mit dem Sie E-Mails senden können, die mit in der Datenbank gespeicherten Vorlagen gerendert wurden. Ein Beispiel:

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

Wenn Sie dynamische E-Mail-Vorlagen für Ihre E-Mails wünschen, speichern Sie den E-Mail-Inhalt in Ihren Datenbanktabellen. Dies ist, was ich als HTML-Code in der Datenbank gespeichert habe =

<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 Ihren Ansichten:

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

Dadurch wird der dynamischen HTML-Vorlage gesendet, was Sie in Db gespeichert haben.

Javed
quelle
0

send_emai()hat bei mir nicht funktioniert, also habe ich EmailMessage hier in Django-Dokumenten verwendet .

Ich habe zwei Versionen des Anser aufgenommen:

  1. Nur mit HTML-E-Mail-Version
  2. Mit Klartext-E-Mail- und HTML-E-Mail-Versionen
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()

Wenn Sie eine Nur-Text-Version Ihrer E-Mail einfügen möchten, ändern Sie Folgendes wie folgt:

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

Meine Plain- und HTML-Versionen sehen folgendermaßen aus: 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>
Alkadelik
quelle
-1

Ich verwende dieses Tool gerne, um das einfache Senden von E-Mail-HTML und TXT mit einfacher Kontextverarbeitung zu ermöglichen: https://github.com/divio/django-emailit

matinfo
quelle