Using RPC over email?
Can someone tell me how they have done this in some form, be it XML-RPC, SOAP, bespoke etc. Not too worried on the packet format.
I am interested in 开发者_Go百科doing some sort of RPC over email, setting up a program to receive commands via email from another application(s) or even from users on a subscription list. Basically the idea is you give someone the email address and then send messages to active commands, and the response is back in email. A good example of where I would be taking this is maybe a chess program, where time is irrelevant but delivery is everything and sequential ordering of moves is a given.
I would be most interested in the experiences of others, especially with the nature of email and any idiosyncratic behaviour that I should be aware of.
I have quite a bit of experience of RPC over Message Queues and asynchronous delivery, but would like to come up with a solution where I shift the communications on to hotmail or gmail, freeing up my servers and the headache of the asynchronous intercoms.
I'm already doing this with Google AppEngine and Python. It's really simple.
In your app.yaml
file you need to setup that you will using the email service and you file to manage them:
application: appname
version: 1
runtime: python
api_version: 1
handlers:
- url: /_ah/mail/.+
script: mail.py
login: admin
inbound_services:
- mail
Then create a mail.py
file with something like this:
#!/usr/bin/env python
import rfc822
import logging
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from google.appengine.ext.webapp.util import run_wsgi_app
class LogSenderHandler(InboundMailHandler):
def receive(self, message):
service_name, service_email = rfc822.parseaddr(message.to)
service_request = service_email.split('@').pop(0)
sender_name, sender_email = rfc822.parseaddr(message.sender)
logging.info('Service `%s` activated by `%s`.' % (service_request, sender_email))
if __name__ == '__main__':
application = webapp.WSGIApplication(
[LogSenderHandler.mapping()])
run_wsgi_app(application)
All you need to do is send an email to servicename@appname.appspotmail.com
. Voila!
You could use fetchmail like this:
#!/bin/bash
while sleep 1
do
fetchmail --idle --mda python program_that_accepts_email_with_headers_on_stdin.py
done
Then Your program can do various things from querying database, through using some http services, to sending an email to someone. The way it works is first it sleeps for a second, then it checks the email box according to settings You need to place in ~/.fetchmailrc (read man fetchmail
for info on how to do that). If it finds any email, it invokes Your program, if not and the loop goes back to the start point. If it doesn't find any emails, it waits until an email will arrive (or the mail server will restart).
The bottom line is that if the said system is not heavily loaded, it will almost instantly react to emails (usually You send an email with command, wait 3 seconds and You have a reply in Your inbox).
NOTE: halting (--idle
) only works with IMAP servers. With pop servers You could do the same but sleep 10 seconds instead of 1. Sleeping for 1 second is good because Your program may be ultra-fast and may create an infinite loop with other program (f.e. mailer daemon saying someone is on vacation) and usually it would be good to at least limit their looping frenzy to 1 email/second. I learned it the hard way :) Sleeping will be bad if You would like to process more than 1 email/second. If so, switch sleep 1
to true
.
精彩评论