Subject: | patch for starttls support |
(Short form: patch attached to implement rudimentary STARTTLS support
into Mail::POP3Client.)
Good afternoon,
For work I've had to implement starttls support into a pop3 client for
testing, so I ended up patching Mail::POP3Client as the simple/obvious
solution. I attempted to keep to the coding style where I could. I
haven't tested it for weeks/months and it's likely not feature-complete,
but it at least solves my immediate problem. Thank you for the module,
it has been quite useful.
I would use the patch to be able to do this:
my $pop = new Hostopia::Mail::POP3Client(
HOST => $host,
PORT => $port,
USER => $user,
PASSWORD => $pass,
USESTARTTLS => 1,
);
And this too:
my $pop = new Hostopia::Mail::POP3Client(
HOST => $host,
PORT => $port,
);
$pop->starttls();
$pop->User($user);
$pop->Pass($pass);
$pop->Login();
Subject: | POP3Client.patch |
*** POP3Client.pm.orig 2013-02-12 15:47:25.493463321 -0500
--- POP3Client.pm 2013-02-12 15:47:25.493463321 -0500
***************
*** 68,73 ****
--- 68,76 ----
LOCALADDR => undef,
SOCKET => undef,
USESSL => 0,
+ USESTARTTLS => 0,
+ SSL_VERIFY_MODE => 1,
+ SSL_CA_PATH => '/etc/ssl/certs',
};
$self->{tranlog} = ();
$^O =~ /MacOS/i && ($self->{STRIPCR} = 1);
***************
*** 196,201 ****
--- 199,229 ----
#******************************************************************************
+ #* set/query the SSL_verify_mode
+ #******************************************************************************
+ sub Ssl_verify_mode
+ {
+ my $me = shift;
+ my $SSL_verify_mode = shift or return $me->{SSL_VERIFY_MODE};
+
+ $me->{SSL_VERIFY_MODE} = $SSL_verify_mode;
+
+ } # end Ssl_verify_mode
+
+ #******************************************************************************
+ #* set/query the SSL_ca_path
+ #******************************************************************************
+ sub Ssl_ca_path
+ {
+ my $me = shift;
+ my $SSL_ca_path = shift or return $me->{SSL_CA_PATH};
+
+ $me->{SSL_CA_PATH} = $SSL_ca_path;
+
+ } # end Ssl_ca_path
+
+
+ #******************************************************************************
#* set the host
#******************************************************************************
sub Host
***************
*** 306,311 ****
--- 334,379 ----
#******************************************************************************
#*
#******************************************************************************
+ sub Starttls
+ {
+ my ($me, $SSL_verify_mode, $SSL_ca_path) = @_;
+
+ $SSL_verify_mode and $me->Ssl_verify_mode($SSL_verify_mode);
+ $SSL_ca_path and $me->Ssl_ca_path($SSL_ca_path);
+
+ my $has_starttls = 0;
+ foreach my $capa ($me->Capa()) {
+ $capa =~ /STLS/ and $has_starttls = 1 and last;
+ }
+
+ if ($has_starttls && $me->Socket() && $me->Socket()->connected() ) {
+ $me->_sockprint( "STLS", $me->EOL );
+ my $line = $me->_sockread();
+ unless (defined $line) {
+ $me->Message("Socket read failed for STLS");
+ undef $me->{SOCKET};
+ return 0;
+ }
+ $line =~ /^\+OK/i || return 0;
+ require IO::Socket::SSL;
+ IO::Socket::SSL->start_SSL(
+ $me->Socket(),
+ SSL_verify_mode => $me->Ssl_verify_mode(),
+ SSL_ca_path => $me->Ssl_ca_path(),
+ ) or $me->Message("Could not upgrade to TLS: $!") and
+ return 0;
+ }
+ 1;
+ } # end Starttls
+
+ sub Stls { Starttls(@_); }
+ sub starttls { Starttls(@_); }
+ sub stls { Starttls(@_); }
+
+
+ #******************************************************************************
+ #*
+ #******************************************************************************
sub Close
{
my $me = shift;
***************
*** 378,383 ****
--- 446,453 ----
Proto => "tcp",
Type => SOCK_STREAM,
LocalAddr => $me->LocalAddr(),
+ SSL_verify_mode => $me->Ssl_verify_mode(),
+ SSL_ca_path => $me->Ssl_ca_path(),
Timeout => $me->{TIMEOUT} )
or $me->Message( "could not connect SSL socket [$me->{HOST}, $me->{PORT}]: $!" )
and return 0;
***************
*** 413,419 ****
$me->Message($msg);
$me->State('AUTHORIZATION');
! defined($me->User()) and defined($me->Pass()) and $me->Login();
} # end Connect
--- 483,498 ----
$me->Message($msg);
$me->State('AUTHORIZATION');
!
! if (!$me->{USESSL} && $me->{USESTARTTLS}) {
! $me->Starttls() or $me->Message("Starttls problem: $!") and return 0;
! }
!
! if (defined($me->User()) and defined($me->Pass())) {
! $me->Login();
! } else {
! return 1;
! }
} # end Connect
***************
*** 1250,1255 ****
--- 1329,1337 ----
LOCALADDR => 'xxx.xxx.xxx.xxx[:xx]',
SOCKET => undef,
USESSL => 0,
+ USESTARTTLS => 0,
+ SSL_VERIFY_MODE => 1,
+ SSL_CA_PATH => '/etc/ssl/certs',
);
=over 4
***************
*** 1278,1283 ****
--- 1360,1368 ----
=item *
LOCALADDR - allow selecting a local inet address to use
+ =item *
+ USESTARTTLS - uses STLS, but ignored if USESSL is set
+
=back
=head1 METHODS
***************
*** 1499,1508 ****
--- 1584,1605 ----
Set/Return the current user name.
+ =item I<Ssl_verify_mode>( [1|0] )
+
+ Set/Return the SSL verification mode.
+
+ =item I<Ssl_ca_path>( [/path/to/ca/certs] )
+
+ Set/Return the SSL CA directory path.
+
=item I<Login>
Attempt to login to the server connection.
+ =item I<Starttls>
+
+ Attempt to upgrade the connection to TLS.
+
=item I<Host>( [HOSTNAME] )
Set/Return the current host.