check-smtp-auth
changeset 0 1d98e3a7f076
child 1 6f3d1d1f856a
equal deleted inserted replaced
-1:000000000000 0:1d98e3a7f076
       
     1 #! /usr/bin/perl
       
     2 # up-to-date source is at:
       
     3 # https://keller.schlittermann.de/hg/check-smtp-auth
       
     4 
       
     5 use strict;
       
     6 use warnings;
       
     7 use Sys::Hostname;
       
     8 use IO::Socket::INET;
       
     9 use IO::Socket::SSL;
       
    10 use Pod::Usage;
       
    11 use Getopt::Long;
       
    12 
       
    13 my $HOSTNAME = hostname();
       
    14 
       
    15 my $opt_ssl   = 0;
       
    16 my $opt_debug = 0;
       
    17 
       
    18 sub check_auth($$);
       
    19 
       
    20 MAIN: {
       
    21 
       
    22     GetOptions(
       
    23         "d|debug" => \$opt_debug,
       
    24         "s|ssl"   => \$opt_ssl,
       
    25 	"m|man"   => sub { pod2usage(-exitval => 0, -verbose => 2) },
       
    26 	"h|help"   => sub { pod2usage(-exitval => 0, -verbose => 1) },
       
    27     ) or pod2usage();
       
    28 
       
    29     my $remote = shift or pod2usage;
       
    30     $remote .= $opt_ssl ? ":smtps" : ":smtp" if not $remote =~ /:/;
       
    31 
       
    32     warn "connecting to $remote\n" if $opt_debug;
       
    33     my $s =
       
    34       $opt_ssl
       
    35       ? new IO::Socket::SSL($remote)
       
    36       : new IO::Socket::INET($remote)
       
    37       or die "Can't open socket to $remote\n";
       
    38 
       
    39     # Get the greeting and even expect continuation lines
       
    40     # I do not know if they may appear in the greeting, probably not,
       
    41     # because it's feature of ESMTP and the server doesn't know if the
       
    42     # client would understand it)
       
    43 
       
    44     while (<$s>) { last if /^\d{3}\s/ }
       
    45 
       
    46     # Do not continue on any error
       
    47     /^2/ or die "expected 2xx\n";
       
    48 
       
    49     # Do not continue if the server does not speak ESMTP
       
    50     /ESMTP/ or die "expected ESMTP";
       
    51 
       
    52     # first attempt plain (or SSL)
       
    53     print map { "$_\n" } check_auth($s, $HOSTNAME);
       
    54 
       
    55     # if still not closed we should try STARTTLS
       
    56     if ($s->connected) {
       
    57         warn "trying STARTTLS\n" if $opt_debug;
       
    58 
       
    59         print {$s} "STARTTLS\r\n";
       
    60         while (<$s>) { last if /^\d{3}\s/ }
       
    61         /^2.. TLS/ or die "can't start TLS: $_";
       
    62 
       
    63         IO::Socket::SSL->start_SSL($s);
       
    64         print map { "$_\n" } check_auth($s, $HOSTNAME);
       
    65     }
       
    66 
       
    67 }
       
    68 
       
    69 sub check_auth($$) {
       
    70     my ($socket, $hostname, $tls) = @_;
       
    71     my $close = 1;
       
    72     my @auth;
       
    73 
       
    74     print {$socket} "EHLO $HOSTNAME\r\n";
       
    75 
       
    76     my $prefix = ref($socket) =~ /::SSL$/ ? "ssl" : "plain";
       
    77 
       
    78     # Parse the response to the EHLO
       
    79     while (<$socket>) {
       
    80         print STDERR if $opt_debug;
       
    81         /STARTTLS/ and $close = 0;
       
    82         push @auth, map { "$prefix $_" } split if s/^.*AUTH\s+//;
       
    83         last if /^\d{3}\s/;    # last line
       
    84     }
       
    85 
       
    86     if ($close) {
       
    87         print {$socket} "QUIT\r\n";
       
    88         $socket->close;
       
    89     }
       
    90 
       
    91     return @auth;
       
    92 }
       
    93 
       
    94 __END__
       
    95 
       
    96 =head1 NAME
       
    97 
       
    98  check-smtp-auth - checks the auth capabilities of a remote SMTP server
       
    99 
       
   100 =head1 SYNOPSIS
       
   101 
       
   102  check-smtp-auth [-d|--debug] [-s|--ssl] server[:port]
       
   103  check-smtp-auth [-m|--man] [-h|--help]
       
   104 
       
   105 =head1 DESCRIPTION
       
   106 
       
   107 This tools checks the AUTH capabilities of a SMTP server. It connects, 
       
   108 issues an "EHLO" command and tries to parse the output.
       
   109 
       
   110 If in the server output "STARTTLS" appears, it retries to get this
       
   111 information after issuing "STARTTLS".
       
   112 
       
   113 The output is line by line one AUTH method, prefixed with "plain"
       
   114 or "ssl", depending on the type of the connection.
       
   115 
       
   116 =head1 OPTIONS
       
   117 
       
   118 =over
       
   119 
       
   120 =item [-s|--ssl]
       
   121 
       
   122 Connect via a SSL socket. This option changes the default port
       
   123 to connect to "smtps" instead of "smtp". (default: 0)
       
   124 
       
   125 =item [-d|--debug]
       
   126 
       
   127 Issue some debugging information to STDERR. (default: 0)
       
   128 
       
   129 =back
       
   130 
       
   131 =head1 AUTHOR
       
   132 
       
   133 Heiko Schlittermann <hs@schlittermann.de>
       
   134 See L<https://keller.schlittermann.de/hg/check-smtp-auth> for
       
   135 the current version.
       
   136 
       
   137 =cut