1# Net::POP3.pm
2#
3# Copyright (C) 1995-2004 Graham Barr.  All rights reserved.
4# Copyright (C) 2013-2016 Steve Hay.  All rights reserved.
5# This module is free software; you can redistribute it and/or modify it under
6# the same terms as Perl itself, i.e. under the terms of either the GNU General
7# Public License or the Artistic License, as specified in the F<LICENCE> file.
8
9package Net::POP3;
10
11use 5.008001;
12
13use strict;
14use warnings;
15
16use Carp;
17use IO::Socket;
18use Net::Cmd;
19use Net::Config;
20
21our $VERSION = "3.11";
22
23# Code for detecting if we can use SSL
24my $ssl_class = eval {
25  require IO::Socket::SSL;
26  # first version with default CA on most platforms
27  no warnings 'numeric';
28  IO::Socket::SSL->VERSION(2.007);
29} && 'IO::Socket::SSL';
30
31my $nossl_warn = !$ssl_class &&
32  'To use SSL please install IO::Socket::SSL with version>=2.007';
33
34# Code for detecting if we can use IPv6
35my $family_key = 'Domain';
36my $inet6_class = eval {
37  require IO::Socket::IP;
38  no warnings 'numeric';
39  IO::Socket::IP->VERSION(0.25) || die;
40  $family_key = 'Family';
41} && 'IO::Socket::IP' || eval {
42  require IO::Socket::INET6;
43  no warnings 'numeric';
44  IO::Socket::INET6->VERSION(2.62);
45} && 'IO::Socket::INET6';
46
47
48sub can_ssl   { $ssl_class };
49sub can_inet6 { $inet6_class };
50
51our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET');
52
53sub new {
54  my $self = shift;
55  my $type = ref($self) || $self;
56  my ($host, %arg);
57  if (@_ % 2) {
58    $host = shift;
59    %arg  = @_;
60  }
61  else {
62    %arg  = @_;
63    $host = delete $arg{Host};
64  }
65  my $hosts = defined $host ? [$host] : $NetConfig{pop3_hosts};
66  my $obj;
67
68  if ($arg{SSL}) {
69    # SSL from start
70    die $nossl_warn if !$ssl_class;
71    $arg{Port} ||= 995;
72  }
73
74  $arg{Timeout} = 120 if ! defined $arg{Timeout};
75
76  foreach my $h (@{$hosts}) {
77    $obj = $type->SUPER::new(
78      PeerAddr => ($host = $h),
79      PeerPort => $arg{Port} || 'pop3(110)',
80      Proto => 'tcp',
81      $family_key => $arg{Domain} || $arg{Family},
82      LocalAddr => $arg{LocalAddr},
83      LocalPort => exists($arg{ResvPort}) ? $arg{ResvPort} : $arg{LocalPort},
84      Timeout => $arg{Timeout},
85      )
86      and last;
87  }
88
89  return
90    unless defined $obj;
91
92  ${*$obj}{'net_pop3_arg'} = \%arg;
93  ${*$obj}{'net_pop3_host'} = $host;
94  if ($arg{SSL}) {
95    Net::POP3::_SSL->start_SSL($obj,%arg) or return;
96  }
97
98  $obj->autoflush(1);
99  $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
100
101  unless ($obj->response() == CMD_OK) {
102    $obj->close();
103    return;
104  }
105
106  ${*$obj}{'net_pop3_banner'} = $obj->message;
107
108  $obj;
109}
110
111
112sub host {
113  my $me = shift;
114  ${*$me}{'net_pop3_host'};
115}
116
117##
118## We don't want people sending me their passwords when they report problems
119## now do we :-)
120##
121
122
123sub debug_text { $_[2] =~ /^(pass|rpop)/i ? "$1 ....\n" : $_[2]; }
124
125
126sub login {
127  @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->login( USER, PASS )';
128  my ($me, $user, $pass) = @_;
129
130  if (@_ <= 2) {
131    ($user, $pass) = $me->_lookup_credentials($user);
132  }
133
134  $me->user($user)
135    and $me->pass($pass);
136}
137
138sub starttls {
139  my $self = shift;
140  $ssl_class or die $nossl_warn;
141  $self->_STLS or return;
142  Net::POP3::_SSL->start_SSL($self,
143    %{ ${*$self}{'net_pop3_arg'} }, # (ssl) args given in new
144    @_   # more (ssl) args
145  ) or return;
146  return 1;
147}
148
149sub apop {
150  @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->apop( USER, PASS )';
151  my ($me, $user, $pass) = @_;
152  my $banner;
153  my $md;
154
155  if (eval { local $SIG{__DIE__}; require Digest::MD5 }) {
156    $md = Digest::MD5->new();
157  }
158  elsif (eval { local $SIG{__DIE__}; require MD5 }) {
159    $md = MD5->new();
160  }
161  else {
162    carp "You need to install Digest::MD5 or MD5 to use the APOP command";
163    return;
164  }
165
166  return
167    unless ($banner = (${*$me}{'net_pop3_banner'} =~ /(<.*>)/)[0]);
168
169  if (@_ <= 2) {
170    ($user, $pass) = $me->_lookup_credentials($user);
171  }
172
173  $md->add($banner, $pass);
174
175  return
176    unless ($me->_APOP($user, $md->hexdigest));
177
178  $me->_get_mailbox_count();
179}
180
181
182sub user {
183  @_ == 2 or croak 'usage: $pop3->user( USER )';
184  $_[0]->_USER($_[1]) ? 1 : undef;
185}
186
187
188sub pass {
189  @_ == 2 or croak 'usage: $pop3->pass( PASS )';
190
191  my ($me, $pass) = @_;
192
193  return
194    unless ($me->_PASS($pass));
195
196  $me->_get_mailbox_count();
197}
198
199
200sub reset {
201  @_ == 1 or croak 'usage: $obj->reset()';
202
203  my $me = shift;
204
205  return 0
206    unless ($me->_RSET);
207
208  if (defined ${*$me}{'net_pop3_mail'}) {
209    local $_;
210    foreach (@{${*$me}{'net_pop3_mail'}}) {
211      delete $_->{'net_pop3_deleted'};
212    }
213  }
214}
215
216
217sub last {
218  @_ == 1 or croak 'usage: $obj->last()';
219
220  return
221    unless $_[0]->_LAST && $_[0]->message =~ /(\d+)/;
222
223  return $1;
224}
225
226
227sub top {
228  @_ == 2 || @_ == 3 or croak 'usage: $pop3->top( MSGNUM [, NUMLINES ])';
229  my $me = shift;
230
231  return
232    unless $me->_TOP($_[0], $_[1] || 0);
233
234  $me->read_until_dot;
235}
236
237
238sub popstat {
239  @_ == 1 or croak 'usage: $pop3->popstat()';
240  my $me = shift;
241
242  return ()
243    unless $me->_STAT && $me->message =~ /(\d+)\D+(\d+)/;
244
245  ($1 || 0, $2 || 0);
246}
247
248
249sub list {
250  @_ == 1 || @_ == 2 or croak 'usage: $pop3->list( [ MSGNUM ] )';
251  my $me = shift;
252
253  return
254    unless $me->_LIST(@_);
255
256  if (@_) {
257    $me->message =~ /\d+\D+(\d+)/;
258    return $1 || undef;
259  }
260
261  my $info = $me->read_until_dot
262    or return;
263
264  my %hash = map { (/(\d+)\D+(\d+)/) } @$info;
265
266  return \%hash;
267}
268
269
270sub get {
271  @_ == 2 or @_ == 3 or croak 'usage: $pop3->get( MSGNUM [, FH ])';
272  my $me = shift;
273
274  return
275    unless $me->_RETR(shift);
276
277  $me->read_until_dot(@_);
278}
279
280
281sub getfh {
282  @_ == 2 or croak 'usage: $pop3->getfh( MSGNUM )';
283  my $me = shift;
284
285  return unless $me->_RETR(shift);
286  return $me->tied_fh;
287}
288
289
290sub delete {
291  @_ == 2 or croak 'usage: $pop3->delete( MSGNUM )';
292  my $me = shift;
293  return 0 unless $me->_DELE(@_);
294  ${*$me}{'net_pop3_deleted'} = 1;
295}
296
297
298sub uidl {
299  @_ == 1 || @_ == 2 or croak 'usage: $pop3->uidl( [ MSGNUM ] )';
300  my $me = shift;
301  my $uidl;
302
303  $me->_UIDL(@_)
304    or return;
305  if (@_) {
306    $uidl = ($me->message =~ /\d+\s+([\041-\176]+)/)[0];
307  }
308  else {
309    my $ref = $me->read_until_dot
310      or return;
311    $uidl = {};
312    foreach my $ln (@$ref) {
313      my ($msg, $uid) = $ln =~ /^\s*(\d+)\s+([\041-\176]+)/;
314      $uidl->{$msg} = $uid;
315    }
316  }
317  return $uidl;
318}
319
320
321sub ping {
322  @_ == 2 or croak 'usage: $pop3->ping( USER )';
323  my $me = shift;
324
325  return () unless $me->_PING(@_) && $me->message =~ /(\d+)\D+(\d+)/;
326
327  ($1 || 0, $2 || 0);
328}
329
330
331sub _lookup_credentials {
332  my ($me, $user) = @_;
333
334  require Net::Netrc;
335
336       $user ||= eval { local $SIG{__DIE__}; (getpwuid($>))[0] }
337    || $ENV{NAME}
338    || $ENV{USER}
339    || $ENV{LOGNAME};
340
341  my $m = Net::Netrc->lookup(${*$me}{'net_pop3_host'}, $user);
342  $m ||= Net::Netrc->lookup(${*$me}{'net_pop3_host'});
343
344  my $pass = $m
345    ? $m->password || ""
346    : "";
347
348  ($user, $pass);
349}
350
351
352sub _get_mailbox_count {
353  my ($me) = @_;
354  my $ret = ${*$me}{'net_pop3_count'} =
355    ($me->message =~ /(\d+)\s+message/io) ? $1 : ($me->popstat)[0];
356
357  $ret ? $ret : "0E0";
358}
359
360
361sub _STAT { shift->command('STAT'       )->response() == CMD_OK }
362sub _LIST { shift->command('LIST',    @_)->response() == CMD_OK }
363sub _RETR { shift->command('RETR', $_[0])->response() == CMD_OK }
364sub _DELE { shift->command('DELE', $_[0])->response() == CMD_OK }
365sub _NOOP { shift->command('NOOP'       )->response() == CMD_OK }
366sub _RSET { shift->command('RSET'       )->response() == CMD_OK }
367sub _QUIT { shift->command('QUIT'       )->response() == CMD_OK }
368sub _TOP  { shift->command( 'TOP',    @_)->response() == CMD_OK }
369sub _UIDL { shift->command('UIDL',    @_)->response() == CMD_OK }
370sub _USER { shift->command('USER', $_[0])->response() == CMD_OK }
371sub _PASS { shift->command('PASS', $_[0])->response() == CMD_OK }
372sub _APOP { shift->command('APOP',    @_)->response() == CMD_OK }
373sub _PING { shift->command('PING', $_[0])->response() == CMD_OK }
374sub _RPOP { shift->command('RPOP', $_[0])->response() == CMD_OK }
375sub _LAST { shift->command('LAST'       )->response() == CMD_OK }
376sub _CAPA { shift->command('CAPA'       )->response() == CMD_OK }
377sub _STLS { shift->command("STLS",     )->response() == CMD_OK }
378
379
380sub quit {
381  my $me = shift;
382
383  $me->_QUIT;
384  $me->close;
385}
386
387
388sub DESTROY {
389  my $me = shift;
390
391  if (defined fileno($me) and ${*$me}{'net_pop3_deleted'}) {
392    $me->reset;
393    $me->quit;
394  }
395}
396
397##
398## POP3 has weird responses, so we emulate them to look the same :-)
399##
400
401
402sub response {
403  my $cmd  = shift;
404  my $str  = $cmd->getline() or return;
405  my $code = "500";
406
407  $cmd->debug_print(0, $str)
408    if ($cmd->debug);
409
410  if ($str =~ s/^\+OK\s*//io) {
411    $code = "200";
412  }
413  elsif ($str =~ s/^\+\s*//io) {
414    $code = "300";
415  }
416  else {
417    $str =~ s/^-ERR\s*//io;
418  }
419
420  ${*$cmd}{'net_cmd_resp'} = [$str];
421  ${*$cmd}{'net_cmd_code'} = $code;
422
423  substr($code, 0, 1);
424}
425
426
427sub capa {
428  my $this = shift;
429  my ($capa, %capabilities);
430
431  # Fake a capability here
432  $capabilities{APOP} = '' if ($this->banner() =~ /<.*>/);
433
434  if ($this->_CAPA()) {
435    $capabilities{CAPA} = 1;
436    $capa = $this->read_until_dot();
437    %capabilities = (%capabilities, map {/^\s*(\S+)\s*(.*)/} @$capa);
438  }
439  else {
440
441    # Check AUTH for SASL capabilities
442    if ($this->command('AUTH')->response() == CMD_OK) {
443      my $mechanism = $this->read_until_dot();
444      $capabilities{SASL} = join " ", map {m/([A-Z0-9_-]+)/} @{$mechanism};
445    }
446  }
447
448  return ${*$this}{'net_pop3e_capabilities'} = \%capabilities;
449}
450
451
452sub capabilities {
453  my $this = shift;
454
455  ${*$this}{'net_pop3e_capabilities'} || $this->capa;
456}
457
458
459sub auth {
460  my ($self, $username, $password) = @_;
461
462  eval {
463    require MIME::Base64;
464    require Authen::SASL;
465  } or $self->set_status(500, ["Need MIME::Base64 and Authen::SASL todo auth"]), return 0;
466
467  my $capa       = $self->capa;
468  my $mechanisms = $capa->{SASL} || 'CRAM-MD5';
469
470  my $sasl;
471
472  if (ref($username) and UNIVERSAL::isa($username, 'Authen::SASL')) {
473    $sasl = $username;
474    my $user_mech = $sasl->mechanism || '';
475    my @user_mech = split(/\s+/, $user_mech);
476    my %user_mech;
477    @user_mech{@user_mech} = ();
478
479    my @server_mech = split(/\s+/, $mechanisms);
480    my @mech = @user_mech
481      ? grep { exists $user_mech{$_} } @server_mech
482      : @server_mech;
483    unless (@mech) {
484      $self->set_status(
485        500,
486        [ 'Client SASL mechanisms (',
487          join(', ', @user_mech),
488          ') do not match the SASL mechnism the server announces (',
489          join(', ', @server_mech), ')',
490        ]
491      );
492      return 0;
493    }
494
495    $sasl->mechanism(join(" ", @mech));
496  }
497  else {
498    die "auth(username, password)" if not length $username;
499    $sasl = Authen::SASL->new(
500      mechanism => $mechanisms,
501      callback  => {
502        user     => $username,
503        pass     => $password,
504        authname => $username,
505      }
506    );
507  }
508
509  # We should probably allow the user to pass the host, but I don't
510  # currently know and SASL mechanisms that are used by smtp that need it
511  my ($hostname) = split /:/, ${*$self}{'net_pop3_host'};
512  my $client = eval { $sasl->client_new('pop', $hostname, 0) };
513
514  unless ($client) {
515    my $mech = $sasl->mechanism;
516    $self->set_status(
517      500,
518      [ " Authen::SASL failure: $@",
519        '(please check if your local Authen::SASL installation',
520        "supports mechanism '$mech'"
521      ]
522    );
523    return 0;
524  }
525
526  my ($token) = $client->client_start
527    or do {
528    my $mech = $client->mechanism;
529    $self->set_status(
530      500,
531      [ ' Authen::SASL failure:  $client->client_start ',
532        "mechanism '$mech' hostname #$hostname#",
533        $client->error
534      ]
535    );
536    return 0;
537    };
538
539  # We don't support sasl mechanisms that encrypt the socket traffic.
540  # todo that we would really need to change the ISA hierarchy
541  # so we don't inherit from IO::Socket, but instead hold it in an attribute
542
543  my @cmd = ("AUTH", $client->mechanism);
544  my $code;
545
546  push @cmd, MIME::Base64::encode_base64($token, '')
547    if defined $token and length $token;
548
549  while (($code = $self->command(@cmd)->response()) == CMD_MORE) {
550
551    my ($token) = $client->client_step(MIME::Base64::decode_base64(($self->message)[0])) or do {
552      $self->set_status(
553        500,
554        [ ' Authen::SASL failure:  $client->client_step ',
555          "mechanism '", $client->mechanism, " hostname #$hostname#, ",
556          $client->error
557        ]
558      );
559      return 0;
560    };
561
562    @cmd = (MIME::Base64::encode_base64(defined $token ? $token : '', ''));
563  }
564
565  $code == CMD_OK;
566}
567
568
569sub banner {
570  my $this = shift;
571
572  return ${*$this}{'net_pop3_banner'};
573}
574
575{
576  package Net::POP3::_SSL;
577  our @ISA = ( $ssl_class ? ($ssl_class):(), 'Net::POP3' );
578  sub starttls { die "POP3 connection is already in SSL mode" }
579  sub start_SSL {
580    my ($class,$pop3,%arg) = @_;
581    delete @arg{ grep { !m{^SSL_} } keys %arg };
582    ( $arg{SSL_verifycn_name} ||= $pop3->host )
583        =~s{(?<!:):[\w()]+$}{}; # strip port
584    $arg{SSL_hostname} = $arg{SSL_verifycn_name}
585        if ! defined $arg{SSL_hostname} && $class->can_client_sni;
586    $arg{SSL_verifycn_scheme} ||= 'pop3';
587    my $ok = $class->SUPER::start_SSL($pop3,%arg);
588    $@ = $ssl_class->errstr if !$ok;
589    return $ok;
590  }
591}
592
593
594
5951;
596
597__END__
598
599=head1 NAME
600
601Net::POP3 - Post Office Protocol 3 Client class (RFC1939)
602
603=head1 SYNOPSIS
604
605    use Net::POP3;
606
607    # Constructors
608    $pop = Net::POP3->new('pop3host');
609    $pop = Net::POP3->new('pop3host', Timeout => 60);
610    $pop = Net::POP3->new('pop3host', SSL => 1, Timeout => 60);
611
612    if ($pop->login($username, $password) > 0) {
613      my $msgnums = $pop->list; # hashref of msgnum => size
614      foreach my $msgnum (keys %$msgnums) {
615        my $msg = $pop->get($msgnum);
616        print @$msg;
617        $pop->delete($msgnum);
618      }
619    }
620
621    $pop->quit;
622
623=head1 DESCRIPTION
624
625This module implements a client interface to the POP3 protocol, enabling
626a perl5 application to talk to POP3 servers. This documentation assumes
627that you are familiar with the POP3 protocol described in RFC1939.
628With L<IO::Socket::SSL> installed it also provides support for implicit and
629explicit TLS encryption, i.e. POP3S or POP3+STARTTLS.
630
631A new Net::POP3 object must be created with the I<new> method. Once
632this has been done, all POP3 commands are accessed via method calls
633on the object.
634
635The Net::POP3 class is a subclass of Net::Cmd and (depending on avaibility) of
636IO::Socket::IP, IO::Socket::INET6 or IO::Socket::INET.
637
638
639=head1 CONSTRUCTOR
640
641=over 4
642
643=item new ( [ HOST ] [, OPTIONS ] )
644
645This is the constructor for a new Net::POP3 object. C<HOST> is the
646name of the remote host to which an POP3 connection is required.
647
648C<HOST> is optional. If C<HOST> is not given then it may instead be
649passed as the C<Host> option described below. If neither is given then
650the C<POP3_Hosts> specified in C<Net::Config> will be used.
651
652C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
653Possible options are:
654
655B<Host> - POP3 host to connect to. It may be a single scalar, as defined for
656the C<PeerAddr> option in L<IO::Socket::INET>, or a reference to
657an array with hosts to try in turn. The L</host> method will return the value
658which was used to connect to the host.
659
660B<Port> - port to connect to.
661Default - 110 for plain POP3 and 995 for POP3s (direct SSL).
662
663B<SSL> - If the connection should be done from start with SSL, contrary to later
664upgrade with C<starttls>.
665You can use SSL arguments as documented in L<IO::Socket::SSL>, but it will
666usually use the right arguments already.
667
668B<LocalAddr> and B<LocalPort> - These parameters are passed directly
669to IO::Socket to allow binding the socket to a specific local address and port.
670For compatibility with older versions B<ResvPort> can be used instead of
671B<LocalPort>.
672
673B<Domain> - This parameter is passed directly to IO::Socket and makes it
674possible to enforce IPv4 connections even if L<IO::Socket::IP> is used as super
675class. Alternatively B<Family> can be used.
676
677B<Timeout> - Maximum time, in seconds, to wait for a response from the
678POP3 server (default: 120)
679
680B<Debug> - Enable debugging information
681
682=back
683
684=head1 METHODS
685
686Unless otherwise stated all methods return either a I<true> or I<false>
687value, with I<true> meaning that the operation was a success. When a method
688states that it returns a value, failure will be returned as I<undef> or an
689empty list.
690
691C<Net::POP3> inherits from C<Net::Cmd> so methods defined in C<Net::Cmd> may
692be used to send commands to the remote POP3 server in addition to the methods
693documented here.
694
695=over 4
696
697=item host ()
698
699Returns the value used by the constructor, and passed to IO::Socket::INET,
700to connect to the host.
701
702=item auth ( USERNAME, PASSWORD )
703
704Attempt SASL authentication.
705
706=item user ( USER )
707
708Send the USER command.
709
710=item pass ( PASS )
711
712Send the PASS command. Returns the number of messages in the mailbox.
713
714=item login ( [ USER [, PASS ]] )
715
716Send both the USER and PASS commands. If C<PASS> is not given the
717C<Net::POP3> uses C<Net::Netrc> to lookup the password using the host
718and username. If the username is not specified then the current user name
719will be used.
720
721Returns the number of messages in the mailbox. However if there are no
722messages on the server the string C<"0E0"> will be returned. This is
723will give a true value in a boolean context, but zero in a numeric context.
724
725If there was an error authenticating the user then I<undef> will be returned.
726
727=item starttls ( SSLARGS )
728
729Upgrade existing plain connection to SSL.
730You can use SSL arguments as documented in L<IO::Socket::SSL>, but it will
731usually use the right arguments already.
732
733=item apop ( [ USER [, PASS ]] )
734
735Authenticate with the server identifying as C<USER> with password C<PASS>.
736Similar to L</login>, but the password is not sent in clear text.
737
738To use this method you must have the Digest::MD5 or the MD5 module installed,
739otherwise this method will return I<undef>.
740
741=item banner ()
742
743Return the sever's connection banner
744
745=item capa ()
746
747Return a reference to a hash of the capabilities of the server.  APOP
748is added as a pseudo capability.  Note that I've been unable to
749find a list of the standard capability values, and some appear to
750be multi-word and some are not.  We make an attempt at intelligently
751parsing them, but it may not be correct.
752
753=item  capabilities ()
754
755Just like capa, but only uses a cache from the last time we asked
756the server, so as to avoid asking more than once.
757
758=item top ( MSGNUM [, NUMLINES ] )
759
760Get the header and the first C<NUMLINES> of the body for the message
761C<MSGNUM>. Returns a reference to an array which contains the lines of text
762read from the server.
763
764=item list ( [ MSGNUM ] )
765
766If called with an argument the C<list> returns the size of the message
767in octets.
768
769If called without arguments a reference to a hash is returned. The
770keys will be the C<MSGNUM>'s of all undeleted messages and the values will
771be their size in octets.
772
773=item get ( MSGNUM [, FH ] )
774
775Get the message C<MSGNUM> from the remote mailbox. If C<FH> is not given
776then get returns a reference to an array which contains the lines of
777text read from the server. If C<FH> is given then the lines returned
778from the server are printed to the filehandle C<FH>.
779
780=item getfh ( MSGNUM )
781
782As per get(), but returns a tied filehandle.  Reading from this
783filehandle returns the requested message.  The filehandle will return
784EOF at the end of the message and should not be reused.
785
786=item last ()
787
788Returns the highest C<MSGNUM> of all the messages accessed.
789
790=item popstat ()
791
792Returns a list of two elements. These are the number of undeleted
793elements and the size of the mbox in octets.
794
795=item ping ( USER )
796
797Returns a list of two elements. These are the number of new messages
798and the total number of messages for C<USER>.
799
800=item uidl ( [ MSGNUM ] )
801
802Returns a unique identifier for C<MSGNUM> if given. If C<MSGNUM> is not
803given C<uidl> returns a reference to a hash where the keys are the
804message numbers and the values are the unique identifiers.
805
806=item delete ( MSGNUM )
807
808Mark message C<MSGNUM> to be deleted from the remote mailbox. All messages
809that are marked to be deleted will be removed from the remote mailbox
810when the server connection closed.
811
812=item reset ()
813
814Reset the status of the remote POP3 server. This includes resetting the
815status of all messages to not be deleted.
816
817=item quit ()
818
819Quit and close the connection to the remote POP3 server. Any messages marked
820as deleted will be deleted from the remote mailbox.
821
822=item can_inet6 ()
823
824Returns whether we can use IPv6.
825
826=item can_ssl ()
827
828Returns whether we can use SSL.
829
830=back
831
832=head1 NOTES
833
834If a C<Net::POP3> object goes out of scope before C<quit> method is called
835then the C<reset> method will called before the connection is closed. This
836means that any messages marked to be deleted will not be.
837
838=head1 SEE ALSO
839
840L<Net::Netrc>,
841L<Net::Cmd>,
842L<IO::Socket::SSL>
843
844=head1 AUTHOR
845
846Graham Barr E<lt>F<gbarr@pobox.com>E<gt>.
847
848Steve Hay E<lt>F<shay@cpan.org>E<gt> is now maintaining libnet as of version
8491.22_02.
850
851=head1 COPYRIGHT
852
853Copyright (C) 1995-2004 Graham Barr.  All rights reserved.
854
855Copyright (C) 2013-2016 Steve Hay.  All rights reserved.
856
857=head1 LICENCE
858
859This module is free software; you can redistribute it and/or modify it under the
860same terms as Perl itself, i.e. under the terms of either the GNU General Public
861License or the Artistic License, as specified in the F<LICENCE> file.
862
863=cut
864