Net-IMAP-Simple
view release on metacpan or search on metacpan
lib/Net/IMAP/Simple.pm view on Meta::CPAN
package Net::IMAP::Simple;
use strict;
use warnings;
use Carp;
use IO::File;
use IO::Socket;
use IO::Select;
use Net::IMAP::Simple::PipeSocket;
our $VERSION = "1.2212";
BEGIN {
# I'd really rather the pause/cpan indexers miss this "package"
eval ## no critic
q( package Net::IMAP::Simple::_message;
use overload fallback=>1, '""' => sub { local $"=""; "@{$_[0]}" };
sub new { bless $_[1] })
}
our $uidm;
sub new {
my ( $class, $server, %opts ) = @_;
## warn "use of Net::IMAP::Simple::SSL is depricated, pass use_ssl to new() instead\n"
## if $class =~ m/::SSL/;
my $self = bless { count => -1 } => $class;
$self->{use_v6} = ( $opts{use_v6} ? 1 : 0 );
$self->{use_ssl} = ( $opts{use_ssl} ? 1 : 0 );
unless( $opts{shutup_about_v6ssl} ) {
carp "use_ssl with IPv6 is not yet supported"
if $opts{use_v6} and $opts{use_ssl};
}
if( $opts{ssl_version} ) {
$self->{ssl_version} = $opts{ssl_version};
$opts{use_ssl} = 1;
}
$opts{use_ssl} = 1 if $opts{find_ssl_defaults};
if( $opts{use_ssl} ) {
eval {
require IO::Socket::SSL;
import IO::Socket::SSL;
"true";
} or croak "IO::Socket::SSL must be installed in order to use_ssl";
$self->{ssl_options} = [ eval {@{ $opts{ssl_options} }} ];
carp "ignoring ssl_options: $@" if $opts{ssl_options} and not @{ $self->{ssl_options} };
unless( @{ $self->{ssl_options} } ) {
if( $opts{find_ssl_defaults} ) {
my $nothing = 1;
for(qw(
/etc/ssl/certs/ca-certificates.crt
/etc/pki/tls/certs/ca-bundle.crt
/etc/ssl/ca-bundle.pem
/etc/ssl/certs/
)) {
if( -f $_ ) {
@{ $self->{ssl_options} } = (SSL_ca_file=>$_, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER());
$nothing = 0;
last;
} elsif( -d $_ ) {
@{ $self->{ssl_options} } = (SSL_ca_path=>$_, SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER());
$nothing = 0;
last;
}
}
if( $nothing ) {
carp "couldn't find rational defaults for ssl verify. Choosing to not verify.";
@{ $self->{ssl_options} } = (SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE());
}
} else {
@{ $self->{ssl_options} } = (SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE());
}
}
}
if ( $opts{use_v6} ) {
eval {
require IO::Socket::INET6;
import IO::Socket::INET6;
"true";
} or croak "IO::Socket::INET6 must be installed in order to use_v6";
}
if( $server =~ m/cmd:(.+)/ ) {
$self->{cmd} = $1;
} else {
if( ($self->{server}, $self->{port}) = $server =~ m/^(\d{1,3}(?:\.\d{1,3}){3})(?::(\d+))?\z/ ) {
} elsif( ($self->{server}, $self->{port}) = $server =~ m/^\[([a-fA-F0-9:]+)\]:(\d+)\z/ ) {
} elsif( ($self->{server}, $self->{port}) = $server =~ m/^([a-fA-F0-9:]+)\z/ ) {
} elsif( ($self->{server}, $self->{port}) = $server =~ m/^([^:]+):(\d+)\z/ ) {
} else {
$self->{server} = $server;
$self->{port} = $opts{port};
}
$self->{port} = $self->_port unless defined $self->{port};
}
$self->{timeout} = ( $opts{timeout} ? $opts{timeout} : $self->_timeout );
$self->{retry} = ( defined($opts{retry}) ? $opts{retry} : $self->_retry );
$self->{retry_delay} = ( defined($opts{retry_delay}) ? $opts{retry_delay} : $self->_retry_delay );
$self->{bindaddr} = $opts{bindaddr};
$self->{use_select_cache} = $opts{use_select_cache};
$self->{select_cache_ttl} = $opts{select_cache_ttl};
$self->{debug} = $opts{debug};
$self->{readline_callback} = $opts{readline_callback};
my $sock;
my $c;
for ( my $i = 0 ; $i <= $self->{retry} ; $i++ ) {
if ( $sock = $self->{sock} = $self->_connect ) {
$c = 1;
last;
} elsif ( $i < $self->{retry} ) {
sleep $self->{retry_delay};
# Critic NOTE: I'm not sure why this was done, but it was removed
# beucase the critic said it was bad and sleep makes more sense.
# select( undef, undef, undef, $self->{retry_delay} );
}
}
if ( !$c ) {
$@ =~ s/IO::Socket::INET6?: //g;
lib/Net/IMAP/Simple.pm view on Meta::CPAN
$self->_debug( caller, __LINE__, 'new', "looking for greeting" ) if $self->{debug};
if( my $line = $sock->getline ) {
# Cool, we got a line, check to see if it's a
# greeting.
$self->_debug( caller, __LINE__, 'new', "got a greeting: $line" ) if $self->{debug};
$greeting_ok = 1 if $line =~ m/^\*\s+(?:OK|PREAUTH)/i;
# Also, check to see if we failed before we sent any
# commands.
return if $line =~ /^\*\s+(?:NO|BAD)(?:\s+(.+))?/i;
} else {
$self->_debug( caller, __LINE__, 'new', "server hung up during connect" ) if $self->{debug};
# The server hung up on us, otherwise we'd get a line
# after can_read.
return;
}
} else {
$self->_debug( caller, __LINE__, 'new', "no greeting found before timeout" ) if $self->{debug};
}
return unless $greeting_ok;
return $self;
}
sub _connect {
my ($self) = @_;
my $sock;
if( $self->{cmd} ) {
$self->_debug( caller, __LINE__, '_connect', "popping open a pipesocket for command: $self->{cmd}" ) if $self->{debug};
$sock = Net::IMAP::Simple::PipeSocket->new(cmd=>$self->{cmd});
} else {
$self->_debug( caller, __LINE__, '_connect', "connecting to $self->{server}:$self->{port}" ) if $self->{debug};
$sock = $self->_sock_from->new(
PeerAddr => $self->{server},
PeerPort => $self->{port},
Timeout => $self->{timeout},
Proto => 'tcp',
( $self->{bindaddr} ? ( LocalAddr => $self->{bindaddr} ) : () ),
( $_[0]->{ssl_version} ? ( SSL_version => $self->{ssl_version} ) : () ),
( $_[0]->{use_ssl} ? (@{ $self->{ssl_options} }) : () ),
);
}
$self->_debug( caller, __LINE__, '_connect', "connected, returning socket" ) if $self->{debug};
return $sock;
}
sub _port { return $_[0]->{use_ssl} ? 993 : 143 }
sub _sock { return $_[0]->{sock} }
sub _count { return $_[0]->{count} }
sub _last { $_[0]->select unless exists $_[0]->{last}; return $_[0]->{last}||0 }
sub _timeout { return 90 }
sub _retry { return 1 }
sub _retry_delay { return 5 }
sub _sock_from { return $_[0]->{use_v6} ? 'IO::Socket::INET6' : $_[0]->{use_ssl} ? 'IO::Socket::SSL' : 'IO::Socket::INET' }
sub starttls {
my ($self) = @_;
require IO::Socket::SSL; import IO::Socket::SSL;
require Net::SSLeay; import Net::SSLeay;
# $self->{debug} = 1;
# warn "Processing STARTTLS command";
return $self->_process_cmd(
cmd => ['STARTTLS'],
final => sub {
Net::SSLeay::load_error_strings();
Net::SSLeay::SSLeay_add_ssl_algorithms();
Net::SSLeay::randomize();
my $startres = IO::Socket::SSL->start_SSL(
$self->{sock},
SSL_version => $self->{ssl_version} || "SSLv3 TLSv1",
SSL_startHandshake => 0,
);
unless ( $startres ) {
croak "Couldn't start TLS: " . IO::Socket::SSL::errstr() . "\n";
}
$self->_debug( caller, __LINE__, 'starttls', "TLS initialization done" ) if $self->{debug};
1;
},
# process => sub { push @lines, $_[0] if $_[0] =~ /^(?: \s+\S+ | [^:]+: )/x },
);
}
sub login {
my ( $self, $user, $pass ) = @_;
$pass = _escape($pass);
return $self->_process_cmd(
cmd => [ LOGIN => qq[$user $pass] ],
final => sub { 1 },
process => sub { },
);
}
sub separator {
my ( $self, ) = @_;
my $sep;
return $self->_process_cmd (
cmd => [ LIST => qq["" ""] ],
final => sub { $sep },
process => sub { (undef,undef,undef,$sep,undef) = split /\s/smx , $_[0];
$sep =~ s/["]//g; },
);
}
sub _clear_cache {
my $self = shift;
my $cb = $self->current_box;
push @_, $cb if $cb and not @_;
return unless @_;
for my $box (@_) {
delete $self->{BOXES}{$box};
}
delete $self->{last};
return 1;
}
sub uidnext {
my $self = shift;
my $mbox = shift || $self->current_box || "INBOX";
return $self->status($mbox => 'uidnext');
}
sub uidvalidity {
my $self = shift;
my $mbox = shift || $self->current_box || "INBOX";
( run in 1.590 second using v1.01-cache-2.11-cpan-39bf76dae61 )