diff --git a/mail/IMAPCopySrc.zip b/mail/IMAPCopySrc.zip new file mode 100755 index 0000000..ae1defc Binary files /dev/null and b/mail/IMAPCopySrc.zip differ diff --git a/mail/notify_by_sms2email b/mail/notify_by_sms2email new file mode 100755 index 0000000..32d4f9e --- /dev/null +++ b/mail/notify_by_sms2email @@ -0,0 +1,99 @@ +#!/bin/sh +# +# Sample script to send an SMS email notifcation to SMS2Email's HTTP gateways + +# Username and password associated with SMS2Email account +# Modify these values to match your account credentials if you don't want to +# specify them as command line arguments. +username= +password= + +number= +message="Test message" + + + +# Show usage if necessary +if [ $# -eq 0 ]; then + echo "Usage: $0 -n [number] -m [message] -u [username] -p [password]"; + echo ""; + echo "[number] = SMS number to send message to"; + echo "[message] = Text of message you want to send"; + echo "[username] = Username assocated with SMS2Email account"; + echo "[password] = Password assocated with SMS2Email account"; + echo " Both the username and password options are optional and"; + echo " override the account credentials defined in this script."; + echo ""; + exit 1; +fi + + +# Get command line arguments +while [ "$1" != "" ] ; do + case $1 + in + -n) + # Get the SMS number that we should send message to + number=$2; + shift 2; + ;; + -m) + # Get the message we should send + message=$2; + shift 2; + ;; + -u) + # Get the username + username=$2; + shift 2; + ;; + -p) + # Get the password + password=$2; + shift 2; + ;; + *) + echo "Unknown option: $1" + exit 1; + ;; + esac +done + + +# We haven't sent the message yet +message_sent_ok=0; + +# Try to send an HTTP POST message (try all servers until successful) +for server in gw1 gw11 gw2 gw22; do + + RESPONSE=`curl -s -d username=$username -d password=$password -d to_num=$number -d message="$message" http://$server.sms2email.com/sms/postmsg.php` + + # Curl was able to post okay... + if [ "$?" -eq "0" ]; then + + # Test the response from the SMS2Email server + case $RESPONSE + in + AQSMS-OK) + # Message was queued ok + mesage_sent_ok=1; + echo "Message posted OK to HTTP gateway $server" + exit 0; + ;; + AQSMS*) + # Some kind of fatal error occurred + echo "Fatal error received from HTTP gateway $server: $RESPONSE" + exit 1; + ;; + *) + # No response or invalid response + ;; + esac + + fi + +done + + + + diff --git a/mail/search maillogs/findrecpt.pl b/mail/search maillogs/findrecpt.pl new file mode 100755 index 0000000..7af4929 --- /dev/null +++ b/mail/search maillogs/findrecpt.pl @@ -0,0 +1,132 @@ +#!/usr/bin/perl -w +# +# Name: checkrecpt.pl +# Purpose: Checks a specified postfix maillog for a specified sender +# email address and returns a list of recipients email addresses +# to which email was sent. +# Author: David Miller -- +# Version: 0.04 +# Created: 23 Jul 2002 +# Modified: 24 Jul 2002 -- Optimization of message id array to eliminate +# processing of duplicates. Accepts commandline parameters. +# Modified: 24 Jul 2002 -- Cleanup and optimization of message search loop. +# Modified: 25 Jul 2002 -- Added code to handle 'expired' reporting. +# +# +use strict; + +#-------------- +# variables +#-------------- +my $maillog; +my $sender; +my @msgids; + +#--------------------------- +# Main Thread of Execution +#--------------------------- +# process command line arguments +usage() unless ($#ARGV > 0 && $#ARGV < 2); +$sender = $ARGV[0]; +$maillog = $ARGV[1]; + +# check sender name for basically valid form +if (! ($sender =~ /.*@.*/)) { + print "Sender address $sender does not appear valid\n"; + exit 1; +} + +# test for existance of maillog +if(! -r $maillog) { + print "Can not find mail log $maillog\n"; + exit 1; +} + +# get all message ids associated with the sender in temporary array +my @temp; +open(LOG, "<$maillog") || die "Open of $maillog failed\n"; +while() { + if(/from=<$sender>/) { + my @fields = split " "; + $fields[5] =~ s/://; + $temp[$#temp + 1] = $fields[5]; + } +} +close(LOG); + +# optimize list by sorting and removing duplicates +@temp = sort @temp; +foreach my $msg (@temp) { + if($#msgids < 0) { + $msgids[0] = $msg; + } elsif ($msgids[$#msgids] ne $msg) { + $msgids[$#msgids + 1] = $msg; + } +} + +# display count of messages and display header if there are messages +# if no messages we are done +print "Found " . ($#msgids + 1) . " messages from $sender in $maillog\n"; +printMessageHeader() if ($#msgids >= 0) || exit 0; + +# Lookup recipients for each message id +open(LOG, "<$maillog") || die "Open of $maillog failed\n"; +foreach my $msg (@msgids) { + while() { + chomp(); + if(/$msg/ && /smtp/ && /to=,$//; + # status + if($fields[9] =~ /^status=/) { + $status = $fields[9]; + } + $status =~ s/^status=//; + # display the message info + print "$msg $status \t$fields[6]"; + if(($status eq "bounced") || ($status eq "deferred")) { + print " $fields[10]"; + } + print "\n"; + # loop optimization + last if ($status eq "bounced"); + } elsif (/$msg/ && /status=expired/) { # handle exired messages + my $status; + my @fields = split " ", $_, 9; + # sender address for return + $fields[6] =~ s/^from=,$//; + # status field + if($fields[7] =~ /^status=/) { + $status = $fields[7]; + } + $status =~ s/^status=//; + $status =~ s/,$//; + # display the message info + print "$msg $status \t<$fields[8]>\t\t$fields[6]\n"; + last; + } + } + seek LOG, 0, 0; +} +close(LOG); +exit 0; + +#---------------- +# Sub Routines +#---------------- +sub usage +{ + print "usage: $0 sender maillog\n"; + exit 0; +} + +sub printMessageHeader +{ + print "Checking for message recipients\n\n"; + print "Message ID Status \tRecipient\n"; + print "----------------------------------------------------------------\n"; +} diff --git a/mail/search maillogs/findsender.pl b/mail/search maillogs/findsender.pl new file mode 100755 index 0000000..ca1b530 --- /dev/null +++ b/mail/search maillogs/findsender.pl @@ -0,0 +1,157 @@ +#!/usr/bin/perl -w +# +# Name: findsender.pl +# Purpose: Checks a specified postfix maillog for a specified recipient +# email address and returns a list of sender's email addresses +# to which email was sent. +# Author: David Miller -- <> +# Version: 0.01 +# Created: 25 Jul 2002 +# Modified: for additional syslog formats, +# +use strict; + +#-------------- +# variables +#-------------- +my $debug = 0; +my $maillog; +my $recipient; +my @msgids; +my $msg; +my @fields; + +my $qid; # field numbers within $maillog +my $nrcpts; +my $sender; +my $size; + +#--------------------------- +# Main Thread of Execution +#--------------------------- +# process command line arguments +usage() unless (@ARGV == 2); +$recipient = $ARGV[0]; +$maillog = $ARGV[1]; + +# check sender name for basically valid form +if (! ($recipient =~ /.+@.+/)) { + print "Recipient address $recipient does not appear valid\n"; + exit 1; +} +# test for existence of maillog +if(! -r $maillog) { + print "Can not find mail log $maillog\n"; + exit 1; +} + +# get all message ids associated with the recipient in temporary array +my @temp; +open(LOG, "<$maillog") || die "Initial open of $maillog failed\n"; +while() { + # on the fly, determine log line format (where various fields are) + unless (defined $nrcpts) { + if(/from=) { + chomp(); + if(/$msg/ && /from=,$/) { + $fields[$sender] = "<>"; + } else { + $fields[$sender] =~ s/^from=<(.+)>,$/$1/; # keep just the addr + } + $fields[$size] =~ s/^size=(\d+),$/$1/; # keep just the number + $fields[$nrcpts] =~ s/^nrcpts?=(\d+),?$/$1/; # keep just the number + # display the message info + write; + last; + } + } + unless ($msg eq $msgids[-1]) { # in which case we're done + seek LOG, 0, 0 && die "Seek/rewind failed: $!"; + } +} +close(LOG); +exit 0; + +format = +@<<<<<<<<<<<<<< @>>>>>> @> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +$msg, $fields[$size], $fields[$nrcpts], $fields[$sender] +. + +#---------------- +# Sub Routines +#---------------- +sub usage +{ + print "usage: $0 recipient maillog\n"; + exit 0; +} + +sub printMessageHeader +{ + print "Checking for message senders\n\n"; + print "Message ID Size Rcpts Sender\n"; + print "-"x70, "\n"; +} + +sub find_fromline_fields +{ + my @fields = @_; + + for my $i (0 .. $#fields) { + unless (defined $qid) { + if ($fields[$i] =~ /^[A-Za-z\d]+:$/) { # alphanum+colon + $qid = $i; + print if ($debug > 1); + print "DEBUG: \$qid\t= $qid\n" if ($debug); + } + } + if ($fields[$i] =~ /from=/) { + $sender = $i; + print if ($debug > 1); + print "DEBUG: \$sender\t= $sender\n" if ($debug); + } elsif ($fields[$i] =~ /size=/) { + $size = $i; + print if ($debug > 1); + print "DEBUG: \$size\t= $size\n" if ($debug); + } elsif ($fields[$i] =~ /nrcpts?=/) { + $nrcpts = $i; + print if ($debug > 1); + print "DEBUG: \$nrcpts\t= $nrcpts\n" if ($debug); + } + } +} + diff --git a/mail/search maillogs/prepflog-0.4.tgz b/mail/search maillogs/prepflog-0.4.tgz new file mode 100755 index 0000000..b883b9e Binary files /dev/null and b/mail/search maillogs/prepflog-0.4.tgz differ diff --git a/mail/smtp-client.pl b/mail/smtp-client.pl new file mode 100755 index 0000000..90730c1 --- /dev/null +++ b/mail/smtp-client.pl @@ -0,0 +1,445 @@ +#!/usr/bin/perl + +# +# Simple SMTP client with STARTTLS and AUTH support. +# Michal Ludvig , 2003-2006 +# See http://www.logix.cz/michal/devel/smtp for details. +# Thanks to all contributors for ideas and fixes! +# + +# +# This program can be freely distributed, used and modified +# without any restrictions. It's a public domain. +# + +use strict; +use IO::Socket::INET; +use IO::Socket::SSL; +use Net::SSLeay; +use Digest::HMAC_MD5 qw(hmac_md5_hex); +use MIME::Base64 qw(encode_base64 decode_base64); +use Getopt::Long; +use Term::ReadKey; +use Socket qw(:DEFAULT :crlf); + +my ($user, $pass, $host, $port, + $use_login, $use_plain, $use_cram_md5, $use_digest_md5, + $ehlo_ok, $auth_ok, $starttls_ok, $verbose, + $hello_host, $from, @to, $datasrc); + +$host = 'localhost'; +$port = 'smtp(25)'; +$hello_host = 'localhost'; +$verbose = 0; +$use_login = 0; +$use_plain = 0; +$use_cram_md5 = 0; +$use_digest_md5 = 0; +$starttls_ok = 1; +$auth_ok = 0; +$ehlo_ok = 1; + +# Get command line options. +GetOptions ('host=s' => \$host, 'server=s' => \$host, + 'port=i' => \$port, + 'user=s' => \$user, 'password=s' => \$pass, + 'auth-login' => \$use_login, + 'auth-plain' => \$use_plain, + 'auth-cram-md5' => \$use_cram_md5, + 'auth-digest-md5' => \$use_digest_md5, + 'disable-ehlo' => sub { $ehlo_ok = 0; }, + 'force-ehlo' => sub { $ehlo_ok = 2; }, + 'hello-host|ehlo-host|helo-host=s' => \$hello_host, + 'enable-auth' => \$auth_ok, + 'disable-starttls|disable-tls|disable-ssl' => + sub { $starttls_ok = 0; }, + 'from|mail-from=s' => \$from, + 'to|rcpt-to=s' => \@to, + 'data=s' => \$datasrc, + 'verbose:1' => \$verbose, + 'help' => sub { &usage() } ); + +if ($host =~ /^(.*):(.*)$/) +{ + $host = $1; + $port = $2; +} + +# If at least one --auth-* option was given, enable AUTH. +if ($use_login + $use_plain + $use_cram_md5 + $use_digest_md5 > 0) + { $auth_ok = 1; } + +# If --enable-auth was given, enable all AUTH methods. +elsif ($auth_ok && ($use_login + $use_plain + $use_cram_md5 + + $use_digest_md5 == 0)) +{ + $use_login = 1; + $use_plain = 1; + $use_cram_md5 = 1; + $use_digest_md5 = 1; +} + +# Exit if user haven't specified username for AUTH. +if ($auth_ok && !defined ($user)) + { die ("You requested SMTP AUTH support. Consider using --user switch as well.\n"); } + +# Ask for password if it wasn't supplied on the command line. +if ($auth_ok && defined ($user) && !defined ($pass)) +{ + printf ("Enter password for %s@%s : ", $user, $host); + # Set echo off. + ReadMode (2); + $pass = <>; + # Restore echo. + ReadMode (0); + printf ("\n"); + + exit if (! defined ($pass)); + chop ($pass); +} + +# Connect to the SMTP server. +my $sock = IO::Socket::INET->new( + PeerAddr => $host, + PeerPort => $port, + Proto => 'tcp', + Timeout => 5) + or die ("Connect failed: $@\n"); + +my ($code, $text); +my (%features); + +# Wait for the welcome message of the server. +($code, $text) = &get_line ($sock); +die ("Unknown welcome string: '$code $text'\n") if ($code != 220); +$ehlo_ok-- if ($text !~ /ESMTP/); + +# Send EHLO +&say_hello ($sock, $ehlo_ok, $hello_host, \%features) or exit (1); + +# Run the SMTP session +&run_smtp (); + +# Good bye... +&send_line ($sock, "QUIT\n"); +($code, $text) = &get_line ($sock); +die ("Unknown QUIT response '$code'.\n") if ($code != 221); + +exit 0; + +# This is the main SMTP "engine". +sub run_smtp +{ + # See if we could start encryption + if ((defined ($features{'STARTTLS'}) || defined ($features{'TLS'})) && $starttls_ok) + { + printf ("Starting TLS...\n") if ($verbose >= 1); + + # Do Net::SSLeay initialization + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + + &send_line ($sock, "STARTTLS\n"); + ($code, $text) = &get_line ($sock); + die ("Unknown STARTTLS response '$code'.\n") if ($code != 220); + + if (! IO::Socket::SSL::socket_to_SSL($sock, + SSL_version => 'SSLv3 TLSv1')) + { + die ("STARTTLS: ".IO::Socket::SSL::errstr()."\n"); + } + + if ($verbose >= 1) + { + printf ("Using cipher: %s\n", $sock->get_cipher ()); + printf ("%s", $sock->dump_peer_certificate()); + } + + # Send EHLO again (required by the SMTP standard). + &say_hello ($sock, $ehlo_ok, $hello_host, \%features) or return 0; + } + + # See if we should authenticate ourself + if (defined ($features{'AUTH'}) && $auth_ok) + { + if ($verbose >= 1) + { + printf ("AUTH method (%s): ", $features{'AUTH'}); + } + + # Try CRAM-MD5 if supported by the server + if ($features{'AUTH'} =~ /CRAM-MD5/i && $use_cram_md5) + { + printf ("using CRAM-MD5\n") if ($verbose >= 1); + &send_line ($sock, "AUTH CRAM-MD5\n"); + ($code, $text) = &get_line ($sock); + if ($code != 334) + { + warn ("AUTH failed '$code $text'.\n"); + return 0; + } + + my $response = &encode_cram_md5 ($text, $user, $pass); + &send_line ($sock, "%s\n", $response); + ($code, $text) = &get_line ($sock); + if ($code != 235) + { + warn ("AUTH failed: '$code'.\n"); + return 0; + } + } + # Or try LOGIN method + elsif ($features{'AUTH'} =~ /LOGIN/i && $use_login) + { + printf ("using LOGIN\n") if ($verbose >= 1); + &send_line ($sock, "AUTH LOGIN\n"); + ($code, $text) = &get_line ($sock); + if ($code != 334) + { + warn ("AUTH failed '$code $text'.\n"); + return 0; + } + + &send_line ($sock, "%s\n", encode_base64 ($user, "")); + + ($code, $text) = &get_line ($sock); + if ($code != 334) + { + warn ("AUTH failed '$code $text'.\n"); + return 0; + } + + &send_line ($sock, "%s\n", encode_base64 ($pass, "")); + + ($code, $text) = &get_line ($sock); + if ($code != 235) + { + warn ("AUTH failed '$code $text'.\n"); + return 0; + } + } + # Or finally PLAIN if nothing else was supported. + elsif ($features{'AUTH'} =~ /PLAIN/i && $use_plain) + { + printf ("using PLAIN\n") if ($verbose >= 1); + &send_line ($sock, "AUTH PLAIN %s\n", + encode_base64 ("$user\0$user\0$pass", "")); + ($code, $text) = &get_line ($sock); + if ($code != 235) + { + warn ("AUTH failed '$code $text'.\n"); + return 0; + } + } + # Complain otherwise. + else + { + warn ("No supported authentication method\n". + "advertised by the server.\n"); + return 0; + } + + if ($verbose >= 1) + { printf ("Authentication of $user\@$host succeeded\n"); } + } + + # We can do a relay-test now if a recipient was set. + if ($#to >= 0) + { + if (!defined ($from)) + { + warn ("From: address not set. Using empty one.\n"); + $from = ""; + } + &send_line ($sock, "MAIL FROM: <%s>\n", $from); + ($code, $text) = &get_line ($sock); + if ($code != 250) + { + warn ("MAIL FROM failed: '$code $text'\n"); + return 0; + } + + my $i; + for ($i=0; $i <= $#to; $i++) + { + &send_line ($sock, "RCPT TO: <%s>\n", $to[$i]); + ($code, $text) = &get_line ($sock); + if ($code != 250) + { + warn ("RCPT TO <".$to[$i]."> ". + "failed: '$code $text'\n"); + return 0; + } + } + } + + # Wow, we should even send something! + if (defined ($datasrc)) + { + if ($datasrc eq "-") + { + *MAIL = *STDIN; + } + elsif (!open (MAIL, $datasrc)) + { + warn ("Can't open file '$datasrc'\n"); + return 0; + } + + &send_line ($sock, "DATA\n"); + ($code, $text) = &get_line ($sock); + if ($code != 354) + { + warn ("DATA failed: '$code $text'\n"); + return 0; + } + + while () + { + my $line = $_; + $line =~ s/^\.$CRLF$/\. $CRLF/; + $line =~ s/^\.\n$/\. $CRLF/; + $sock->print ($line); + } + + close (MAIL); + + $sock->printf ("$CRLF.$CRLF"); + + ($code, $text) = &get_line ($sock); + if ($code != 250) + { + warn ("DATA not send: '$code $text'\n"); + return 0; + } + } + + # Perfect. Everything succeeded! + return 1; +} + +# Get one line of response from the server. +sub get_one_line ($) +{ + my $sock = shift; + my ($code, $sep, $text) = ($sock->getline() =~ /(\d+)(.)([^\r]*)/); + my $more; + $more = ($sep eq "-"); + if ($verbose) + { printf ("[%d] '%s'\n", $code, $text); } + return ($code, $text, $more); +} + +# Get concatenated lines of response from the server. +sub get_line ($) +{ + my $sock = shift; + my ($code, $text, $more) = &get_one_line ($sock); + while ($more) { + my ($code2, $line); + ($code2, $line, $more) = &get_one_line ($sock); + $text .= " $line"; + die ("Error code changed from $code to $code2. That's illegal.\n") if ($code ne $code2); + } + return ($code, $text); +} + +# Send one line back to the server +sub send_line ($@) +{ + my $socket = shift; + my @args = @_; + + if ($verbose) + { printf ("> "); printf (@args); } + $args[0] =~ s/\n/$CRLF/g; + $socket->printf (@args); +} + +# Helper function to encode CRAM-MD5 challenge +sub encode_cram_md5 ($$$) +{ + my ($ticket64, $username, $password) = @_; + my $ticket = decode_base64($ticket64) or + die ("Unable to decode Base64 encoded string '$ticket64'\n"); + + my $password_md5 = hmac_md5_hex($ticket, $password); + return encode_base64 ("$username $password_md5", ""); +} + +# Store all server's ESMTP features to a hash. +sub say_hello ($$$$) +{ + my ($sock, $ehlo_ok, $hello_host, $featref) = @_; + my ($feat, $param); + my $hello_cmd = $ehlo_ok > 0 ? "EHLO" : "HELO"; + + &send_line ($sock, "$hello_cmd $hello_host\n"); + my ($code, $text, $more) = &get_one_line ($sock); + + if ($code != 250) + { + warn ("$hello_cmd failed: '$code $text'\n"); + return 0; + } + + # Empty the hash + %{$featref} = (); + + ($feat, $param) = ($text =~ /^(\w+)[= ]*(.*)$/); + $featref->{$feat} = $param; + + # Load all features presented by the server into the hash + while ($more == 1) + { + ($code, $text, $more) = &get_one_line ($sock); + ($feat, $param) = ($text =~ /^(\w+)[= ]*(.*)$/); + $featref->{$feat} = $param; + } + + return 1; +} + +sub usage () +{ + printf ("Simple SMTP client written in Perl that supports some +advanced features like STARTTLS and AUTH. + +Author: Michal Ludvig (c) 2003-2006 + http://www.logix.cz/michal/devel/smtp + +Usage: smtp-client.pl [--options] + + --host= Host name or address of the SMTP server. + (default: localhost) + --port= Port where the SMTP server is listening. + (default: 25) + + --hello-host= String to use in the EHLO/HELO command. + --disable-ehlo Don't use ESMTP EHLO command, only HELO. + --force-ehlo Use EHLO even if server doesn't say ESMTP. + + --disable-starttls Don't use encryption even if the remote + host offers it. + + --enable-auth Enable all methods of SMTP authentication. + --auth-login Enable only AUTH LOGIN method. + --auth-plain Enable only AUTH PLAIN method. + --auth-cram-md5 Enable only AUTH CRAM-MD5 method. + --user= Username for SMTP authentication. + --pass= Corresponding password. + + --from=
Address to use in MAIL FROM command. + --to=
Address to use in RCPT TO command. + + --data= Name of file to send after DATA command. + With \"--data=-\" the script will read + standard input (useful e.g. for pipes). + + --verbose[=] Be more verbose, print the SMTP session. + --help Guess what is this option for ;-) +"); + exit (0); +} + diff --git a/mail/smtp_auth.zip b/mail/smtp_auth.zip new file mode 100755 index 0000000..6da16d3 Binary files /dev/null and b/mail/smtp_auth.zip differ