35

Getting Django to send an email is nicely explained here using standard settings as shown below.

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "mail.mysmtpserver.somewhere"
#EMAIL_PORT
EMAIL_HOST_USER = "my@login"
EMAIL_HOST_PASSWORD = "mypassword"
#EMAIL_USE_TLS = True

Then using django.core.mail.EmailMessage to send it of.

How ever, what if you are running multiple sites and need each of these to send email through their own SMTP server (or just different login in the same SMTP server)?

Searching for a EmailBackend like this or a way to do it with the current backend did not produce any satisfactory results.

Tommy Strand
  • 1,384
  • 2
  • 14
  • 15

7 Answers7

46

If you want to override the provided settings you can just create your own connection and provide it to send_email or EmailMessage

from django.core.mail import get_connection, send_mail
from django.core.mail.message import EmailMessage
# TODO: Insert clever settings mechanism
my_host = ''
my_port = 587
my_username = ''
my_password = ''
my_use_tls = True
connection = get_connection(host=my_host, 
                            port=my_port, 
                            username=my_username, 
                            password=my_password, 
                            use_tls=my_use_tls) 

send_mail('diditwork?', 'test message', 'from_email', ['to'], connection=connection)
# or
EmailMessage('diditwork?', 'test message', 'from_email', ['to'], connection=connection).send(fail_silently=False)

Update: Make sure to close the connection after use, @michel.iamit answer points to code showing the connection is cached for smpt. @dhackner answer shows how to automatically close a connection using with statement.

vishes_shell
  • 22,409
  • 6
  • 71
  • 81
Daniel Backman
  • 5,121
  • 1
  • 32
  • 37
  • something i found while using this solution is Celery/Kombu *cant pickle the EmailMessage* when you pass a connection object, so I think this method might not work when scheduling emails for future delivery – David Lam Dec 09 '14 at 06:08
  • 3
    You should probably never try to pickle a "connection" as it might not be available in the future task. It should work if just the data is passed to the future task and EmailMessage is constructed when task executes... – Daniel Backman Dec 09 '14 at 08:45
  • can we use ssl ? – Ahmed Yasin Mar 02 '22 at 15:31
22

I would slightly modify Daniel Backman's answer to use a context manager like in the docs. It will take care of open() and close() calls by itself.

from django.core.mail import get_connection, send_mail
from django.core.mail.message import EmailMessage

with get_connection(
    host=my_host, 
    port=my_port, 
    username=my_username, 
    password=my_password, 
    use_tls=my_use_tls
) as connection:
    EmailMessage(subject1, body1, from1, [to1],
                 connection=connection).send()

https://docs.djangoproject.com/en/dev/topics/email/#email-backends

Daniel Backman
  • 5,121
  • 1
  • 32
  • 37
dhackner
  • 2,942
  • 2
  • 20
  • 23
2

Sorry, can't comment directly on the rest of the answers, not enough rep.

Just one addition:

connection = get_connection(host=my_host, 
                                port=my_port, 
                                username=my_username, 
                                password=my_password, 
                                user_tls=my_use_tls)

should be

connection = get_connection(host=my_host, 
                                port=my_port, 
                                username=my_username, 
                                password=my_password, 
                                use_tls=my_use_tls)

It's only a problem if you are NOT using TLS (and you should), since it defaults to True.

paketep
  • 53
  • 6
1

It might be an idea to have a look at the email backend of django, and create a customised one.

here is the code: https://github.com/django/django/blob/master/django/core/mail/backends/smtp.py

This example shows how you can make a custom one (this one uses SMTP_SSL in stead of SMTP):

https://gist.github.com/jsummerfield/1486891

and I forked that one, to combine both (so I can use one backend for different sites with different mail settings):

https://gist.github.com/iamit/5415771

Not sure if that will work, but as you see all of the codes above returns on opening the connection if there is already a connection... So maybe there is the start for your solution.... don't do that, close the open connection and reopen with different settings... (not sure if that works).

michel.iamit
  • 5,788
  • 9
  • 55
  • 74
0

use a different configuration for each site.

one way is to have, in addition to your settings.py, a settings_SITENAME.py for each site. these files will have the custom mail server settings. each site will have settings_local.py be a symlink to it's own custom settings file

then put this stanza at the bottom of settings.py:

try:                                                                                                                                                                            
    from settings_local import *                                                                                                                                                
except ImportError:                                                                                                                                                             
    pass  

now you have per-site custom settings

scytale
  • 12,346
  • 3
  • 32
  • 46
  • Any way todo this with one settings file? I need one Django instance to send using multiple SMTP servers. – Cloud Artisans Nov 29 '12 at 20:10
  • 1
    don't use the django email backend - use the lower level python libraries - http://docs.python.org/2/library/email-examples.html – scytale Nov 30 '12 at 07:58
  • Please don't, lol. What if settings_local needs to modify an existing setting? – DylanYoung Jan 21 '21 at 19:36
  • @CloudArtisans Create a function like send_email, but pull from your custom email settings instead of the ones hardcoded by django. If you have a lot of them, you could alias them in a dictionary (like how django handles DBs) and pass the alias into your send_mail function. The only thing you won't be able to do this way is alter the credentials for the emails that django sends by default (probably need to monkeypatch for that or add a custom mail backend if django allows that). – DylanYoung Jan 21 '21 at 19:39
0

In case it helps someone. If you need to send emails from different accounts within the same HOST (the one defined in the settings.py) you can make it simpler without having to create a new connection:

send_mail(subject, message, from_email, recipient_list, auth_user="my_secondary_email@example.com", auth_password="mypassword")
LaCharcaSoftware
  • 1,075
  • 1
  • 5
  • 13
0

I created a lib for this cases...

https://pypi.org/project/django-multi-mail-backend/

allow multiples backends (including smtp servers)