This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
0811025b0a2611a64141468e7f9ed2b4050a728e
[perl5.git] / cpan / libnet / lib / Net / POP3.pm
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
9 package Net::POP3;
10
11 use 5.008001;
12
13 use strict;
14 use warnings;
15
16 use Carp;
17 use IO::Socket;
18 use Net::Cmd;
19 use Net::Config;
20
21 our $VERSION = "3.11";
22
23 # Code for detecting if we can use SSL
24 my $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
31 my $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
35 my $family_key = 'Domain';
36 my $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
48 sub can_ssl   { $ssl_class };
49 sub can_inet6 { $inet6_class };
50
51 our @ISA = ('Net::Cmd', $inet6_class || 'IO::Socket::INET');
52
53 sub 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
112 sub 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
123 sub debug_text { $_[2] =~ /^(pass|rpop)/i ? "$1 ....\n" : $_[2]; }
124
125
126 sub 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
138 sub 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
149 sub 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
182 sub user {
183   @_ == 2 or croak 'usage: $pop3->user( USER )';
184   $_[0]->_USER($_[1]) ? 1 : undef;
185 }
186
187
188 sub 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
200 sub 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
217 sub 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
227 sub 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
238 sub 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
249 sub 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
270 sub 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
281 sub 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
290 sub 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
298 sub 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
321 sub 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
331 sub _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
352 sub _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
361 sub _STAT { shift->command('STAT'       )->response() == CMD_OK }
362 sub _LIST { shift->command('LIST',    @_)->response() == CMD_OK }
363 sub _RETR { shift->command('RETR', $_[0])->response() == CMD_OK }
364 sub _DELE { shift->command('DELE', $_[0])->response() == CMD_OK }
365 sub _NOOP { shift->command('NOOP'       )->response() == CMD_OK }
366 sub _RSET { shift->command('RSET'       )->response() == CMD_OK }
367 sub _QUIT { shift->command('QUIT'       )->response() == CMD_OK }
368 sub _TOP  { shift->command( 'TOP',    @_)->response() == CMD_OK }
369 sub _UIDL { shift->command('UIDL',    @_)->response() == CMD_OK }
370 sub _USER { shift->command('USER', $_[0])->response() == CMD_OK }
371 sub _PASS { shift->command('PASS', $_[0])->response() == CMD_OK }
372 sub _APOP { shift->command('APOP',    @_)->response() == CMD_OK }
373 sub _PING { shift->command('PING', $_[0])->response() == CMD_OK }
374 sub _RPOP { shift->command('RPOP', $_[0])->response() == CMD_OK }
375 sub _LAST { shift->command('LAST'       )->response() == CMD_OK }
376 sub _CAPA { shift->command('CAPA'       )->response() == CMD_OK }
377 sub _STLS { shift->command("STLS",     )->response() == CMD_OK }
378
379
380 sub quit {
381   my $me = shift;
382
383   $me->_QUIT;
384   $me->close;
385 }
386
387
388 sub 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
402 sub 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
427 sub 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
452 sub capabilities {
453   my $this = shift;
454
455   ${*$this}{'net_pop3e_capabilities'} || $this->capa;
456 }
457
458
459 sub 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
569 sub 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
595 1;
596
597 __END__
598
599 =head1 NAME
600
601 Net::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
625 This module implements a client interface to the POP3 protocol, enabling
626 a perl5 application to talk to POP3 servers. This documentation assumes
627 that you are familiar with the POP3 protocol described in RFC1939.
628 With L<IO::Socket::SSL> installed it also provides support for implicit and
629 explicit TLS encryption, i.e. POP3S or POP3+STARTTLS.
630
631 A new Net::POP3 object must be created with the I<new> method. Once
632 this has been done, all POP3 commands are accessed via method calls
633 on the object.
634
635 The Net::POP3 class is a subclass of Net::Cmd and (depending on avaibility) of
636 IO::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
645 This is the constructor for a new Net::POP3 object. C<HOST> is the
646 name of the remote host to which an POP3 connection is required.
647
648 C<HOST> is optional. If C<HOST> is not given then it may instead be
649 passed as the C<Host> option described below. If neither is given then
650 the C<POP3_Hosts> specified in C<Net::Config> will be used.
651
652 C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
653 Possible options are:
654
655 B<Host> - POP3 host to connect to. It may be a single scalar, as defined for
656 the C<PeerAddr> option in L<IO::Socket::INET>, or a reference to
657 an array with hosts to try in turn. The L</host> method will return the value
658 which was used to connect to the host.
659
660 B<Port> - port to connect to.
661 Default - 110 for plain POP3 and 995 for POP3s (direct SSL).
662
663 B<SSL> - If the connection should be done from start with SSL, contrary to later
664 upgrade with C<starttls>.
665 You can use SSL arguments as documented in L<IO::Socket::SSL>, but it will
666 usually use the right arguments already.
667
668 B<LocalAddr> and B<LocalPort> - These parameters are passed directly
669 to IO::Socket to allow binding the socket to a specific local address and port.
670 For compatibility with older versions B<ResvPort> can be used instead of
671 B<LocalPort>.
672
673 B<Domain> - This parameter is passed directly to IO::Socket and makes it
674 possible to enforce IPv4 connections even if L<IO::Socket::IP> is used as super
675 class. Alternatively B<Family> can be used.
676
677 B<Timeout> - Maximum time, in seconds, to wait for a response from the
678 POP3 server (default: 120)
679
680 B<Debug> - Enable debugging information
681
682 =back
683
684 =head1 METHODS
685
686 Unless otherwise stated all methods return either a I<true> or I<false>
687 value, with I<true> meaning that the operation was a success. When a method
688 states that it returns a value, failure will be returned as I<undef> or an
689 empty list.
690
691 C<Net::POP3> inherits from C<Net::Cmd> so methods defined in C<Net::Cmd> may
692 be used to send commands to the remote POP3 server in addition to the methods
693 documented here.
694
695 =over 4
696
697 =item host ()
698
699 Returns the value used by the constructor, and passed to IO::Socket::INET,
700 to connect to the host.
701
702 =item auth ( USERNAME, PASSWORD )
703
704 Attempt SASL authentication.
705
706 =item user ( USER )
707
708 Send the USER command.
709
710 =item pass ( PASS )
711
712 Send the PASS command. Returns the number of messages in the mailbox.
713
714 =item login ( [ USER [, PASS ]] )
715
716 Send both the USER and PASS commands. If C<PASS> is not given the
717 C<Net::POP3> uses C<Net::Netrc> to lookup the password using the host
718 and username. If the username is not specified then the current user name
719 will be used.
720
721 Returns the number of messages in the mailbox. However if there are no
722 messages on the server the string C<"0E0"> will be returned. This is
723 will give a true value in a boolean context, but zero in a numeric context.
724
725 If there was an error authenticating the user then I<undef> will be returned.
726
727 =item starttls ( SSLARGS )
728
729 Upgrade existing plain connection to SSL.
730 You can use SSL arguments as documented in L<IO::Socket::SSL>, but it will
731 usually use the right arguments already.
732
733 =item apop ( [ USER [, PASS ]] )
734
735 Authenticate with the server identifying as C<USER> with password C<PASS>.
736 Similar to L</login>, but the password is not sent in clear text.
737
738 To use this method you must have the Digest::MD5 or the MD5 module installed,
739 otherwise this method will return I<undef>.
740
741 =item banner ()
742
743 Return the sever's connection banner
744
745 =item capa ()
746
747 Return a reference to a hash of the capabilities of the server.  APOP
748 is added as a pseudo capability.  Note that I've been unable to
749 find a list of the standard capability values, and some appear to
750 be multi-word and some are not.  We make an attempt at intelligently
751 parsing them, but it may not be correct.
752
753 =item  capabilities ()
754
755 Just like capa, but only uses a cache from the last time we asked
756 the server, so as to avoid asking more than once.
757
758 =item top ( MSGNUM [, NUMLINES ] )
759
760 Get the header and the first C<NUMLINES> of the body for the message
761 C<MSGNUM>. Returns a reference to an array which contains the lines of text
762 read from the server.
763
764 =item list ( [ MSGNUM ] )
765
766 If called with an argument the C<list> returns the size of the message
767 in octets.
768
769 If called without arguments a reference to a hash is returned. The
770 keys will be the C<MSGNUM>'s of all undeleted messages and the values will
771 be their size in octets.
772
773 =item get ( MSGNUM [, FH ] )
774
775 Get the message C<MSGNUM> from the remote mailbox. If C<FH> is not given
776 then get returns a reference to an array which contains the lines of
777 text read from the server. If C<FH> is given then the lines returned
778 from the server are printed to the filehandle C<FH>.
779
780 =item getfh ( MSGNUM )
781
782 As per get(), but returns a tied filehandle.  Reading from this
783 filehandle returns the requested message.  The filehandle will return
784 EOF at the end of the message and should not be reused.
785
786 =item last ()
787
788 Returns the highest C<MSGNUM> of all the messages accessed.
789
790 =item popstat ()
791
792 Returns a list of two elements. These are the number of undeleted
793 elements and the size of the mbox in octets.
794
795 =item ping ( USER )
796
797 Returns a list of two elements. These are the number of new messages
798 and the total number of messages for C<USER>.
799
800 =item uidl ( [ MSGNUM ] )
801
802 Returns a unique identifier for C<MSGNUM> if given. If C<MSGNUM> is not
803 given C<uidl> returns a reference to a hash where the keys are the
804 message numbers and the values are the unique identifiers.
805
806 =item delete ( MSGNUM )
807
808 Mark message C<MSGNUM> to be deleted from the remote mailbox. All messages
809 that are marked to be deleted will be removed from the remote mailbox
810 when the server connection closed.
811
812 =item reset ()
813
814 Reset the status of the remote POP3 server. This includes resetting the
815 status of all messages to not be deleted.
816
817 =item quit ()
818
819 Quit and close the connection to the remote POP3 server. Any messages marked
820 as deleted will be deleted from the remote mailbox.
821
822 =item can_inet6 ()
823
824 Returns whether we can use IPv6.
825
826 =item can_ssl ()
827
828 Returns whether we can use SSL.
829
830 =back
831
832 =head1 NOTES
833
834 If a C<Net::POP3> object goes out of scope before C<quit> method is called
835 then the C<reset> method will called before the connection is closed. This
836 means that any messages marked to be deleted will not be.
837
838 =head1 SEE ALSO
839
840 L<Net::Netrc>,
841 L<Net::Cmd>,
842 L<IO::Socket::SSL>
843
844 =head1 AUTHOR
845
846 Graham Barr E<lt>F<gbarr@pobox.com>E<gt>.
847
848 Steve Hay E<lt>F<shay@cpan.org>E<gt> is now maintaining libnet as of version
849 1.22_02.
850
851 =head1 COPYRIGHT
852
853 Copyright (C) 1995-2004 Graham Barr.  All rights reserved.
854
855 Copyright (C) 2013-2016 Steve Hay.  All rights reserved.
856
857 =head1 LICENCE
858
859 This module is free software; you can redistribute it and/or modify it under the
860 same terms as Perl itself, i.e. under the terms of either the GNU General Public
861 License or the Artistic License, as specified in the F<LICENCE> file.
862
863 =cut