Introduction

While working on Informeer I have been using a small Perl application to simplify notification management. In fact the application is so simple that I decided to upload it to the wiki in the hope that it may inspire others.

This tutorial provides an example of using the Perl RPC-XML module to create your own web based API that you can use to centralise your e-mail notifications.

xmlrpctutorial.png

Requirements

Prerequisites

Before we get started you are going to need a working Perl installation and the RPC-XML Perl module. Do not worry if your version of Perl is not greater than 5.8, the scripts should work with older versions. If you are wondering what version of Perl you are running just enter the following command at your commandline / shell prompt:

perl -v

If that command fails to return anything useful you will need to download and install the Perl runtime using the link above.

Once you have a working Perl installation you will need to download a few perl modules to make creating your own RPC client/server as simple as a few lines of Perl.

For this tutorial you are going to need the following modules installed:

If you are new to Perl and CPAN and want to know how to install those modules I recommend you take a look at the perlmodinstall guide over at the perldoc site.

The Server

The server script will run as a Daemon and listen for notifications.

The first step will be to import any modules we wish to use, most importantly RPC::XML which you should have installed. I have also imported a couple of Email modules so that I can mail any notifications with minimal code.

use Email::Send;
use Email::Simple;
use Email::Simple::Creator;
use RPC::XML;
use RPC::XML::Server;

Now that we have imported the modules it is time to configure the Daemon to listen on port 8080. You are free to use any port you like (You'll need root privileges for anything lower than 1024 on Unix) and with a little configuration you could even use Apache to handle your requests, however for the purpose of this guide we will be running as a Daemon keeps things simple.

my $daemon = RPC::XML::Server->new(port => "8080");

Ok so now we need to define the methods that we will expose to remote clients. Here we are adding a single method called sendmail.

The name parameter supplied to the add_method provides an identifier for remote clients to call. We use the reverse domain notation (e.g. org.wave2.tutorial.sendmail) to identify the method, this will allow you to run many applications on a single server without the worry of name clashes.

The signature parameter comprises a list of types that may be passed to the method and returned upon completion (the first type being the return value). For the sendmail method we have a single return value type of string and two string parameters that will comprise the email address and notification message.

The code parameter is simply a reference to the method that we execute when a remote client makes the RPC call. We will look at that method next.

print "Adding org.wave2.tutorial.sendmail method...\n";
$daemon->add_method({ name => 'org.wave2.tutorial.sendmail',
      signature => ['string string string'],
      code => \&sendmail });

We have now defined the external interface that clients will use to execute the sendmail method, our next step is to implement that method:

sub sendmail() {
    my $s = shift; # The first parameter is the server object
    my $email_address = shift;
    my $notification = shift;

    my $email = Email::Simple->create(
      header => [
        From    => 'xmlrpc@insertserverhere.org',
        To      => "$email_address",
        Subject => 'Notification Message',
      ],
      body => $notification,
    );

    my $sender = Email::Send->new({mailer => 'SMTP'});
    $sender->mailer_args([Host => 'localhost']);
    my $result = $sender->send($email);

    return "$result";
};

To keep things simple this method takes the 3 parameters supplied by the client (Server, E-Mail, Notification) and uses the Email::Simple/Email::Send modules to actually produce and send the E-Mail using SMTP. (Other Mailers possible using Email::Send - Click Here for details)

You will need to change the From address to something sensible e.g. no-reply@yourdomain.com and specify the hostname or IP address of your preferred SMTP server.

The final step in our notification Server script is to actually start up the Daemon:

$daemon->server_loop;

This causes the script to start listening on the port we specified and wait for a request to arrive. Simple huh?

The Client

The client script can be written in just 4 lines of code - it's that easy!.

As with the server we need to import a couple of modules to do all the hard work for us:

require RPC::XML;
require RPC::XML::Client;

Once we have the RPC modules imported the next step is create the client object that we will use to remotely execute our sendmail method.

As you can see we pass the URI of our server followed by RPCSERV which is where our server will be listening.

my $client = RPC::XML::Client->new('http://SERVERHOSTNAME:8080/RPCSERV');

Now that we have a client object created we can send a request simply by calling the send_request method of our client object.

As you can see from the following code we pass 3 parameters:

  1. The method identifier we declared in the server. e.g org.wave2.tutorial.sendmail
  2. The E-Mail address to send the notification to.
  3. The Noticiation method.

my $res = $client->send_request('org.wave2.tutorial.sendmail',
    RPC::XML::string->new('foo@bar.com'),
    RPC::XML::string->new('Testing 1.2.3'));

Source Code

Browse Source

What now? - Some suggestions

  • Security - as with any web based application you will want to control who can use your shiny new API. You could start by looking at the Server object passed into every method call to perform simple validation using the peerhost key. You can find more details Here.

  • Why don't you try adding SMS support to the script? There are many interfaces to services like Clickatell that make sending SMS messages a breeze.
  • What about auditing those messages? With a little work you can update your favorite database with each notification / timestamp allowing you to trend your notifications.


CategoryTutorial