added more mail scripts
This commit is contained in:
parent
c95fd6c427
commit
e81fd3702d
7 changed files with 833 additions and 0 deletions
BIN
mail/IMAPCopySrc.zip
Executable file
BIN
mail/IMAPCopySrc.zip
Executable file
Binary file not shown.
99
mail/notify_by_sms2email
Executable file
99
mail/notify_by_sms2email
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
132
mail/search maillogs/findrecpt.pl
Executable file
132
mail/search maillogs/findrecpt.pl
Executable file
|
@ -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 -- <dmiller@newportnet.com>
|
||||||
|
# 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(<LOG>) {
|
||||||
|
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(<LOG>) {
|
||||||
|
chomp();
|
||||||
|
if(/$msg/ && /smtp/ && /to=</) {
|
||||||
|
my $status;
|
||||||
|
my @fields = split " ", $_, 11;
|
||||||
|
# recipient address
|
||||||
|
$fields[6] =~ s/^to=<//;
|
||||||
|
$fields[6] =~ s/>,$//;
|
||||||
|
# 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=<//;
|
||||||
|
$fields[6] =~ s/>,$//;
|
||||||
|
# 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";
|
||||||
|
}
|
157
mail/search maillogs/findsender.pl
Executable file
157
mail/search maillogs/findsender.pl
Executable file
|
@ -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(<LOG>) {
|
||||||
|
# on the fly, determine log line format (where various fields are)
|
||||||
|
unless (defined $nrcpts) {
|
||||||
|
if(/from=</ && !/postfix\/pickup/ && !/: warning: .*;/) {
|
||||||
|
my @fields = split;
|
||||||
|
find_fromline_fields(@fields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(/to=/) { # feature: matches Postfix orig_to= also
|
||||||
|
if(/to=<?$recipient[\W_]/) { # same feature
|
||||||
|
my @fields = split;
|
||||||
|
$fields[$qid] =~ s/://;
|
||||||
|
push @temp, $fields[$qid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(LOG);
|
||||||
|
|
||||||
|
# optimize list by sorting and removing duplicates
|
||||||
|
@temp = sort @temp;
|
||||||
|
foreach my $msg (@temp) {
|
||||||
|
if ((@msgids == 0) || ($msgids[$#msgids] ne $msg)) { # not yet recorded
|
||||||
|
push @msgids, $msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# display count of messages, and display header if there are messages
|
||||||
|
# if no messages we are done
|
||||||
|
print "Found ", scalar @msgids, " messages for $recipient in $maillog\n";
|
||||||
|
(@msgids) ? printMessageHeader() : exit 0;
|
||||||
|
|
||||||
|
# look up sender, size, etc. for each message id
|
||||||
|
open(LOG, "<$maillog") || die "2nd open of $maillog failed\n";
|
||||||
|
foreach $msg (@msgids) {
|
||||||
|
while(<LOG>) {
|
||||||
|
chomp();
|
||||||
|
if(/$msg/ && /from=</ && !/postfix\/pickup/ && !/: warning: .*;/) {
|
||||||
|
@fields = split " ", $_, 14;
|
||||||
|
# munge data fields for output
|
||||||
|
if ($fields[$sender] =~ /^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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
BIN
mail/search maillogs/prepflog-0.4.tgz
Executable file
BIN
mail/search maillogs/prepflog-0.4.tgz
Executable file
Binary file not shown.
445
mail/smtp-client.pl
Executable file
445
mail/smtp-client.pl
Executable file
|
@ -0,0 +1,445 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
#
|
||||||
|
# Simple SMTP client with STARTTLS and AUTH support.
|
||||||
|
# Michal Ludvig <michal@logix.cz>, 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 (<MAIL>)
|
||||||
|
{
|
||||||
|
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 <michal\@logix.cz> (c) 2003-2006
|
||||||
|
http://www.logix.cz/michal/devel/smtp
|
||||||
|
|
||||||
|
Usage: smtp-client.pl [--options]
|
||||||
|
|
||||||
|
--host=<hostname> Host name or address of the SMTP server.
|
||||||
|
(default: localhost)
|
||||||
|
--port=<number> Port where the SMTP server is listening.
|
||||||
|
(default: 25)
|
||||||
|
|
||||||
|
--hello-host=<string> 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> Username for SMTP authentication.
|
||||||
|
--pass=<password> Corresponding password.
|
||||||
|
|
||||||
|
--from=<address> Address to use in MAIL FROM command.
|
||||||
|
--to=<address> Address to use in RCPT TO command.
|
||||||
|
|
||||||
|
--data=<filename> Name of file to send after DATA command.
|
||||||
|
With \"--data=-\" the script will read
|
||||||
|
standard input (useful e.g. for pipes).
|
||||||
|
|
||||||
|
--verbose[=<number>] Be more verbose, print the SMTP session.
|
||||||
|
--help Guess what is this option for ;-)
|
||||||
|
");
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
BIN
mail/smtp_auth.zip
Executable file
BIN
mail/smtp_auth.zip
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue