Skip to content

Instantly share code, notes, and snippets.

@ogarrett
Created October 9, 2013 13:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ogarrett/6901360 to your computer and use it in GitHub Desktop.
Save ogarrett/6901360 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use warnings;
use strict;
use Getopt::Long;
sub uri_escape( $ );
# Default country code to add to phone numbers that start with
# a 0 so the SMS gateway will accept them.
my $country_code = "+44"; # UK
my $usage = "Usage: sendsms.pl --destination=telno[,telno...] [--eventtype=<eventtype>] [--debug] message";
my( $destination, $eventtype, $help, $debug );
GetOptions(
'help|h|?' => \$help,
'destination=s' => \$destination,
'eventtype=s' => \$eventtype,
'debug=s' => \$debug,
) or die "\nInvalid arguments.\n\n$usage\n";
my $message = shift @ARGV;
if ( !$message || $help ) {
print "\n$usage\n";
exit 0;
}
my @destinations = split ',', $destination;
# Numbers must be in country code format
for( my $i=0; $i < scalar @destinations; $i++ ) {
$destinations[$i] =~ s/^\s+//;
$destinations[$i] =~ s/^0/$country_code/;
die "Invalid destination: ".$destinations[$i] unless $destinations[$i] =~ /^\+\d+/;
}
# Join the numbers back up for the SMS Gateway
$destination = join ',', @destinations;
# Create the content of the SMS message
my @alert = split "\t", $message;
if( scalar @alert > 2 ) {
# Looks like a ZXTM event message - format it...
# Message format:
# Event Type:
# INFO:
# section/object
# primary tag
# additional tags
#
# message
my $alerttext = pop @alert;
# Get the error level
$message = " ".(shift @alert).":\n";
# Get the other information - the section,
# primary tag and additional tags. This could
# be improved to only include information that
# is useful to see in a text message for each
# event that can trigger this program to be run.
foreach my $object( @alert ) {
$message .= " $object\n";
}
# Add the description of the event
$message .= "\n$alerttext";
}
# Add the event type that triggered this program to the message.
$message = $eventtype.": ".$message if $eventtype;
# The URL of the SMS Gateway.
my $url = "http://ws.textanywhere.net/HTTPRX/SendSMSEx.aspx";
# Parameters to send to the gateway...
my %params = ( Client_ID => "AB1234567",
Client_Pass => "password",
Client_Ref => "my_company",
Billing_Ref => "zxtm",
Connection => $debug ? 1 : 2,
Originator => "ZXTM",
OType => 1,
DestinationEx => $destination,
Body => "$message",
SMS_Type => 0,
Reply_Type => 0
);
my $body = "";
# URL encode the parameters
foreach my $param( keys %params ) {
$body .= "&" if $body;
$body .= uri_escape($param)."=".uri_escape($params{$param});
}
# Send the request
my $httpclient = $ENV{ZEUSHOME}."/admin/bin/httpclient";
open FH, "echo '$body' | $httpclient -m POST $url |" or die "Could not execute httpclient: $!";
# Get the response
my $responseline = <FH>;
if( !$responseline ) {
die "SMS Send failed: Could not execute $httpclient or no response received from remote server";
}
my $responsecode = $1 if $responseline =~ /^HTTP\/1\.1 (\d+)/;
if( $responsecode && $responsecode == 200 ) {
# Gateway successfully receieved the request...
my %responses = (
1 => "SMS Sent",
2 => "Authentication failed: Account not found",
22 => "Authentication failed: Account is currently suspended",
3 => "SMS failed",
31 => "SMS failed: Insufficient message credits on your account",
311 => "SMS failed: This Connection does not exist",
32 => "SMS failed: Originator format not recognised",
321 => "SMS failed: OType invalid",
33 => "SMS failed: Destination(s) format not recognised",
34 => "SMS failed: Reply_Type invalid or Reply_Data empty",
35 => "SMS failed: Client_Ref too long or empty (maximum 50 characters)",
36 => "SMS failed: Billing_Ref too long or empty (maximum 50 characters)",
37 => "SMS failed: Body too long or empty (maximum 160 characters)",
38 => "SMS failed: Wrong message type",
39 => "SMS failed: Wrong message encoding"
);
# Skip the headers
while( <FH> ) {
last if /^\r\n/;
}
my $codes_received = 0;
# We're at the body data...
while( <FH> ) {
# Get the return codes for each destination
my @returncodes = split ',', $_;
foreach my $returncode( @returncodes ) {
my( $num, $code ) = split ':', $returncode;
next unless $num && $code;
$codes_received++;
if( $code == 1 ) {
# Message sent OK
print "$num: SMS Sent\n";
next;
}
# Gateway could not send this message - look up the error code
# in the table above to get an indication of why it failed.
warn "$num: ". (exists $responses{$code} ? $responses{$code} : "SMS failed - unknown error") ."\n";
}
}
# Extra check to make sure the gateway tried all the numbers we sent it.
warn "SMS Gateway did not send a response code for all numbers.\n" if $codes_received < scalar @destinations;
} else {
# Gateway returned a non-200 response
warn "Failed to send SMS message".(scalar @destinations > 1 ? "s" : ""). ".\n";
warn "SMS Gateway returned response code $responsecode\n" if $responsecode;
}
close FH;
exit 0;
### END ###
sub uri_escape( $ )
{
my( $str ) = @_;
$str =~ s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
return $str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment