New framework for private custom notifications from emails

An iPhone client for Growl available on the App Store.
nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

New framework for private custom notifications from emails

Postby nzoschke » Sun Mar 07, 2010 7:36 pm

I'm a very happy Prowl customer. Prowl and Google Voice has allowed my to forgo an AT&T SMS plan for a while now. In return, I decided to share my strategy for creating these notifications with the community:

http://github.com/nzoschke/gae-message-utils

There are 3rd party services that offer this functionality, but I am not comfortable giving private credentials or forwarding private emails to a 3rd party I do not trust.

Instead I have discovered that Google App Engine offers a platform that can receive emails, transform their contents, then make Prowl (and more) API calls. This is free, can be set up and run completely privately by yourself, and is infinitely extensible provided you know a bit of Python and regular expressions.

I'd love to get some feedback on this strategy, and find other people interested in setting up an app and giving feedback to improve the code.
Last edited by nzoschke on Sun Mar 07, 2010 7:51 pm, edited 2 times in total.

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications

Postby nzoschke » Sun Mar 07, 2010 7:43 pm

A couple more notes...

This works because appspot can receive an email to `nobody@your-app-id.appspotmail.com` and then POSTs it to a custom Python handler function. This handler parses the sender, to, subject and body and make a remote URL call when it matches all the rules. Since Google Voice sends an email notification for SMS and voicemail, this is a match made in heaven.

I haven't added support yet, but Google App Engine also treats incoming XMPP messages the same way, so this can be a Jabber to Prowl bridge too.

mlcampbe
Harmless
Posts: 14
Joined: Thu Dec 17, 2009 7:19 pm

Re: New framework for private custom notifications from emails

Postby mlcampbe » Wed Mar 10, 2010 1:56 am

I used the code provided to create my own google appspot.com provider. I am only interested in the email to prowl part though and I see that the code has various calls for google voicemail and google SMS messages. What is the proper way to remove this code and make the result generic such that any email recieved at nobody@id.appspotmail.com is forwarded to my prowl api key?

I tried removing some stuff but got confused and it broke the app so it didn't work at all.

Is it possible you can post the files for a generic email-to-prowl app?

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications from emails

Postby nzoschke » Wed Mar 10, 2010 8:34 pm

Sure. Your settings.py file should look something like below. Make sure to fill in your Prowl API key.

This MailRouter has a single route that matches every email and calls the Prowl API with the event set to the email subject, and the description to the email body.

--

Code: Select all

from handlers import MailRouter
from rpc import Prowl

PROWL_API_KEY          = 'SECRET'

class MailRouter(MailRouter):
  def __init__(self):
    # generic email to prowl forwarding
    self.add_route(
      name      = 'Every email to Prowl',
      to        = '.*',
      callback  = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
    )

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications from emails

Postby nzoschke » Wed Mar 10, 2010 8:38 pm

When you get the hang of how it works you can tune this a bit more.

If you change the route argument to `to = 'prowl@'` then only emails forwarded to prowl@your-app-id.appspotmail.com will be forwarded. If you set description=m.body[:100] in the callback, long messages will look better.

But these tweaks are all up to you. Very interested in hearing if you get it working.

mlcampbe
Harmless
Posts: 14
Joined: Thu Dec 17, 2009 7:19 pm

Re: New framework for private custom notifications from emails

Postby mlcampbe » Fri Mar 12, 2010 2:35 pm

Thanks for the update. I'll give it a try.

mlcampbe
Harmless
Posts: 14
Joined: Thu Dec 17, 2009 7:19 pm

Re: New framework for private custom notifications from emails

Postby mlcampbe » Fri Mar 12, 2010 3:03 pm

As I was making changes to try this out I wondered how I would create a "catch-all" route? For example, if create a route that has `to = 'prowl@'`is there a way to forward any other emails to another address? Could I do this:

from handlers import MailRouter
from rpc import Prowl

PROWL_API_KEY = 'SECRET'

class MailRouter(MailRouter):
def __init__(self):
# generic email to prowl forwarding
self.add_route(
name = 'Every email to Prowl',
to = '.*',
callback = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
)
# catch-all to send all other email to secondary address
self.add_route(
name = 'All other email to xxxx@xxxx.com',
to = '.*',
callback = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
)

Does it process the routes in order such that the above would work?

mlcampbe
Harmless
Posts: 14
Joined: Thu Dec 17, 2009 7:19 pm

Re: New framework for private custom notifications from emails

Postby mlcampbe » Fri Mar 12, 2010 3:36 pm

Using the original settings.py you posted I changed it with your suggestions for customization. I currently have:

Code: Select all

