Pergunta

I want to substitute build-in send_mail function, that works only with plain-text emails, with my own smart send_mail function, that generates both html and plain-text versions automatically. Everything works as expected for my own emails, defined in my own application. I can do it in views.py in this fashion:

from django.core import mail
from utils import send_mail as send_html_mail
mail.send_mail = send_html_mail

But the problem still appears with emails of third-side applications. There all imports already completed before my code with monkey-patching of send_mail function.

Is it possible to override this function before all imports of all django applications? Or may be there is another solution of this issue. I really don't want to patch code with sending emails of these third-party applications. It's much easy just to put html-template.

Foi útil?

Solução 4

I wrote application for quickly switching from plain-text emails to html based emails for all project's applications. It will work without modifying any Django code or code of other third-part applications.

Check it out here: https://github.com/ramusus/django-email-html

Outras dicas

From Django docs: http://docs.djangoproject.com/en/dev/topics/email/#sending-alternative-content-types

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

No send_mail() required.

Sounds like a lot of people are misreading your question.

To override the import from third party modules, overwriting sys.modules['django.core.mail'] might work.

It works in simple tests, but it's not thoroughly tested.

import sys
from django.core import mail 

def my_send_mail(*args, **kwargs):
    print "Sent!11"

mail.send_mail = my_send_mail
sys.modules['django.core.mail'] = mail


from django.core.mail import send_mail
send_mail('blah')
# output: Sent!11

For example, if I put that code in my settings.py and launch the manage.py shell and import send_mail, I get my version.

My shell session

In [1]: from django.core.mail import send_mail
In [2]: send_mail()
Sent!11

Disclaimer
I've never done anything like this and don't know if there are any funky ramifications.

How about changing django a little and substituting original code with your own function? You can actually just add your own function and don't remove the old, as the last definition will be imported. I don't like such solutions, because I don't like patching external libraries (you need to remember about patching them again when you upgrade), but this would solve your problem quickly.

In Django 1.7 added extra attribute html_message to send_mail() function to send html message.

https://docs.djangoproject.com/en/1.8/topics/email/#send-mail

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top