Skip to content

Latest commit

 

History

History
192 lines (125 loc) · 10.4 KB

README.rdoc

File metadata and controls

192 lines (125 loc) · 10.4 KB

Message Gateway

This project aims to provide a way to receive and send SMS messages from an application. SMS aggregators use HTTP endpoints to send and receive messages. This allows you to receive messages from a variety of aggregators and to send those messages back in a synchronous or asynchronous way. It also provides logging and the ability to replay messages from an administrative console. It uses MySQL for logging and Beanstalkd for queueing.

The currently supported aggregators are

Message processing

Receiving messages and sending replies happens over synchronous HTTP. All messages are normalized down to four fields: from, to, source and body. Optionally, there is a carrier_id for aggregators that are carrier aware.

Synchronous processing

Message Gateway supports interacting with these aggregators in an synchronous or asynchronous way. In the synchronous model, here is how a message is processed.

Aggregator                 Message Gateway              Your site
==========                 ===============              =========

Send msg                        
from mobile ====\                  
                 \===>     Normalize
                           Message        =====\        Do something with
                                                \====>  the message. Respond 
                                                        normally

                                                 /===/
                           Denormalize    <=====/
                /=====     message and 
Receive    <===/           reply                                      
response

In this model, replying with non-empty body to the request from the message gateway will send the message back to the client.

Asynchronous processing

In asynchronous processing, the message comes in and uses queues for processing. Here is how it looks:

Aggregator        Q        Message Gateway       Q      Your site
==========                 ===============              =========

Send msg                        
from mobile =====>O                                                        
                  |                                                        
                  |         Normalize   =============> Do something with                                 
Respond w/  <-----O======>  Message                    the message. Respond                                  
200                                              O==== normally            
                                                 |                         
                                                 |                         
                           Denormalize  <========O
Receive     <============  message and   
response                   send to
                           aggregator

In the asynchronous model, a separate sending processor has to be setup, separate from the endpoint for incoming messages. The currently supported asynchronous senders are:

As well, there is another means of sending, SMTP. Many carrier support (as well, all major US carriers) sending messages by email. You can specify SMTP as a message source provided you configure it with a valid SMTP server.

Message Sending

When you add an outbound message sender, Message Gateway assumes that you want to process messages asynchronously.

Outbound message =======> Outbound SMS Sending Endpoint (SmsSendingEndpoint) ====> Beanstalk Queue for later processing

                                        |
                                        |
Appropriate Sender Subclass      < ==== 0

Message Gateway is informed of outbound messages by an HTTP post from your app to the sending interface URL (set up with HttpRouter - see below)

Admin interface

You can configure an admin interface which will give you a high level view of messages processed, and the success or failure of every message. If a message fails, you can attempt to replay it (either to the aggregator or to your site). As well, you can simulate a message from this panel.

Configuration

Configuration right now takes place in a rackup file. Here is an example configuration file with annotation explaining what everything does:

require 'message_gateway'

gateway = MessageGateway.new('my gateway', "http://127.0.0.1:3000/interpret") # This takes a name for display purposes and an endpoint to send messages to.
gateway.beanstalk('127.0.0.1') # This sets the beanstalk host (and port) for use as a queue
gateway.logger = MessageGateway::MessageLogger.new(:adapter => "mysql", :host => "127.0.0.1", :database => "message_gateway", :username => "root", :password => "")
# this configures mysql for use as a logger.

gateway.outbound(:unwired_appeal, '99999') { |out|   # This configures an outbound message sender. The first parameter is the adapter to use
  out.default_from = '99999'                         # and the second parameter is an identifier used to identify it.
  out.event_id     = "1111"                          # Every aggregator has its own configuration parameters. See the rdocs for
  out.password     = "12345678"                      # each adapter for all its options.
}

end_point = gateway.sms_sending_endpoint             # This creates a sending endpoint for initiating sms messages
end_point.default_source = '99999'                   # without having to receive one first.

run HttpRouter.new {                                 # This creates your endpoints:
  add('admin*').to gateway.admin                     # For the admin interface
  post('send').to end_point                          # For the sending interface

  add('sms/incoming.sms').to gateway.inbound(:sync,  '99999').parser(:unwired_appeal) # this creates a receiving endpoint
}                                                                                     # The endpoint using the synchronous processing model and the
                                                                                      # unwired appeal parser.

Once you’ve configured this, you can use thin to run the subsequent rackup file.

Sending messages

Once you’ve set up an SMS sending endpoint, you can send messages to it. Simply post data with the following fields:

  • to – The number you’re sending to

  • body – The contents of the message

  • source – The identifier of the outbound processor to use. This is the name you’ve assigned the source when you set it up. (This is optional, you can configure a default source)

“Post data where?”, one might ask: To the route that calls the SMS sending end point… in the above rackup example, it’s the

post('send').to end_point

line

Recieving messages

Once you’ve set up an inbound endpoint (the HttpRouter block above adds(‘sms/incoming.sms’), as an example), the mobile agreegator will POST to that URL. See the Processor rdocs for more information here.

We’ll call this the “message received application logic callback”, for lack of a better name.

Your “message received application logic callback” will recieve the following parameters:

1. to   - reciever of the SMS message
2. from - sender of the SMS message
3. body - the body of the message

In the “Synchronous processing” section of this document, the flow of this was described, but to put this into a little more perspective:

** The response your "message received application callback" returns will be returned to the Mobile Aggregator.
As such, it should conform to their guidelines about the format of this message. (For example, Twilio
wants an XML-like document returned, and from this document you can send a text message back in reply to your user **

Current limitations

There are some limitations. For one, using a rackup file is a bit awkward for configuration. For another, there is no way to try several aggregators to see which can send a message. As well, there is currently no support for delivery receipts.

Firing up the test suite

You are running the tests before trying any of this, right?

spec/spec_helper.rb defines MessageGateway.default_logger. This object also keeps the database connection information.

By default the test suite uses mysql, with username root and no password, to connect to a database named “message_gateway_test”

Dependancies

Because of the high dependance on EventMachine, Message Gateway assumes your server is an EventMachine compliant server (aka: thin), AND has already started the EventMachine reactor.

Error Handling

If you want, I suggest setting up Airbrake for this app.

In your rackup file, configure Airbrake as the documentation says, then

use Airbrake::Rack

This can go outside the HttpRouter.new block.

This Airbrake middleware will catch errors going into processing. With the Asynchronous processor, this includes breaking the message apart into Message Gateway’s normalized message format. However, sending messages to the message received application callback is not part of this request/response cycle.

Errors from the message received application callback will be logged as an event (thus allowing the incoming SMS message to be replayed).

Contributing on this gem

This gem is managed via Bundler, which has created the skeleton for us in addition to providing Rake tasks related to installing and releasing the gem.

License

This software is distributed under GNU General Public License (www.gnu.org/licenses/gpl.html).