Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Created March 2, 2012 16:03
Show Gist options
  • Select an option

  • Save amcgregor/1959335 to your computer and use it in GitHub Desktop.

Select an option

Save amcgregor/1959335 to your computer and use it in GitHub Desktop.
# encoding: utf-8
"""A simple mail delivery API.
Install in a venv:
$ curl get.web-core.org | python - MailAPI
$ cd MailAPI; . bin/activate
$ pip install marrow.mailer, mako
"""
import time
import web.core
try:
from simplejson import loads
except ImportError:
from json import loads
from marrow.mailer import Mailer, Message
from marrow.templating.core import Engines
log = __import__('logging').getLogger(__name__)
render = Engines(default='mako', cache=50, container=None)
class RootController(web.core.Controller):
"""A handy HTTP API for mail delivery.
Configuration is loaded from 'config.json'.
mailer -- a dictionary containing the Marrow Mailer configuration
defaults -- a dictionary of default values for Message objects
headers -- additional headers to add to the messages
reply, sender, return, unsubscribe -- a string template for appropriate e-mail addresses
String templates allow you to use {} to insert the target's identifier.
To use, POST to /deliver with the following values:
targets -- a list of targets (comma-separated) each combining an identifier and address (colon-separated)
subject -- the subject of the mailing
plain -- the template to use for the plain text version
rich -- the template to use for the rich text version
**kw -- unlimited key/value pairs which get passed to the template
Additionally, the template will have access to the target's Address object (name/e-mail) and identifier.
Returns a JSON dictionary of:
success -- identifiers successfully delivered to
failure -- identifiers that could not be delivered to
time -- the amount of time delivery took
"""
def __init__(self):
self.config = loads(open('config.json', 'ru'))
self.mailer = Mailer(self.config['mailer'])
self.mailer.start()
def deliver(self, targets, subject, plain, rich, **data):
if isinstance(targets, basestring):
targets = targets.split(',')
success = []
failure = []
start = time.time()
for target in targets:
if isinstance(target, basestring):
target = target.split(':')
identifier, address = target
try:
message = self.mailer.new(**self.config['defaults'])
message.subject = subject
message.to = address
message.reply = self.config['reply'].format(identifier)
message.sender = self.config['sender'].format(identifier)
message.headers.append(('Precedence', 'bulk'))
message.headers.append(('List-Unsubscribe', self.config['unsubscribe'].format(identifier)))
message.headers.append(('Return-Path', self.config['return'].format(identifier)))
# X-Copyright
data = dict(data)
data['identifier'] = identifier
data['target'] = message.to
data['subject'] = subject
mime, message.plain = render(plain, data)
mime, message.rich = render(rich, data)
message.send()
except:
log.exception("Unable to deliver to %s.", identifier)
failure.append(identifier)
else:
success.append(identifier)
end = time.time()
return 'json:', dict(success=success, failure=failure, time=end - start)
if __name__ == '__main__':
from paste import httpserver
app = web.core.Application.factory(root=RootController, debug=False)
httpserver.serve(app, host='127.0.0.1', port='8080')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment