All pastes #1409923 Raw Edit

harleypig

public text v1 · immutable
#1409923 ·published 2009-05-01 22:55 UTC
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;

}