rendered paste body#!/usr/bin/perl -w
$|++;
# email to sms gateways:
#
# AT&T: phonenumber@txt.att.net
# ALLTEL: phonenumber@message.alltel.com
# Nextel: phonenumber@messaging.nextel.com
# Sprint: phonenumber@messaging.sprintpcs.com
# Verizon: phonenumber@vtext.com
# Cingular: phonenumber@cingularme.com
# T-Mobile: phonenumber@tmomail.net
# Metrocall: phonenumber@page.metrocall.com
# Virgin Mobile: phonenumber@vmobl.com
#
# from http://www.tech-recipes.com/rx/939/sms_email_cingular_nextel_sprint_tmobile_verizon_virgin/
# and http://www.accutracking.com/sms-email.html
#
# See http://en.wikipedia.org/wiki/List_of_carriers_providing_Email_or_Web_to_SMS for a more complete list.
use strict;
use lib '/usr/local/apache/libs';
use CGI::Carp 'fatalsToBrowser';
use DBI;
use Data::Dumper;
use Database::Hosts;
use Digest::MD5 'md5_hex';
use Net::SMTP;
my $notes;
#my $pid = -1;
#my $pid = fork;
#if ( ! defined $pid || $pid != 0 ) {
#
error_page();
# exit if $pid != 0;
# $notes .= "Unable to fork.\n";
#
#}
# wait how many seconds before sending another notification
my $wait = 15 * 60;
my $dbh = Database::Hosts::connect( 'junk', 'server_errors' );
my $email_sql = qq{SELECT name, address, type FROM contact};
my ( @email, @email2sms );
for my $contact ( @{ $dbh->selectall_arrayref( $email_sql, { 'Slice' => {} } ) } ) {
next unless $contact->{ 'type' } =~ /^email(?:2sms)?$/;
next unless $contact->{ 'name' } =~ /alan|joseph/i;
push @{ $contact->{ 'type' } eq 'email' ? \@email : \@email2sms },
sprintf '"%s" <%s>', @{ $contact }{qw( name address )};
}
#chomp( my $hostname = $> == 0 ? `su nobody -c "hostname --fqdn"` : `hostname --fqdn` );
chomp( my $hostname = `hostname --fqdn` );
$hostname ||= 'NoHostName';
my $error = merge( qq{<<STATUS>> <<ERROR_NOTES>>} );
my $hostip = $ENV{ 'REDIRECT_SERVER_ADDR' } || 'NoHostIP';
my $script = $ENV{ 'REDIRECT_SCRIPT_FILENAME' } || 'NoScript';
my $ssl = exists $ENV{ 'REDIRECT_HTTPS' } && $ENV{ 'REDIRECT_HTTPS' } eq 'on' ? 's' : '';
my $url = merge( qq{http${ssl}://<<HTTP_HOST>><<REQUEST_URI>>} );
my $md5 = md5_hex( merge( "${hostname}${hostip}<<SERVER_NAME>>${script}" ) );
exit if md5_seen();
my $dump = do { my $d = Data::Dumper->new( [ \%ENV ], [ 'ENV' ] ) ; $d->Sortkeys( 1 ) ; $d->Dump };
my $sms = merge( qq{$url
$hostname $hostip
$script
$error});
$sms .= "\n$notes" if $notes;
my $email = merge( qq{ URL: $url
Host: $hostname $hostip
Script: $script
Error: $error});
$email .= "\nNotes: $notes" if $notes;
$email .= "\nEnvironment Dump:\n$dump";
notify( \@email2sms, $sms ); # Send sms
notify( \@email, $email, 1 ); # Send email
# End of line.
sub error_page {
print merge( qq{Content-type: text/html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or misconfiguration and was
unable to complete your request.</p>
<p>More information about this error may be available in the server error
log.</p>
<hr>
</body>
</html>
});
}
sub merge {
no warnings 'uninitialized';
my $string = shift;
$string =~ s/<<([^>]*)>>/$ENV{ "REDIRECT_$1" }/g;
return $string;
}
sub md5_seen {
# Has this hash been seen yet? or has it been sent in the last 15 minutes?
# If yes return 1 otherwise return ''
my $seen_sql = qq{
SELECT count, UNIX_TIMESTAMP( touched ) AS touched, UNIX_TIMESTAMP( NOW() ) as now
FROM 500_errors WHERE md5 = ?
};
my ( $count, $seen, $now ) = $dbh->selectrow_array( $seen_sql, {}, $md5 );
if ( $dbh->err ) {
$notes .= sprintf "%s failed: %s\n", $seen_sql, $dbh->errstr;
return;
};
if ( ! $seen ) {
$notes .= "First time this error has been seen.\n";
my $insert_sql = qq{
INSERT INTO 500_errors ( md5, url, hostname, hostip, script, error )
VALUES ( ?, ?, ?, ?, ?, ? )
};
$dbh->do( $insert_sql, {}, $md5, $url, $hostname, $hostip, $script, $error )
or $notes .= sprintf "%s failed: %s\n", $insert_sql, $dbh->errstr;
return;
} elsif ( $now - $seen > $wait ) {
$notes .= sprintf "This error has been occuring for at least %d minutes.\n", ( $count * $wait ) / 60;
my $update_sql = qq{UPDATE 500_errors SET count = count + 1 WHERE md5 = ?};
$dbh->do( $update_sql, {}, $md5 )
or $notes .= sprintf "%s failed: %s\n", $update_sql, $dbh->errstr;
return;
}
return 1;
}
sub notify {
my ( $to, $text, $extra_headers ) = @_;
my $status = $ENV{ 'REDIRECT_STATUS' } || '000';
#my $smtp = Net::SMTP->new( '208.110.142.84', Debug => 1 );
my $smtp = Net::SMTP->new( '208.110.142.84' );
$smtp->mail( "\"$status Error Notifier\" <noreply\@vankomenmedia.com>" );
$smtp->to( @$to, { SkipBad => 1 });
$smtp->data();
if ( $extra_headers ) {
$smtp->datasend( "To: $status Error Notifiee\n" );
$smtp->datasend( "From: $status Error Notifier\n" );
$smtp->datasend( "Subject: $status Error Notification\n" );
} else {
$smtp->datasend( "To: $status Err\n" );
}
$smtp->datasend( "\n" );
$smtp->datasend( $text );
$smtp->dataend();
$smtp->quit;
}