sendemail脚本-perl语言_byzehm

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

        ## Prompt for a password since one wasn't specified with the -xp option.
        $SIG{'ALRM'} = sub { quit("ERROR => Timeout waiting for password inpupt", 1); };
        alarm(60) if ($^O !~ /win/i);  ## alarm() doesn't work in win32
        print "Password: ";
        $opt{'password'} = <STDIN>; chomp $opt{'password'};
        if (!$opt{'password'}) {
            quit("ERROR => A username for SMTP authentication was specified, but no password!", 1);
        }
    }
}

## Validate the TLS setting
$opt{'tls'} = lc($opt{'tls'});
if ($opt{'tls'} !~ /^(auto|yes|no)$/) {
    quit("ERROR => Invalid TLS setting ($opt{'tls'}). Must be one of auto, yes, or no.", 1);
}

## If TLS is set to "yes", make sure sendEmail loaded the libraries needed.
if ($opt{'tls'} eq 'yes' and $conf{'tls\_client'} == 0) {
    quit("ERROR => No TLS support! SendEmail can't load required libraries. (try installing Net::SSLeay and IO::Socket::SSL)", 1);
}

## Return 0 errors
return(0);

}

getline($socketRef)

sub getline {
my ( s o c k e t R e f ) = @ _ ; l o c a l ( socketRef) = @\_; local ( socketRef)=@_;local(/) = “\r\n”;
return $$socketRef->getline;
}

Receive a (multiline?) SMTP response from ($socketRef)

