Creazione di modelli di email con Django


207

Voglio inviare e-mail HTML, utilizzando modelli Django come questo:

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

Non riesco a trovare nulla send_maile django-mailer invia solo modelli HTML, senza dati dinamici.

Come posso utilizzare il motore di template di Django per generare e-mail?


3
Avviso Django 1.7offerte html_messagein send_email stackoverflow.com/a/28476681/953553
andilabs

Ciao @anakin, ho lottato a lungo con questo problema e ho deciso di creare un pacchetto per quello. Sarei molto felice di ricevere il tuo feedback: github.com/charlesthk/django-simple-mail
Charlesthk

Risposte:


385

Dai documenti , per inviare e-mail HTML si desidera utilizzare tipi di contenuto alternativi, come questo:

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

Probabilmente avrai bisogno di due modelli per la tua e-mail: uno di testo semplice simile a questo, memorizzato nella directory dei modelli in email.txt:

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

e uno HTMLy, archiviato sotto email.html:

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

È quindi possibile inviare un'e-mail utilizzando entrambi questi modelli facendo uso di get_template, in questo modo:

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
Penso che si possa semplificare questo con render_to_string , che permetterà di perdere le linee separate assegnando modelli per plaintexte htmly, e basta impostare modelli e contesti in cui si definiscono text_contente html_content.
cms_mgr

@cms_mgr Puoi elaborare cosa vuoi dire e come possiamo usarlo
Akki

3
@akki vedi la risposta di andi sotto, che semplifica anche la parte alternativa grazie al parametro html_message che viene aggiunto a send_email () in Django 1.7
Mike S

Perdonatemi, ma perché usiamo txt e htmly entrambi contemporaneamente per una mail. Non ho capito questa logica
Shashank Vivek,

sono solo esempi per mostrare diversi tipi di metodi, puoi usare uno di loro @ShashankVivek
erdemlal

242

Ragazzi e ragazze!

Dal 1.7 di Django nel metodo send_email il html_messageparametro è stato aggiunto.

html_message: se viene fornito html_message, l'e-mail risultante sarà un'e-mail multipart / alternativa con messaggio come tipo di testo / contenuto normale e html_message come tipo di contenuto testo / html.

Quindi puoi semplicemente:

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
Nota se "email.txt" e "email.html" si trovano in modelli di directory come definito nelle impostazioni rispetto a render_to_string ("email.txt", {"some_params": some_params} _
Bruno Vermeulen

Grazie per il render_to_stringsuggerimento, molto utile.
hoefling

1
Buona soluzione! Tuttavia, con send_mailnon è possibile impostare alcuni header personalizzati come ie Return-Pathche possono essere impostati conEmailMultiAlternatives's constructor header parameter
Qlimax

26

Ho creato django-templated-email nel tentativo di risolvere questo problema, ispirato da questa soluzione (e la necessità, ad un certo punto, di passare dall'uso dei modelli django all'utilizzo di un mailchimp ecc. Set di modelli per e-mail transazionali il mio progetto). È comunque un work-in-progress, ma per l'esempio sopra, dovresti fare:

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

Con l'aggiunta di quanto segue a settings.py (per completare l'esempio):

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

Questo cercherà automaticamente i modelli denominati "templated_email / email.txt" e "templated_email / email.html" rispettivamente per le parti semplici e html, nelle normali directory / caricatori del modello django (lamentandosi se non riesce a trovarne almeno una) .


1
Mi sembra buono. L'ho tagliato e buttato in un biglietto per aggiungere django.shortcuts.send_templated_mail: code.djangoproject.com/ticket/17193
Tom Christie,

Bello, felice di vederlo essere proposto come uno strumento per il django core. Il mio caso d'uso / focus per la lib è un po 'più grande della semplice scorciatoia (passaggio facile tra i provider di posta che hanno api chiave / valore per l'invio di posta), ma sembra una caratteristica mancante dal core
Darb

15

Usa EmailMultiAlternatives e render_to_string per utilizzare due modelli alternativi (uno in testo normale e uno 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 = ['to@example.com']
email.send()

5

Ho creato Django Simple Mail per avere un modello semplice, personalizzabile e riutilizzabile per ogni e-mail transazionale che desideri inviare.

I contenuti e i modelli di e-mail possono essere modificati direttamente dall'amministratore di django.

Con il tuo esempio, registreresti la tua email:

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)

E invialo in questo modo:

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)

Mi piacerebbe ricevere feedback.


Sarebbe molto utile se carichi un'applicazione demo del tuo pacchetto sul tuo repository.
ans2human,

Ciao @ ans2human grazie per questo suggerimento, lo aggiungo all'elenco dei miglioramenti!
Charlesthk,


3

Django Mail Templated è un'applicazione Django ricca di funzionalità per inviare e-mail con il sistema di modelli Django.

Installazione:

pip install django-mail-templated

Configurazione:

INSTALLED_APPS = (
    ...
    'mail_templated'
)

Modello:

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

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

Pitone:

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

Maggiori informazioni: https://github.com/artemrizhov/django-mail-templated


Questo è stato davvero facile da usare. Grazie.
Cheenbabes

Ciao, come posso impostare tutti i miei destinatari su BCC?
aldesabido,

@aldesabido Questo è solo un wrapper per la classe EmailMessage standard di Django. Quindi, si dovrebbe leggere la documentazione ufficiale quando alla ricerca di tali caratteristiche: docs.djangoproject.com/en/1.10/topics/email prendere anche uno sguardo a domanda simile: stackoverflow.com/questions/3470172/...
raacer

Per essere più precisi, il messaggio di posta elettronica standard non è racchiuso, ma ereditato. Cioè questa è un'estensione per la classe standard :)
raacer

È possibile includere JS / CSS nel modello?
Daniel Shatz,

3

So che questa è una vecchia domanda, ma so anche che alcune persone sono proprio come me e sono sempre alla ricerca di risposte aggiornate , poiché le vecchie risposte a volte possono avere informazioni deprecate se non aggiornate.

Ora è gennaio 2020 e sto usando Django 2.2.6 e Python 3.7

Nota: utilizzo DJANGO REST FRAMEWORK , il codice seguente per l'invio di e-mail era in un modello di visualizzazione nel mioviews.py

Quindi dopo aver letto più belle risposte, questo è quello che ho fatto.

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)

Importante! Quindi, come si render_to_stringarriva receipt_email.txte receipt_email.html? Nel mio settings.py, ho TEMPLATESe sotto è come appare

Presta attenzione DIRS, c'è questa linea os.path.join(BASE_DIR, 'templates', 'email_templates') . Questa linea è ciò che rende accessibili i miei modelli. Nel mio project_dir, ho una cartella chiamata templatese una sottodirectory chiamata email_templatescosì project_dir->templates->email_templates. I miei modelli receipt_email.txte receipt_email.htmlsono nella email_templatessottodirectory.

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

Vorrei solo aggiungere che, il mio recept_email.txtassomiglia a questo;

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

E, il mio receipt_email.htmlassomiglia a questo;

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

0

Ho scritto uno snippet che ti consente di inviare e-mail renderizzate con modelli memorizzati nel database. Un esempio:

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

0

Se si desidera modelli di posta elettronica dinamici per la posta, salvare il contenuto della posta elettronica nelle tabelle del database. Questo è ciò che ho salvato come codice HTML nel 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>

Nelle tue opinioni:

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

Questo invierà al modello HTML dinamico ciò che hai salvato in Db.


0

send_emai()non ha funzionato per me, quindi l'ho usato EmailMessage qui nei documenti di Django .

Ho incluso due versioni di Anser:

  1. Solo con la versione e-mail html
  2. Con e-mail di testo semplice e versioni e-mail 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()

Se desideri includere una versione in testo semplice della tua e-mail, modifica quanto sopra in questo modo:

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

Le mie versioni semplici e html si presentano così: 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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.