[Prev] Thread [Next]  |  [Prev] Date [Next]

Re: #10355 Add support for email backends Russell Keith-Magee Fri Aug 21 06:02:32 2009

On Fri, Aug 21, 2009 at 5:53 PM, Zachary
Voase<[EMAIL PROTECTED]> wrote:
> Hi Andi,
> On 21 Aug 2009, at 05:34, Andi Albrecht wrote:
>> Hi,
>> I'm interested in working on #10355 "Add support for email backends."
>> IMHO it's an good idea to make the email backend configurable. There
>> are at least two use cases I can think of. The first is to send email
>> with other services than SMTP, like App Engine as noted in the
>> ticket's description. The second is to deliver email asynchronously,
>> like the django-mailer application does already.
> I wholeheartedly agree.
>> The ticket currently needs a design decision, so my question is what
>> the actual concerns to change this are.
>> I would propose the following changes. It's a very simplistic approach
>> that tries to keep the current API as much as possible:
>> Add a new setting EMAIL_BACKEND. A string that can be resolved to a
>> class. Default should be the current SMTP implementation.
>> Provide a base class for mail backends. A mail backend must provide
>> the method send_messages(email_messages) and must return the number of
>> messages sent to provide backward compatibility. The constructor of a
>> mail backend should take at least the keyword argument fail_silently
>> (default: False). What I'm a bit unsure about are additional
>> constructor arguments. Currently the SMTP backend allows in addition
>> host, port, username, password and use_tls. Those are very
>> SMTP-specific, but only username and password are used by the
>> mail.send_mail* APIs. It would be an agreement to allow username and
>> password in addition to fail_silently to not break the send_mail* API.
>> The SMTP backend could accept host, port and use_tls as extra keywords
>> again to provide backward compatibility for code that directly uses
>> SMTPConnection (within Django SMTPConnection is not used outside
>> django.core.mail). I would suggest to rename SMTPConnection to
>> SMTPBackend, but only if this would break too much third-party code as
>> SMTPConnection is mentioned in the docs.
> This I disagree with slightly. My main concern is the single-backend
> architecture; many websites will probably want to use more than one
> method for sending e-mail.

I'm not sure I agree with your assertion of "many"."Some" might be
accurate. "Your" is probably more accurate :-)

I've got many websites in the field, and not one of them has needed
anything more than trivial email handling. We've managed to get to
v1.1 and AppEngine support is the first time that pluggable email
backends have really been raised as an issue.

This is hardly surprising. After all, email is email. You have an SMTP
server, you connect to it, you send your mail. AppEngine is a weird
case in that they provide an email-sending API rather than using SMTP,
but that's an artefact of the platform. Once you have one email
sending capability, I find it hard to believe that most people will
need a second.

I don't doubt that there are applications that will require more than
one mail server, but I'm comfortable calling them edge cases. If you
have highly specialized mail requirements, then it makes sense that
you should have a highly specialized mail server handling.

That said, there isn't really that much difference between the simple
and complex case - it's just a matter of defaults.

Django needs to have a default Email backend, guaranteed available.

EmailMessage.send() uses the 'default' backend - essentially just
calling backend.send_messages([msg])

backend.send_messages() also exists as a direct call.
SMTPConnection().send_messages() is really just a shortcut for
instantiating and using an SMTP connection with the default settings.

You're not compelled to use the default connection though. You could
instantiate multiple instances of different backends, and use them to
call other_backend.send_messages().

I see this working almost exactly as the Cache backend works right
now. There is a base interface for caching. There are several cache
backends; dummy and locmem are handy for testing, but if you're
serious, the only one that gets used is memcached. There is a default
cache instantiated as a result of the CACHE_BACKEND setting. For most
people, this is all you will ever need. However, if you want to
instantiate (and use) multiple caches (e.g., if you want to get really
fancy about cache overflow and expiry policies), you can.

> In addition, if mail backends only need to
> implement one method, why not just have EMAIL_BACKEND refer to a
> callable instead?

Persistence of settings. s1 = Backend(host, port, username password)
can be configured once, then s1 can be reused whenever needed.

> I think a slightly better architecture would be this:
> * Make full use of the existing Django signals framework to send e-
> mail. Have callables which implement 'send_messages()' connect to a
> 'sendmail' signal through the use of a simple decorator or connector.

What exactly is the use case where you need to have the 1-n
cardinality provided by signals? The only use I can think of would be
to have message delivery determined by the message itself - i.e., a
message could be sent by SMTP server 1, SMTP server 2, or the
AppEngine Server, depending on the recipient/content.

If this is the use case, I put it to you that this is an _extreme_
edge case - and one that could be handled using a custom mail backend
that does content-based dispatch - i.e., a mail backend that wraps
other mail backend instances.

Russ Magee %-)

You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [EMAIL PROTECTED]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at