sub getResponse {
my ( s o c k e t R e f ) = @ _ ; m y ( socketRef) = @\_; my ( socketRef)=@_;my(tmp, r e p l y ) ; l o c a l ( reply); local ( reply);local(/) = “\r\n”;
return undef unless defined( t m p = g e t l i n e ( tmp = getline( tmp=getline(socketRef));
return(“getResponse() socket is not open”) unless ($KaTeX parse error: Expected 'EOF', got '#' at position 25: …->opened); #̲# Keep reading …tmp =~ /^\d{3}-/o) {
$reply .= t m p ; r e t u r n u n d e f u n l e s s d e f i n e d ( tmp; return undef unless defined( tmp;returnundefunlessdefined(tmp = getline($socketRef));
}
$reply .= $tmp;
KaTeX parse error: Undefined control sequence: \n at position 15: reply =~ s/\r?\̲n̲//o;
return $reply;
}

###############################################################################################

Function: SMTPchat ( [string $command] )

Description: Sends $command to the SMTP server (on SERVER) and awaits a successful

reply form the server. If the server returns an error, or does not reply

within $conf{‘alarm’} seconds an error is generated.

NOTE: $command is optional, if no command is specified then nothing will

be sent to the server, but a valid response is still required from the server.

Input: [$command] A (optional) valid SMTP command (ex. “HELO”)

Output: Returns zero on success, or non-zero on error.

Error messages will be stored in $conf{‘error’}

A copy of the last SMTP response is stored in the global variable

$conf{‘SMTPchat_response’}

Example: SMTPchat (“HELO mail.isp.net”);

###############################################################################################
sub SMTPchat {
my ($command) = @_;

printmsg("INFO => Sending: \t$command", 1) if ($command);

## Send our command
print $SERVER "$command$CRLF" if ($command);

## Read a response from the server
$SIG{'ALRM'} = sub { $conf{'error'} = "alarm"; $SERVER->close(); };
alarm($conf{'alarm'}) if ($^O !~ /win/i);  ## alarm() doesn't work in win32;
my $result = $conf{'SMTPchat\_response'} = getResponse(\$SERVER); 
alarm(0) if ($^O !~ /win/i);  ## alarm() doesn't work in win32;

## Generate an alert if we timed out
if ($conf{'error'} eq "alarm") {
    $conf{'error'} = "ERROR => Timeout while reading from $conf{'server'}:$conf{'port'} There was no response after $conf{'alarm'} seconds.";
    return(1);
}

## Make sure the server actually responded
if (!$result) {
    $conf{'error'} = "ERROR => $conf{'server'}:$conf{'port'} returned a zero byte response to our query.";
    return(2);
}

## Validate the response
if (evalSMTPresponse($result)) {
    ## conf{'error'} will already be set here
    return(2);
}

## Print the success messsage
printmsg($conf{'error'}, 1);

## Return Success
return(0);

}

###############################################################################################

Function: evalSMTPresponse (string $message )

Description: Searches $message for either an SMTP success or error code, and returns

0 on success, and the actual error code on error.

Input: $message Data received from a SMTP server (ex. "220

Output: Returns zero on success, or non-zero on error.

Error messages will be stored in $conf{‘error’}

Example: SMTPchat (“HELO mail.isp.net”);

###############################################################################################
sub evalSMTPresponse {
my ($message) = @_;

## Validate input
if (!$message) { 
    $conf{'error'} = "ERROR => No message was passed to evalSMTPresponse(). What happened?";
    return(1)
}

printmsg("DEBUG => evalSMTPresponse() - Checking for SMTP success or error status in the message: $message ", 3);

## Look for a SMTP success code
if ($message =~ /^([23]\d\d)/) {
    printmsg("DEBUG => evalSMTPresponse() - Found SMTP success code: $1", 2);
    $conf{'error'} = "SUCCESS => Received: \t$message";
    return(0);
}

## Look for a SMTP error code
if ($message =~ /^([45]\d\d)/) {
    printmsg("DEBUG => evalSMTPresponse() - Found SMTP error code: $1", 2);
    $conf{'error'} = "ERROR => Received: \t$message";
    return($1);
}

## If no SMTP codes were found return an error of 1
$conf{'error'} = "ERROR => Received a message with no success or error code. The message received was: $message";
return(2);

}

#########################################################

SUB: &return_month(0,1,etc)

returns the name of the month that corrosponds

with the number. returns 0 on error.

#########################################################
sub return_month {
my $x = _ [ 0 ] ; i f ( \_[0]; if ( _[0];if(x == 0) { return ‘Jan’; }
if ( x = = 1 ) r e t u r n ′ F e b ′ ; i f ( x == 1) { return 'Feb'; } if ( x==1)returnFeb;if(x == 2) { return ‘Mar’; }
if ( x = = 3 ) r e t u r n ′ A p r ′ ; i f ( x == 3) { return 'Apr'; } if ( x==3)returnApr;if(x == 4) { return ‘May’; }
if ( x = = 5 ) r e t u r n ′ J u n ′ ; i f ( x == 5) { return 'Jun'; } if ( x==5)returnJun;if(x == 6) { return ‘Jul’; }
if ( x = = 7 ) r e t u r n ′ A u g ′ ; i f ( x == 7) { return 'Aug'; } if ( x==7)returnAug;if(x == 8) { return ‘Sep’; }
if ( x = = 9 ) r e t u r n ′ O c t ′ ; i f ( x == 9) { return 'Oct'; } if ( x==9)returnOct;if(x == 10) { return ‘Nov’; }
if ($x == 11) { return ‘Dec’; }
return (0);
}

#########################################################

SUB: &return_day(0,1,etc)

returns the name of the day that corrosponds

with the number. returns 0 on error.

#########################################################
sub return_day {
my $x = _ [ 0 ] ; i f ( \_[0]; if ( _[0];if(x == 0) { return ‘Sun’; }
if ( x = = 1 ) r e t u r n ′ M o n ′ ; i f ( x == 1) { return 'Mon'; } if ( x==1)returnMon;if(x == 2) { return ‘Tue’; }
if ( x = = 3 ) r e t u r n ′ W e d ′ ; i f ( x == 3) { return 'Wed'; } if ( x==3)returnWed;if(x == 4) { return ‘Thu’; }
if ( x = = 5 ) r e t u r n ′ F r i ′ ; i f ( x == 5) { return 'Fri'; } if ( x==5)returnFri;if(x == 6) { return ‘Sat’; }
return (0);
}

###############################################################################################

Function: returnAddressParts(string $address)

Description: Returns a two element array containing the “Name” and “Address” parts of

an email address.

Example: “Brandon Zehm caspian@dotconf.net

would return: (“Brandon Zehm”, “caspian@dotconf.net”);

“caspian@dotconf.net”

would return: (“caspian@dotconf.net”, “caspian@dotconf.net”)

###############################################################################################
sub returnAddressParts {
my $input = $_[0];
my $name = “”;
my $address = “”;

## Make sure to fail if it looks totally invalid
if ($input !~ /(\S+\@\S+)/) {
    $conf{'error'} = "ERROR => The address [$input] doesn't look like a valid email address, ignoring it";
    return(undef());
}

## Check 1, should find addresses like: "Brandon Zehm <caspian@dotconf.net>"
elsif ($input =~ /^\s\*(\S(.\*\S)?)\s\*<(\S+\@\S+)>/o) {
    ($name, $address) = ($1, $3);
}

## Otherwise if that failed, just get the address: <caspian@dotconf.net>
elsif ($input =~ /<(\S+\@\S+)>/o) {
    $name = $address = $1;
}

## Or maybe it was formatted this way: caspian@dotconf.net
elsif ($input =~ /(\S+\@\S+)/o) {
    $name = $address = $1;
}

## Something stupid happened, just return an error.
unless ($name and $address) {
    printmsg("ERROR => Couldn't parse the address: $input", 0);
    printmsg("HINT => If you think this should work, consider reporting this as a bug to $conf{'authorEmail'}", 1);
    return(undef());
}

## Make sure there aren't invalid characters in the address, and return it.
my $ctrl        = '\000-\037';
my $nonASCII    = '\x80-\xff';
if ($address =~ /[<> ,;:"'\[\]\\$ctrl$nonASCII]/) {
    printmsg("WARNING => The address [$address] seems to contain invalid characters: continuing anyway", 0);
}
return($name, $address);

}

###############################################################################################

Function: base64_encode(string $data, bool $chunk)

Description: Returns $data as a base64 encoded string.

If $chunk is true, the encoded data is returned in 76 character long lines

with the final \CR\LF removed.

Note: This is only used from the smtp auth section of code.

At some point it would be nice to merge the code that encodes attachments and this.

###############################################################################################
sub base64_encode {
my $data = $_[0];
my $chunk = $_[1];
my $tmp = ‘’;
my $base64 = ‘’;
my $CRLF = “\r\n”;

###################################
## Convert binary data to base64 ##
###################################
while ($data =~ s/(.{45})//s) {        ## Get 45 bytes from the binary string
    $tmp = substr(pack('u', $&), 1);   ## Convert the binary to uuencoded text
    chop($tmp);
    $tmp =~ tr|` -\_|AA-Za-z0-9+/|;     ## Translate from uuencode to base64
    $base64 .= $tmp;
}

##########################
## Encode the leftovers ##
##########################
my $padding = "";
if ( ($data) and (length($data) > 0) ) {
    $padding = (3 - length($data) % 3) % 3;    ## Set flag if binary data isn't divisible by 3
    $tmp = substr(pack('u', $data), 1);        ## Convert the binary to uuencoded text
    chop($tmp);
    $tmp =~ tr|` -\_|AA-Za-z0-9+/|;             ## Translate from uuencode to base64
    $base64 .= $tmp;
}

############################
## Fix padding at the end ##
############################
$data = '';
$base64 =~ s/.{$padding}$/'=' x $padding/e if $padding; ## Fix the end padding if flag (from above) is set
if ($chunk) {
    while ($base64 =~ s/(.{1,76})//s) {                     ## Put $CRLF after each 76 characters
        $data .= "$1$CRLF";
    }
}
else {
    $data = $base64;
}

## Remove any trailing CRLF's
$data =~ s/(\r|\n)\*$//s;
return($data);

}

#########################################################

SUB: send_attachment(“/path/filename”)

Sends the mime headers and base64 encoded file

to the email server.

#########################################################
sub send_attachment {
my ($filename) = @_; ## Get filename passed
my (@fields, $y, $filename_name, $encoding, ## Local variables
@attachlines, $content_type);
my $bin = 1;

@fields = split(/\/|\\/, $filename);             ## Get the actual filename without the path 
$filename\_name = pop(@fields);       
push @attachments\_names, $filename\_name;         ## FIXME: This is only used later for putting in the log file

##########################
## Autodetect Mime Type ##
##########################

@fields = split(/\./, $filename\_name);
$encoding = $fields[$#fields];

if ($encoding =~ /txt|text|log|conf|^c$|cpp|^h$|inc|m3u/i) {   $content\_type = 'text/plain';                      }
elsif ($encoding =~ /html|htm|shtml|shtm|asp|php|cfm/i) {      $content\_type = 'text/html';                       }
elsif ($encoding =~ /sh$/i) {                                  $content\_type = 'application/x-sh';                }
elsif ($encoding =~ /tcl/i) {                                  $content\_type = 'application/x-tcl';               }
elsif ($encoding =~ /pl$/i) {                                  $content\_type = 'application/x-perl';              }
elsif ($encoding =~ /js$/i) {                                  $content\_type = 'application/x-javascript';        }
elsif ($encoding =~ /man/i) {                                  $content\_type = 'application/x-troff-man';         }
elsif ($encoding =~ /gif/i) {                                  $content\_type = 'image/gif';                       }
elsif ($encoding =~ /jpg|jpeg|jpe|jfif|pjpeg|pjp/i) {          $content\_type = 'image/jpeg';                      }
elsif ($encoding =~ /tif|tiff/i) {                             $content\_type = 'image/tiff';                      }
elsif ($encoding =~ /xpm/i) {                                  $content\_type = 'image/x-xpixmap';                 }
elsif ($encoding =~ /bmp/i) {                                  $content\_type = 'image/x-MS-bmp';                  }
elsif ($encoding =~ /pcd/i) {                                  $content\_type = 'image/x-photo-cd';                }
elsif ($encoding =~ /png/i) {                                  $content\_type = 'image/png';                       }
elsif ($encoding =~ /aif|aiff/i) {                             $content\_type = 'audio/x-aiff';                    }
elsif ($encoding =~ /wav/i) {                                  $content\_type = 'audio/x-wav';                     }
elsif ($encoding =~ /mp2|mp3|mpa/i) {                          $content\_type = 'audio/x-mpeg';                    }
elsif ($encoding =~ /ra$|ram/i) {                              $content\_type = 'audio/x-pn-realaudio';            }
elsif ($encoding =~ /mpeg|mpg/i) {                             $content\_type = 'video/mpeg';                      }
elsif ($encoding =~ /mov|qt$/i) {                              $content\_type = 'video/quicktime';                 }
elsif ($encoding =~ /avi/i) {                                  $content\_type = 'video/x-msvideo';                 }
elsif ($encoding =~ /zip/i) {                                  $content\_type = 'application/x-zip-compressed';    }
elsif ($encoding =~ /tar/i) {                                  $content\_type = 'application/x-tar';               }
elsif ($encoding =~ /jar/i) {                                  $content\_type = 'application/java-archive';        }
elsif ($encoding =~ /exe|bin/i) {                              $content\_type = 'application/octet-stream';        }
elsif ($encoding =~ /ppt|pot|ppa|pps|pwz/i) {                  $content\_type = 'application/vnd.ms-powerpoint';   }
elsif ($encoding =~ /mdb|mda|mde/i) {                          $content\_type = 'application/vnd.ms-access';       }
elsif ($encoding =~ /xls|xlt|xlm|xld|xla|xlc|xlw|xll/i) {      $content\_type = 'application/vnd.ms-excel';        }
elsif ($encoding =~ /doc|dot/i) {                              $content\_type = 'application/msword';              }
elsif ($encoding =~ /rtf/i) {                                  $content\_type = 'application/rtf';                 }
elsif ($encoding =~ /pdf/i) {                                  $content\_type = 'application/pdf';                 }
elsif ($encoding =~ /tex/i) {                                  $content\_type = 'application/x-tex';               }
elsif ($encoding =~ /latex/i) {                                $content\_type = 'application/x-latex';             }
elsif ($encoding =~ /vcf/i) {                                  $content\_type = 'application/x-vcard';             }
else { $content\_type = 'application/octet-stream';  }

############################

Process the attachment

############################

#####################################
## Generate and print MIME headers ##
#####################################

$y = "$CRLF--$conf{'delimiter'}$CRLF";

$y .= “Content-Type: c o n t e n t _ t y p e ; content\_type; content_type;CRLF”;
KaTeX parse error: Expected group as argument to '\"' at end of input: y .= " name=\"filename_name"$CRLF";
y . = " C o n t e n t − T r a n s f e r − E n c o d i n g : b a s e 64 y .= "Content-Transfer-Encoding: base64 y.="ContentTransferEncoding:base64CRLF";
KaTeX parse error: Expected group as argument to '\"' at end of input: …nt; filename=\"filename_name"$CRLF";
y . = " y .= " y.="CRLF";
print $SERVER $y;

###########################################################

Convert the file to base64 and print it to the server

###########################################################

open (FILETOATTACH, KaTeX parse error: Expected '}', got 'EOF' at end of input: …ning the file [filename] for attachment failed with the error: $!", 0);
return(1);
};
binmode(FILETOATTACH); ## Hack to make Win32 work

my $res = "";
my $tmp = "";
my $base64 = "";
while (<FILETOATTACH>) {               ## Read a line from the (binary) file
    $res .= $\_;
    
    ###################################
    ## Convert binary data to base64 ##
    ###################################
    while ($res =~ s/(.{45})//s) {         ## Get 45 bytes from the binary string
        $tmp = substr(pack('u', $&), 1);   ## Convert the binary to uuencoded text
        chop($tmp);
        $tmp =~ tr|` -\_|AA-Za-z0-9+/|;     ## Translate from uuencode to base64
        $base64 .= $tmp;
    }
    
    ################################
    ## Print chunks to the server ##
    ################################
    while ($base64 =~ s/(.{76})//s) {
        print $SERVER "$1$CRLF";
    }
  
}

###################################
## Encode and send the leftovers ##
###################################
my $padding = "";
if ( ($res) and (length($res) >= 1) ) {
    $padding = (3 - length($res) % 3) % 3;  ## Set flag if binary data isn't divisible by 3
    $res = substr(pack('u', $res), 1);      ## Convert the binary to uuencoded text
    chop($res);
    $res =~ tr|` -\_|AA-Za-z0-9+/|;          ## Translate from uuencode to base64
}

############################
## Fix padding at the end ##
############################
$res = $base64 . $res;                               ## Get left overs from above
$res =~ s/.{$padding}$/'=' x $padding/e if $padding; ## Fix the end padding if flag (from above) is set
if ($res) {
    while ($res =~ s/(.{1,76})//s) {                 ## Send it to the email server.
        print $SERVER "$1$CRLF";
    }
}

close (FILETOATTACH) || do {
    printmsg("ERROR - Closing the filehandle for file [$filename] failed with the error: $!", 0);
    return(2);
};

## Return 0 errors
return(0);

}

###############################################################################################

Function: $string = get_hostname (boot $fqdn)

Description: Tries really hard to returns the short (or FQDN) hostname of the current

system. Uses techniques and code from the Sys-Hostname module.

Input: $fqdn A true value (1) will cause this function to return a FQDN hostname

rather than a short hostname.

Output: Returns a string

###############################################################################################
sub get_hostname {
## Assign incoming parameters to variables
my ( $fqdn ) = @_;
my $hostname = “”;

## STEP 1: Get short hostname

## Load Sys::Hostname if it's available
eval { require Sys::Hostname; };
unless ($@) {
    $hostname = Sys::Hostname::hostname(); 
}

## If that didn't get us a hostname, try a few other things
else {
    ## Windows systems
    if ($^O !~ /win/i) {
        if ($ENV{'COMPUTERNAME'}) { $hostname = $ENV{'COMPUTERNAME'}; }
        if (!$hostname) { $hostname = gethostbyname('localhost'); }
        if (!$hostname) { chomp($hostname = `hostname 2> NUL`) };
    }
    
    ## Unix systems
    else {
        local $ENV{PATH} = '/usr/bin:/bin:/usr/sbin:/sbin';  ## Paranoia
        
        ## Try the environment first (Help! What other variables could/should I be checking here?)
        if ($ENV{'HOSTNAME'}) { $hostname = $ENV{'HOSTNAME'}; }
        
        ## Try the hostname command
        eval { local $SIG{__DIE__}; local $SIG{CHLD}; $hostname = `hostname 2>/dev/null`; chomp($hostname); } ||
        
        ## Try POSIX::uname(), which strictly can't be expected to be correct
        eval { local $SIG{__DIE__}; require POSIX; $hostname = (POSIX::uname())[1]; } ||
        
        ## Try the uname command
        eval { local $SIG{__DIE__}; $hostname = `uname -n 2>/dev/null`; chomp($hostname); };
        
    }
    
    ## If we can't find anything else, return ""
    if (!$hostname) {
        print "WARNING => No hostname could be determined, please specify one with -o fqdn=FQDN option!\n";
        return("unknown");
    }
}

## Return the short hostname
unless ($fqdn) {
    $hostname =~ s/\..\*//;
    return(lc($hostname));
}

## STEP 2: Determine the FQDN

## First, if we already have one return it.
if ($hostname =~ /\w\.\w/) { return(lc($hostname)); }

## Next try using 
eval { $fqdn = (gethostbyname($hostname))[0]; };
if ($fqdn) { return(lc($fqdn)); }
return(lc($hostname));

}

###############################################################################################

Function: printmsg (string $message, int $level)

Description: Handles all messages - printing them to the screen only if the messages

$level is >= the global debug level. If $conf{‘logFile’} is defined it

will also log the message to that file.

Input: $message A message to be printed, logged, etc.

$level The debug level of the message. If

not defined 0 will be assumed. 0 is

considered a normal message, 1 and

higher is considered a debug message.

Output: Prints to STDOUT

Assumptions: $conf{‘hostname’} should be the name of the computer we’re running on.

$conf{‘stdout’} should be set to 1 if you want to print to stdout

$conf{‘logFile’} should be a full path to a log file if you want that

$conf{‘debug’} should be an integer between 0 and 10.

Example: printmsg(“WARNING: We believe in generic error messages… NOT!”, 0);

###############################################################################################
sub printmsg {
## Assign incoming parameters to variables
my ( $message, $level ) = @_;

## Make sure input is sane
$level = 0 if (!defined($level));
$message =~ s/\s+$//sgo;
$message =~ s/\r?\n/, /sgo;

## Continue only if the debug level of the program is >= message debug level.
if ($conf{'debug'} >= $level) {
    
    ## Get the date in the format: Dec 3 11:14:04
    my ($sec, $min, $hour, $mday, $mon) = localtime();
    $mon = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')[$mon];
    my $date = sprintf("%s %02d %02d:%02d:%02d", $mon, $mday, $hour, $min, $sec);
    
    ## Print to STDOUT always if debugging is enabled, or if conf{stdout} is true.
    if ( ($conf{'debug'} >= 1) or ($conf{'stdout'} == 1) ) {
        print "$date $conf{'hostname'} $conf{'programName'}\[$$\]: $message\n";
    }
    
    ## Print to the log file if $conf{'logging'} is true
    if ($conf{'logFile'}) {
        if (openLogFile($conf{'logFile'})) { $conf{'logFile'} = ""; printmsg("ERROR => Opening the file [$conf{'logFile'}] for appending returned the error: $!", 1); }
        print LOGFILE "$date $conf{'hostname'} $conf{'programName'}\[$$\]: $message\n";
    }
    
}

## Return 0 errors
return(0);

}

###############################################################################################

FUNCTION:

openLogFile ( $filename )

DESCRIPTION:

Opens the file $filename and attaches it to the filehandle “LOGFILE”. Returns 0 on success

and non-zero on failure. Error codes are listed below, and the error message gets set in

global variable $!.

Example:

openFile (“/var/log/sendEmail.log”);

###############################################################################################
sub openLogFile {
## Get the incoming filename
my $filename = $_[0];

## Make sure our file exists, and if the file doesn't exist then create it
if ( ! -f $filename ) {
    print STDERR "NOTICE: The log file [$filename] does not exist. Creating it now with mode [0600].\n" if ($conf{'stdout'});
    open (LOGFILE, ">>$filename");
    close LOGFILE;
    chmod (0600, $filename);
}

## Now open the file and attach it to a filehandle
open (LOGFILE,">>$filename") or return (1);

## Put the file into non-buffering mode
select LOGFILE;
$| = 1;
select STDOUT;

## Return success
return(0);

}

###############################################################################################

Function: read_file (string $filename)

Description: Reads the contents of a file and returns a two part array:

($status, $file-contents)

$status is 0 on success, non-zero on error.

Example: ($status, $file) = read_file(“/etc/passwd”);

###############################################################################################
sub read_file {
my ( $filename ) = @_;

## If the value specified is a file, load the file's contents
if ( (-e $filename and -r $filename) ) {
    my $FILE;
    if(!open($FILE, ' ' . $filename)) {
        return((1, ""));
    }
    my $file = '';
    while (<$FILE>) {
        $file .= $\_;
    }
    ## Strip an ending \r\n
    $file =~ s/\r?\n$//os;
}
return((1, ""));

}

###############################################################################################

Function: quit (string $message, int $errorLevel)

Description: Exits the program, optionally printing $message. It

returns an exit error level of $errorLevel to the

system (0 means no errors, and is assumed if empty.)

Example: quit(“Exiting program normally”, 0);

###############################################################################################
sub quit {
my ( $message, $errorLevel ) = @_;
e r r o r L e v e l = 0 i f ( ! d e f i n e d ( errorLevel = 0 if (!defined( errorLevel=0if(!defined(errorLevel));

## Print exit message
if ($message) { 
    printmsg($message, 0);
}

## Exit
exit($errorLevel);

}

###############################################################################################

Function: help ()

Description: For all those newbies 😉

Prints a help message and exits the program.

###############################################################################################
sub help {
exit(1) if (!$conf{‘stdout’});
print <<EOM;

c o l o r B o l d {colorBold} colorBoldconf{‘programName’}-$conf{‘version’} by c o n f ′ a u t h o r N a m e ′ < conf{'authorName'} < confauthorName<conf{‘authorEmail’}>${colorNoBold}

Synopsis: $conf{‘programName’} -f ADDRESS [options]

c o l o r R e d R e q u i r e d : {colorRed}Required: colorRedRequired:{colorNormal}
-f ADDRESS from (sender) email address
* At least one recipient required via -t, -cc, or -bcc
* Message body required via -m, STDIN, or -o message-file=FILE

c o l o r G r e e n C o m m o n : {colorGreen}Common: colorGreenCommon:{colorNormal}
-t ADDRESS [ADDR …] to email address(es)
-u SUBJECT message subject
-m MESSAGE message body
-s SERVER[:PORT] smtp mail relay, default is c o n f ′ s e r v e r ′ : conf{'server'}: confserver:conf{‘port’}

c o l o r G r e e n O p t i o n a l : {colorGreen}Optional: colorGreenOptional:{colorNormal}
-a FILE [FILE …] file attachment(s)
-cc ADDRESS [ADDR …] cc email address(es)
-bcc ADDRESS [ADDR …] bcc email address(es)
-xu USERNAME username for SMTP authentication
-xp PASSWORD password for SMTP authentication

c o l o r G r e e n P a r a n o r m a l : {colorGreen}Paranormal: colorGreenParanormal:{colorNormal}
-b BINDADDR[:PORT] local host bind address
-l LOGFILE log to the specified file
-v verbosity, use multiple times for greater effect
-q be quiet (i.e. no STDOUT output)
-o NAME=VALUE advanced options, for details try: --help misc
-o message-content-type=<auto|text|html>
-o message-file=FILE -o message-format=raw
-o message-header=HEADER -o message-charset=CHARSET
-o reply-to=ADDRESS -o timeout=SECONDS
-o username=USERNAME -o password=PASSWORD
-o tls=<auto|yes|no> -o fqdn=FQDN

c o l o r G r e e n H e l p : {colorGreen}Help: colorGreenHelp:{colorNormal}
–help the helpful overview you’re reading now
–help addressing explain addressing and related options
–help message explain message body input and related options
–help networking explain -s, -b, etc
–help output explain logging and other output options
–help misc explain -o options, TLS, SMTP auth, and more

EOM
exit(1);
}

###############################################################################################

Function: helpTopic ($topic)

Description: For all those newbies 😉

Prints a help message and exits the program.

###############################################################################################
sub helpTopic {
exit(1) if (! c o n f ′ s t d o u t ′ ) ; m y ( conf{'stdout'}); my ( confstdout);my(topic) = @_;

CASE: {

ADDRESSING

    ($topic eq 'addressing') && do {
        print <<EOM;

c o l o r B o l d A D D R E S S I N G D O C U M E N T A T I O N {colorBold}ADDRESSING DOCUMENTATION colorBoldADDRESSINGDOCUMENTATION{colorNormal}

c o l o r G r e e n A d d r e s s i n g O p t i o n s {colorGreen}Addressing Options colorGreenAddressingOptions{colorNormal}
Options related to addressing:
-f ADDRESS
-t ADDRESS [ADDRESS …]
-cc ADDRESS [ADDRESS …]
-bcc ADDRESS [ADDRESS …]
-o reply-to=ADDRESS

-f ADDRESS
This required option specifies who the email is from, I.E. the sender’s
email address.

-t ADDRESS [ADDRESS …]
This option specifies the primary recipient(s). At least one recipient
address must be specified via the -t, -cc. or -bcc options.

-cc ADDRESS [ADDRESS …]
This option specifies the “carbon copy” recipient(s). At least one
recipient address must be specified via the -t, -cc. or -bcc options.

-bcc ADDRESS [ADDRESS …]
This option specifies the “blind carbon copy” recipient(s). At least
one recipient address must be specified via the -t, -cc. or -bcc options.

-o reply-to=ADDRESS
This option specifies that an optional “Reply-To” address should be
written in the email’s headers.

c o l o r G r e e n E m a i l A d d r e s s S y n t a x {colorGreen}Email Address Syntax colorGreenEmailAddressSyntax{colorNormal}
Email addresses may be specified in one of two ways:
Full Name: “John Doe <john.doe@gmail.com>”
Just Address: “john.doe@gmail.com”

The “Full Name” method is useful if you want a name, rather than a plain
email address, to be displayed in the recipient’s From, To, or Cc fields
when they view the message.

c o l o r G r e e n M u l t i p l e R e c i p i e n t s {colorGreen}Multiple Recipients colorGreenMultipleRecipients{colorNormal}
The -t, -cc, and -bcc options each accept multiple addresses. They may be
specified by separating them by either a white space, comma, or semi-colon
separated list. You may also specify the -t, -cc, and -bcc options multiple
times, each occurance will append the new recipients to the respective list.

Examples:
(I used “-t” in these examples, but it can be “-cc” or “-bcc” as well)

* Space separated list:
-t jane.doe@yahoo.com “John Doe <john.doe@gmail.com>”

* Semi-colon separated list:
-t “jane.doe@yahoo.com; John Doe <john.doe@gmail.com>”

* Comma separated list:
-t “jane.doe@yahoo.com, John Doe <john.doe@gmail.com>”

* Multiple -t, -cc, or -bcc options:
-t “jane.doe@yahoo.com” -t “John Doe <john.doe@gmail.com>”

EOM
last CASE;
};

MESSAGE

($topic eq ‘message’) && do {
print <<EOM;

c o l o r B o l d M E S S A G E D O C U M E N T A T I O N {colorBold}MESSAGE DOCUMENTATION colorBoldMESSAGEDOCUMENTATION{colorNormal}

c o l o r G r e e n M e s s a g e O p t i o n s {colorGreen}Message Options colorGreenMessageOptions{colorNormal}
Options related to the email message body:
-u SUBJECT
-m MESSAGE
-o message-file=FILE
-o message-content-type=<auto|text|html>
-o message-header=EMAIL HEADER
-o message-charset=CHARSET
-o message-format=raw

-u SUBJECT
This option allows you to specify the subject for your email message.
It is not required (anymore) that the subject be quoted, although it
is recommended. The subject will be read until an argument starting
with a hyphen (-) is found.
Examples:
-u “Contact information while on vacation”
-u New Microsoft vulnerability discovered

-m MESSAGE
This option is one of three methods that allow you to specify the message
body for your email. The message may be specified on the command line
with this -m option, read from a file with the -o message-file=FILE
option, or read from STDIN if neither of these options are present.

It is not required (anymore) that the message be quoted, although it is
recommended. The message will be read until an argument starting with a
hyphen (-) is found.
Examples:
-m “See you in South Beach, Hawaii. -Todd”
-m Please ensure that you upgrade your systems right away

Multi-line message bodies may be specified with the -m option by putting
a “\n” into the message. Example:
-m “This is line 1.\nAnd this is line 2.”

HTML messages are supported, simply begin your message with “” and
sendEmail will properly label the mime header so MUAs properly render
the message. It is currently not possible without “-o message-format=raw”
to send a message with both text and html parts with sendEmail.

-o message-file=FILE
This option is one of three methods that allow you to specify the message
body for your email. To use this option simply specify a text file
containing the body of your email message. Examples:
-o message-file=/root/message.txt
-o message-file=“C:\Program Files\output.txt”

-o message-content-type=<auto|text|html>
This option allows you to specify the content-type of the email. If your
email message is an html message but is being displayed as a text message
just add “-o message-content-type=html” to the command line to force it
to display as an html message. This actually just changes the Content-Type:
header. Advanced users will be happy to know that if you specify anything
other than the three options listed above it will use that as the vaule
for the Content-Type header.

-o message-header=EMAIL HEADER
This option allows you to specify additional email headers to be included.
To add more than one message header simply use this option on the command
line more than once. If you specify a message header that sendEmail would
normally generate the one you specified will be used in it’s place.
Do not use this unless you know what you are doing!
Example:
To scare a Microsoft Outlook user you may want to try this:
-o message-header=“X-Message-Flag: Message contains illegal content”
Example:
To request a read-receipt try this:
-o message-header=“Disposition-Notification-To: <user@domain.com>”
Example:
To set the message priority try this:
-o message-header=“X-Priority: 1”
Priority reference: 1=highest, 2=high, 3=normal, 4=low, 5=lowest

-o message-charset=CHARSET
This option allows you to specify the character-set for the message body.
The default is iso-8859-1.

-o message-format=raw
This option instructs sendEmail to assume the message (specified with -m,
read from STDIN, or read from the file specified in -o message-file=FILE)
is already a *complete* email message. SendEmail will not generate any
headers and will transmit the message as-is to the remote SMTP server.
Due to the nature of this option the following command line options will
be ignored when this one is used:
-u SUBJECT
-o message-header=EMAIL HEADER
-o message-charset=CHARSET
-a ATTACHMENT

c o l o r G r e e n T h e M e s s a g e B o d y {colorGreen}The Message Body colorGreenTheMessageBody{colorNormal}
The email message body may be specified in one of three ways:

  1. Via the -m MESSAGE command line option.
    Example:
    -m “This is the message body”

  2. By putting the message body in a file and using the -o message-file=FILE
    command line option.
    Example:
    -o message-file=/root/message.txt

  3. By piping the message body to sendEmail when nither of the above command
    line options were specified.
    Example:
    grep “ERROR” /var/log/messages | sendEmail -t you@domain.com …

If the message body begins with “” then the message will be treated as
an HTML message and the MIME headers will be written so that a HTML capable
email client will display the message in it’s HTML form.
Any of the above methods may be used with the -o message-format=raw option
to deliver an already complete email message.

EOM
last CASE;
};

MISC

($topic eq ‘misc’) && do {
print <<EOM;

c o l o r B o l d M I S C D O C U M E N T A T I O N {colorBold}MISC DOCUMENTATION colorBoldMISCDOCUMENTATION{colorNormal}

c o l o r G r e e n M i s c O p t i o n s {colorGreen}Misc Options colorGreenMiscOptions{colorNormal}
Options that don’t fit anywhere else:
-a ATTACHMENT [ATTACHMENT …]
-xu USERNAME
-xp PASSWORD
-o username=USERNAME
-o password=PASSWORD
-o tls=<auto|yes|no>
-o timeout=SECONDS
-o fqdn=FQDN

-a ATTACHMENT [ATTACHMENT …]
This option allows you to attach any number of files to your email message.
To specify more than one attachment, simply separate each filename with a
space. Example: -a file1.txt file2.txt file3.txt

-xu USERNAME
Alias for -o username=USERNAME

-xp PASSWORD
Alias for -o password=PASSWORD

-o username=USERNAME (synonym for -xu)
These options allow specification of a username to be used with SMTP
servers that require authentication. If a username is specified but a
password is not, you will be prompted to enter one at runtime.

-o password=PASSWORD (synonym for -xp)
These options allow specification of a password to be used with SMTP
servers that require authentication. If a username is specified but a
password is not, you will be prompted to enter one at runtime.

-o tls=<auto|yes|no>
This option allows you to specify if TLS (SSL for SMTP) should be enabled
or disabled. The default, auto, will use TLS automatically if your perl
installation has the IO::Socket::SSL and Net::SSLeay modules available,
and if the remote SMTP server supports TLS. To require TLS for message
delivery set this to yes. To disable TLS support set this to no. A debug
level of one or higher will reveal details about the status of TLS.

-o timeout=SECONDS
This option sets the timeout value in seconds used for all network reads,
writes, and a few other things.

-o fqdn=FQDN
This option sets the Fully Qualified Domain Name used during the initial
SMTP greeting. Normally this is automatically detected, but in case you
need to manually set it for some reason or get a warning about detection
failing, you can use this to override the default.

EOM
last CASE;
};

NETWORKING

($topic eq ‘networking’) && do {
print <<EOM;

c o l o r B o l d N E T W O R K I N G D O C U M E N T A T I O N {colorBold}NETWORKING DOCUMENTATION colorBoldNETWORKINGDOCUMENTATION{colorNormal}

c o l o r G r e e n N e t w o r k i n g O p t i o n s {colorGreen}Networking Options colorGreenNetworkingOptions{colorNormal}
Options related to networking:
-s SERVER[:PORT]
-b BINDADDR[:PORT]
-o tls=<auto|yes|no>
-o timeout=SECONDS

-s SERVER[:PORT]
This option allows you to specify the SMTP server sendEmail should
connect to to deliver your email message to. If this option is not
specified sendEmail will try to connect to localhost:25 to deliver
the message. THIS IS MOST LIKELY NOT WHAT YOU WANT, AND WILL LIKELY
FAIL unless you have a email server (commonly known as an MTA) running
on your computer!
Typically you will need to specify your company or ISP’s email server.
For example, if you use CableOne you will need to specify:
-s mail.cableone.net
If you have your own email server running on port 300 you would
probably use an option like this:
-s myserver.mydomain.com:300
If you’re a GMail user try:
-s smtp.gmail.com:587 -xu me@gmail.com -xp PASSWD

-b BINDADDR[:PORT]
This option allows you to specify the local IP address (and optional
tcp port number) for sendEmail to bind to when connecting to the remote
SMTP server. This useful for people who need to send an email from a
specific network interface or source address and are running sendEmail on
a firewall or other host with several network interfaces.

-o tls=<auto|yes|no>
This option allows you to specify if TLS (SSL for SMTP) should be enabled
or disabled. The default, auto, will use TLS automatically if your perl
installation has the IO::Socket::SSL and Net::SSLeay modules available,
and if the remote SMTP server supports TLS. To require TLS for message
delivery set this to yes. To disable TLS support set this to no. A debug
level of one or higher will reveal details about the status of TLS.

-o timeout=SECONDS
This option sets the timeout value in seconds used for all network reads,
writes, and a few other things.

EOM
last CASE;
};

OUTPUT

($topic eq ‘output’) && do {
print <<EOM;

c o l o r B o l d O U T P U T D O C U M E N T A T I O N {colorBold}OUTPUT DOCUMENTATION colorBoldOUTPUTDOCUMENTATION{colorNormal}

c o l o r G r e e n O u t p u t O p t i o n s {colorGreen}Output Options colorGreenOutputOptions{colorNormal}
Options related to output:
-l LOGFILE
-v
-q

-l LOGFILE
This option allows you to specify a log file to append to. Every message
that is displayed to STDOUT is also written to the log file. This may be
used in conjunction with -q and -v.

-q
This option tells sendEmail to disable printing to STDOUT. In other
words nothing will be printed to the console. This does not affect the
behavior of the -l or -v options.

-v
This option allows you to increase the debug level of sendEmail. You may
either use this option more than once, or specify more than one v at a
time to obtain a debug level higher than one. Examples:
Specifies a debug level of 1: -v
Specifies a debug level of 2: -vv
Specifies a debug level of 2: -v -v
A debug level of one is recommended when doing any sort of debugging.
At that level you will see the entire SMTP transaction (except the
body of the email message), and hints will be displayed for most
warnings and errors. The highest debug level is three.

EOM
last CASE;
};

Unknown option selected!

quit(“ERROR => The help topic specified is not valid!”, 1);
};

exit(1);
}

#############################

MAIN PROGRAM

#############################

Initialize

initialize();

Process Command Line

processCommandLine();
$conf{‘alarm’} = $opt{‘timeout’};

Abort program after $conf{‘alarm’} seconds to avoid infinite hangs

alarm( c o n f ′ a l a r m ′ ) i f ( conf{'alarm'}) if ( confalarm)if(^O !~ /win/i); ## alarm() doesn’t work in win32

###################################################

Read $message from STDIN if -m was not used

###################################################

if (!($message)) {

Read message body from a file specified with -o message-file=

if ($opt{‘message-file’}) {
if (! -e KaTeX parse error: Expected '}', got 'EOF' at end of input: …ile specified [opt{‘message-file’}] does not exist!“, 0);
printmsg(“HINT => 1) check spelling of your file; 2) fully qualify the path; 3) doubble quote it”, 1);
quit(”“, 1);
}
if (! -r $opt{‘message-file’}) {
printmsg(“ERROR => Message body file specified can not be read due to restricted permissions!”, 0);
printmsg(“HINT => Check permissions on file specified to ensure it can be read”, 1);
quit(”“, 1);
}
if (!open(MFILE, “< " . KaTeX parse error: Expected '}', got 'EOF' at end of input: …age body file [opt{‘message-file’}]: $!”, 0);
quit(”", 1);
}
while () {
$message .= $_;
}
close(MFILE);
}

Read message body from STDIN

else {
alarm( c o n f ′ a l a r m ′ ) i f ( conf{'alarm'}) if ( confalarm)if(^O !~ /win/i); ## alarm() doesn’t work in win32
if ($conf{‘stdout’}) {
print “Reading message body from STDIN because the ‘-m’ option was not used.\n”;
print “If you are manually typing in a message:\n”;
print " - First line must be received within KaTeX parse error: Undefined control sequence: \n at position 23: …larm'} seconds.\̲n̲" if (^O !~ /win/i);
print " - End manual input with a CTRL-D on its own line.\n\n" if (KaTeX parse error: Undefined control sequence: \n at position 75: …n its own line.\̲n̲\n" if (^O =~ /win/i);
}
while () { ## Read STDIN into $message
$message .= _ ; a l a r m ( 0 ) i f ( \_; alarm(0) if ( _;alarm(0)if(^O !~ /win/i); ## Disable the alarm since at least one line was received
}
printmsg(“Message input complete.”, 0);
}
}

Replace bare LF’s with CRLF’s (\012 should always have \015 with it)

KaTeX parse error: Undefined control sequence: \0 at position 15: message =~ s/(\̲0̲15)?(\012|)/\015\012/g;

Replace bare CR’s with CRLF’s (\015 should always have \012 with it)

KaTeX parse error: Undefined control sequence: \0 at position 15: message =~ s/(\̲0̲15)(\012|)?/\015\012/g;

Check message for bare periods and encode them

m e s s a g e =   s / ( ∣ message =~ s/(^| message= s/(CRLF)(.{1})( C R L F ∣ CRLF| CRLF)/$1.$2$3/g;

Get the current date for the email header

my ( s e c , sec, sec,min, h o u r , hour, hour,mday, m o n , mon, mon,year,$day) = gmtime();
$year += 1900; m o n = r e t u r n _ m o n t h ( mon = return\_month( mon=return_month(mon); d a y = r e t u r n _ d a y ( day = return\_day( day=return_day(day);
my d a t e = s p r i n t f ( " date = sprintf("%s, %s %s %d %.2d:%.2d:%.2d %s", date=sprintf("day, $mday, $mon, $year, $hour, $min, $sec, $conf{‘timezone’});

##################################

Connect to the SMTP server

##################################
printmsg(“DEBUG => Connecting to c o n f ′ s e r v e r ′ : conf{'server'}: confserver:conf{‘port’}”, 1);
$SIG{‘ALRM’} = sub {
printmsg("ERROR => Timeout while connecting to c o n f ′ s e r v e r ′ : conf{'server'}: confserver:conf{‘port’} There was no response after KaTeX parse error: Expected 'EOF', got '}' at position 134: … quit("", 1); }̲; alarm(conf{‘alarm’}) if ($^O !~ /win/i); ## alarm() doesn’t work in win32;
$SERVER = IO::Socket::INET->new( PeerAddr => $conf{‘server’},
PeerPort => $conf{‘port’},
LocalAddr => $conf{‘bindaddr’},
Proto => ‘tcp’,
Autoflush => 1,
timeout => c o n f ′ a l a r m ′ , ) ; a l a r m ( 0 ) i f ( conf{'alarm'}, ); alarm(0) if ( confalarm,);alarm(0)if(^O !~ /win/i); ## alarm() doesn’t work in win32;

Make sure we got connected

if ( (! S E R V E R ) o r ( ! SERVER) or (! SERVER)or(!SERVER->opened()) ) {
printmsg(“ERROR => Connection attempt to c o n f ′ s e r v e r ′ : conf{'server'}: confserver:conf{‘port’} failed: $@”, 0);
printmsg(“HINT => Try specifying a different mail relay with the -s option.”, 1);
quit(“”, 1);
}

Save our IP address for later

$conf{‘ip’} = $SERVER->sockhost();
printmsg(“DEBUG => My IP address is: $conf{‘ip’}”, 1);

#########################

Do the SMTP Dance

#########################

Read initial greeting to make sure we’re talking to a live SMTP server

if (SMTPchat()) { quit($conf{‘error’}, 1); }

We’re about to use $opt{‘fqdn’}, make sure it isn’t empty

if (!$opt{‘fqdn’}) {
## Ok, that means we couldn’t get a hostname, how about using the IP address for the HELO instead
$opt{‘fqdn’} = “[” . $conf{‘ip’} . “]”;
}

EHLO

if (SMTPchat('EHLO ’ . KaTeX parse error: Expected '}', got 'EOF' at end of input: …{ printmsg(conf{‘error’}, 0);
printmsg(“NOTICE => EHLO command failed, attempting HELO instead”);
if (SMTPchat('HELO ’ . KaTeX parse error: Expected '}', got 'EOF' at end of input: …qdn'})) { quit(conf{‘error’}, 1); }
if ( $opt{‘username’} and $opt{‘password’} ) {
printmsg(“WARNING => The mail server does not support SMTP authentication!”, 0);
}
}
else {

## Determin if the server supports TLS
if ($conf{'SMTPchat\_response'} =~ /STARTTLS/) {
    $conf{'tls\_server'} = 1;
    printmsg("DEBUG => The remote SMTP server supports TLS :)", 2);
}
else {
    $conf{'tls\_server'} = 0;
    printmsg("DEBUG => The remote SMTP server does NOT support TLS :(", 2);
}

## Start TLS if possible
if ($conf{'tls\_server'} == 1 and $conf{'tls\_client'} == 1 and $opt{'tls'} =~ /^(yes|auto)$/) {
    printmsg("DEBUG => Starting TLS", 2);
    if (SMTPchat('STARTTLS')) { quit($conf{'error'}, 1); }
    if (! IO::Socket::SSL->start_SSL($SERVER, SSL_version => 'SSLv3 TLSv1')) {
        quit("ERROR => TLS setup failed: " . IO::Socket::SSL::errstr(), 1);
    }
    printmsg("DEBUG => TLS: Using cipher: ". $SERVER->get_cipher(), 3);
    printmsg("DEBUG => TLS session initialized :)", 1);
    
    ## Restart our SMTP session
    if (SMTPchat('EHLO ' . $opt{'fqdn'})) { quit($conf{'error'}, 1); }
}
elsif ($opt{'tls'} eq 'yes' and $conf{'tls\_server'} == 0) {
    quit("ERROR => TLS not possible! Remote SMTP server, $conf{'server'}, does not support it.", 1);
}


## Do SMTP Auth if required
if ( $opt{'username'} and $opt{'password'} ) {
    if ($conf{'SMTPchat\_response'} !~ /AUTH\s/) {
        printmsg("NOTICE => Authentication not supported by the remote SMTP server!", 0);
    }
    else {
        my $auth\_succeeded = 0;
        my $mutual\_method = 0;
        
        # ## SASL CRAM-MD5 authentication method
        # if ($conf{'SMTPchat\_response'} =~ /\bCRAM-MD5\b/i) {
        # printmsg("DEBUG => SMTP-AUTH: Using CRAM-MD5 authentication method", 1);

if (SMTPchat(‘AUTH CRAM-MD5’)) { quit($conf{‘error’}, 1); }

## FIXME!!

printmsg(“DEBUG => User authentication was successful”, 1);

}

SASL LOGIN authentication method

if ($auth_succeeded == 0 and $conf{‘SMTPchat_response’} =~ /\bLOGIN\b/i) {
KaTeX parse error: Expected '}', got 'EOF' at end of input: …base64\_encode(opt{‘username’}))) {
if (!SMTPchat(base64_encode($opt{‘password’}))) {
KaTeX parse error: Expected 'EOF', got '}' at position 100: … LOGIN)", 1); }̲ } } if (auth_succeeded == 0) {
printmsg(“DEBUG => SMTP-AUTH: LOGIN authenticaion failed.”, 1);
}
}

SASL PLAIN authentication method

if ($auth_succeeded == 0 and $conf{‘SMTPchat_response’} =~ /\bPLAIN\b/i) {
m u t u a l _ m e t h o d = 1 ; p r i n t m s g ( " D E B U G = > S M T P − A U T H : U s i n g P L A I N a u t h e n t i c a t i o n m e t h o d " , 1 ) ; i f ( S M T P c h a t ( ′ A U T H P L A I N ′ . b a s e 64 _ e n c o d e ( " mutual\_method = 1; printmsg("DEBUG => SMTP-AUTH: Using PLAIN authentication method", 1); if (SMTPchat('AUTH PLAIN ' . base64\_encode(" mutual_method=1;printmsg("DEBUG=>SMTPAUTH:UsingPLAINauthenticationmethod",1);if(SMTPchat(AUTHPLAIN.base64_encode("opt{‘username’}\0KaTeX parse error: Undefined control sequence: \0 at position 16: opt{'username'}\̲0̲opt{‘password’}"))) {
printmsg(“DEBUG => SMTP-AUTH: PLAIN authenticaion failed.”, 1);
}
else {
$auth_succeeded = 1;
printmsg(“DEBUG => User authentication was successful (Method: PLAIN)”, 1);
}
}

If none of the authentication methods supported by sendEmail were supported by the server, let the user know

if ($mutual_method == 0) {
printmsg(“WARNING => SMTP-AUTH: No mutually supported authentication methods available”, 0);
}

If we didn’t get authenticated, log an error message and exit

if ($auth_succeeded == 0) {
quit(“ERROR => ERROR => SMTP-AUTH: Authentication to c o n f ′ s e r v e r ′ : conf{'server'}: confserver:conf{‘port’} failed.”, 1);
}
}
}
}

MAIL FROM

if (SMTPchat(‘MAIL FROM:<’ .(returnAddressParts(KaTeX parse error: Expected '}', got 'EOF' at end of input: …. '>')) { quit(conf{‘error’}, 1); }

RCPT TO

my $oneRcptAccepted = 0;
foreach my KaTeX parse error: Expected '}', got 'EOF' at end of input: …, @bcc) { my (name, a d d r e s s ) = r e t u r n A d d r e s s P a r t s ( address) = returnAddressParts( address)=returnAddressParts(rcpt);
if (SMTPchat(‘RCPT TO:<’ . KaTeX parse error: Expected '}', got 'EOF' at end of input: …The recipient <address> was rejected by the mail server, error follows:", 0);
c o n f ′ e r r o r ′ =   s / E R R O R / W A R N I N G / o ; p r i n t m s g ( conf{'error'} =~ s/^ERROR/WARNING/o; printmsg( conferror= s/ERROR/WARNING/o;printmsg(conf{‘error’}, 0);
}
elsif ($oneRcptAccepted == 0) {
$oneRcptAccepted = 1;
}
}

If no recipients were accepted we need to exit with an error.

if ($oneRcptAccepted == 0) {
quit(“ERROR => Exiting. No recipients were accepted for delivery by the mail server.”, 1);
}

DATA

if (SMTPchat(‘DATA’)) { quit($conf{‘error’}, 1); }

###############################

Build and send the body

###############################
printmsg(“INFO => Sending message body”,1);

If the message-format is raw just send the message as-is.

if ( o p t ′ m e s s a g e − f o r m a t ′ =   / r a w opt{'message-format'} =~ /^raw optmessageformat= /raw/i) {
print $SERVER $message;
}

If the message-format isn’t raw, then build and send the message,

else {

Message-ID:

if ($opt{‘message-header’} !~ /^Message-ID:/iom) {
$header .= ‘Message-ID: <’ . $conf{‘Message-ID’} . ‘@’ . $conf{‘hostname’} . ‘>’ . $CRLF;
}

From: “Name” address@domain.com (the pointless test below is just to keep scoping correct)

if ($from and KaTeX parse error: Expected '}', got 'EOF' at end of input: …m:/iom) { my (name, a d d r e s s ) = r e t u r n A d d r e s s P a r t s ( address) = returnAddressParts( address)=returnAddressParts(from);
$header .= ‘From: "’ . $name . ‘" <’ . $address . ‘>’ . $CRLF;
}

最全的Linux教程,Linux从入门到精通

======================

  1. linux从入门到精通(第2版)

  2. Linux系统移植

  3. Linux驱动开发入门与实战

  4. LINUX 系统移植 第2版

  5. Linux开源网络全栈详解 从DPDK到OpenFlow

华为18级工程师呕心沥血撰写3000页Linux学习笔记教程

第一份《Linux从入门到精通》466页

====================

内容简介

====

本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。

华为18级工程师呕心沥血撰写3000页Linux学习笔记教程

本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。

需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值