from handlers import MailRouter
from rpc import Prowl

PROWL_API_KEY          = 'SECRET'

class MailRouter(MailRouter):
  def __init__(self):
    # generic email to prowl forwarding
    self.add_route(
      name      = 'Every email to Prowl',
      to        = 'prowl@',
      callback  = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
    )


This works for me just fine. However, I then tried to add the body changes such as:

callback = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body[.100])

this causes an error. In the appengine log files I see this:

Code: Select all

'EncodedPayload' object is unsubscriptable
Traceback (most recent call last):
  File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 509, in __call__
    handler.post(*groups)
  File "/base/python_lib/versions/1/google/appengine/ext/webapp/mail_handlers.py", line 58, in post
    self.receive(mail.InboundEmailMessage(self.request.body))
  File "/base/data/home/apps/mlc-prowl/1.340485430267560149/handlers.py", line 32, in receive
    route['callback'](inbound_message)
  File "/base/data/home/apps/mlc-prowl/1.340485430267560149/settings.py", line 12, in <lambda>
    callback  = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body[:100])
TypeError: 'EncodedPayload' object is unsubscriptable


Did I do something wrong? What does the [:100] do differently in the formatting?

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications from emails

Postby nzoschke » Mon Mar 15, 2010 3:32 pm

It does process the routes in order. So add a route with to='prowl@', then a route with '.*', and the second will catch everything the first missed.

I didn't test the body substring enhancement before posting. This should work better (but still not tested):

callback = lambda m: Prowl.add(application='Email', event=m.subject, description=unicode(m.body)[:100])

FYI, the lambda is just a function that is called with a Message object as the argument. Using the Message object can be a bit tricky since it handles multipart messages, attachments, etc. The docs offer more guidance:

http://code.google.com/appengine/docs/p ... gmail.html

ccjensen
Harmless
Posts: 18
Joined: Fri Oct 09, 2009 12:38 pm

Re: New framework for private custom notifications from emails

Postby ccjensen » Wed Mar 17, 2010 10:06 am

Hi,

loving the script :)
One issue is the "from" line in the body always comes out as "nobody" on emails forwarded from gmail. I am using the "Every email to Prowl" mail route settings contents you suggested above. Any ideas? How can I help you help me debug this? :D

Chris

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications from emails

Postby nzoschke » Fri Mar 19, 2010 11:56 pm

Ah yes, that's an oddity of the Google App Engine email parsing. I was regexing out that part of the body in the GVSMS parser, but that's no longer necessary if you pull the latest code from my github.

NOTE: I've changed the classes around (MailRouter renamed to MessageRouter) since I've added experimental XMPP support. Your settings.py should now look like this:

Code: Select all

import handlers
from rpc import Prowl

PROWL_API_KEY          = 'SECRET'

class MessageRouter(handlers.MessageRouter):
  def __init__(self):
    # generic email to prowl forwarding
    self.add_route(
      name      = 'Every email to Prowl',
      to        = 'prowl@',
      callback  = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
    )

ccjensen
Harmless
Posts: 18
Joined: Fri Oct 09, 2009 12:38 pm

Re: New framework for private custom notifications from emails

Postby ccjensen » Sat Mar 20, 2010 10:25 am

Found a "bug". If the subject in the email is empty, the script fails with the following exception:

Code: Select all

'InboundEmailMessage' object has no attribute 'subject'
Traceback (most recent call last):
  File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 509, in __call__
    handler.post(*groups)
  File "/base/python_lib/versions/1/google/appengine/ext/webapp/mail_handlers.py", line 58, in post
    self.receive(mail.InboundEmailMessage(self.request.body))
  File "/base/data/home/apps/appname/1.340531665416149545/handlers.py", line 32, in receive
    route['callback'](inbound_message)
  File "/base/data/home/apps/appname/1.340531665416149545/settings.py", line 12, in <lambda>
    callback  = lambda m: Prowl.add(application='Email', event=m.subject, description=m.body)
AttributeError: 'InboundEmailMessage' object has no attribute 'subject'


My friends and I often use gmail for "texting" each other, and just skip the subject. Perhaps it could be checked if empty, and replace by "<No subject>" or something?
Thanks for making the script available to the rest of us, I am enjoying the peace of mind of not having to forward my emails to someone else to get them prowl'd to me :)

nzoschke
Harmless
Posts: 9
Joined: Sun Mar 07, 2010 7:18 pm

Re: New framework for private custom notifications from emails

Postby nzoschke » Mon Mar 22, 2010 4:41 pm

Pull the latest code. The missing subject bug should be fixed.


Return to “Prowl”

Who is online

Users browsing this forum: No registered users