September 24, 2008

Sending HTML emails to multiple subscribers via Django

Filed under: django — Tags: , , — Bart @ 4:38 pm

(Update: Please note I do not advocate spamming or any tomfoolery at all. See the comments below for some great discussion on sending out bulk emails correctly via setting up your DNS and SMTP Servers correctly)

Today I had the fun little project of building a very simple message sending system in Django that would fetch emails from a database of subscribers, check for the latest message in the queue, and send it out.

Sounds easy? Well yes, it is. But there’s a few things that Django can do to make the email sending much smarter.

First off, sending HTML emails in Django requires you to set an alternate content type. This is easily done using the django.core.mail.EmailMultiAlternatives class which is very similar to using the EmailMessage class but provides a few more options for HTML emails. Here’s a simple code snippet using this:

subject, from_email, to = ‘Say Hello to our new website!’, ’service@mycompany.com’, 
                                          ’someuser@gmail.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()

This very simple example sends an email to someuser@gmail.com with an alternative minetype for html. What this allows is for people who have HTML-enabled email clients they receive the full on HTML view, while people who are stuck with text based emails simply get a nice clean cut text email instead of html garble.

Django offers another class that makes it extremely efficient on sending emails to mass amounts of users. Now there is little documentation on this so I do not know how far you can stretch this (hundreds, or thousands of emails?) but it has worked well for me.

It is the SMTPConnection class also found in django.core.mail. With it, you can store all your EmailMessage()’s or your EmailMultiAlternatives()’s in a list of data and then send them all using one single connection instead of re-connecting each time. This is similar to using send_mass_mail but that is just a thin wrapper that does not support alternative mimetypes like HTML and other goodies. Here’s a simple code snipper:

 

# If you do not provide any connection settings, it uses the default found in settings.py
connection = SMTPConnection()
connection.send_messages(messages) # messages can be a list of EmailMessage objects

So those are two great classes that make email sending just that much simpler in Django. How would you put this all together? Here’s a simple example script that fetches an email message from a model named Message, some subscribers, and then sends out a mass email to them. In this script, Message is a model that holds the actual HTML email and Subscribers is a list of our subscribers. To keep it simple, we only work with their email

from django.core.mail import  EmailMultiAlternatives, SMTPConnection
from mysite.email_app.models import Subscriber, Message
message = Message.objects.order_by('-id')[:1][0] # Fetch latest message in our list of emails
if not message.is_sent:
      subscribers = Subscriber.objects.all()
      emails_to_send = []
      for s in subscribers:
           msg = EmailMultiAlternatives(message.subject, message.body_text, 'myemail@foo.com', 
                                                                     [s.email])
           # Attach the html version of our email to the email
           msg.attach_alternative(message.body_html, "text/html")
           emails_to_send.append( msg )
      # Setup a single SMTPConnection to send all emails instead of re-connecting each time
      connection = SMTPConnection()
      connection.send_messages(emails_to_send)
      message.is_sent = True
      message.save()

That’s just a very simple example and if you know any ounce of Django I hope you can understand it. You could also add something like a send_time to your Message model and then run a daily cron script to check if an email has to go out to your user base. This is basically the setup I have now at the office and it works great.

 

For a full reference, see: Django | Sending e-amil

 

 

 

 

February 8, 2008

Why Django and Python just won my heart

Filed under: programming, python — Tags: , , , — Bart @ 9:21 pm

As of yesterday, I completed my first Django app. Django is a high-level Python web framework designed for rapid development and quick deployment. Did it deliver? Oh god yes.

Coming into this project, my Python skill was hurting. I had not written a real Python application in a few months and before that, I never had a solid grasp of Python to begin with.

So why did Django make me so happy? First off, in a weeks time, a few hours here and there throughout the week, I managed to: Create a fully functional website with ability to add new posts (Along with card specials, release schedules), polls, a simple member registration, and of course a fully functional admin panel that made it easy for my client to add content to their site. I did this all, with no knowledge of Django before hand!

Some highlights of the Django framework:

  • Installing and configuring Django takes about 15 minutes for a newbie. Download the project from SVN (At this point in its development, this is a good idea), untar it, modify some settings and you’re golden
  • Setting up a project is simple with manage.py, the core of Django’s management capabilities. Setup the project, then setup your first app, and within a minute you are ready to fly.
  • For each application, Django creates a views.py, models.py and urls.py. These three files are the core of your program and it makes it super easy. Define your table and any core functions in models.py for that application (Ie: News Posts app), setup the templates you will pump out in views.py, and urls.py is if you want to get down and dirty with url structures.
  • syncdb and django admin are amazing. I cannot stress this enough. Define your models in models.py, run syncdb and all your tables (including multi-relational ones!), primary keys, etc are ALL CREATED! I love it!
  • Once all your tables are created, login to Django admin and you have full functionality to play with all your data. If you setup a DateTime variable in your model, the admin displays that field with a nice Javascript calendar popup.
  • Python is a sexy language that you will love the more you use it. When I first began playing with Python it was ok, kind of cool, but nothing amazing. The more I learn about Python, the more I love it. I’ve used PHP for years and I honestly can’t bare to look at it after working with Python in the past few months.

There’s a reason why companies like Google and NASA have adopted some of their technologies around Python, because it is code sex. Yes, I like that term.

To try out Django, check out these resources:

  • The official Django project site has a great documentation and beginners tutorial.
  • The B-List has some good code example and tutorials for Python/Django.
  • #django on irc.freenode.net has some great people. Magus- is a total dick, but very helpful ;)
Powered By WordPress