This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Sync with libnet-1.12
[perl5.git] / lib / Net / POP3.pm
CommitLineData
406c51ee
JH
1# Net::POP3.pm
2#
3# Copyright (c) 1995-1997 Graham Barr <gbarr@pobox.com>. All rights reserved.
4# This program is free software; you can redistribute it and/or
5# modify it under the same terms as Perl itself.
6
7package Net::POP3;
8
9use strict;
10use IO::Socket;
11use vars qw(@ISA $VERSION $debug);
12use Net::Cmd;
13use Carp;
14use Net::Config;
15
12df23ee 16$VERSION = "2.23"; # $Id: //depot/libnet/Net/POP3.pm#22 $
406c51ee
JH
17
18@ISA = qw(Net::Cmd IO::Socket::INET);
19
20sub new
21{
22 my $self = shift;
23 my $type = ref($self) || $self;
24 my $host = shift if @_ % 2;
25 my %arg = @_;
26 my $hosts = defined $host ? [ $host ] : $NetConfig{pop3_hosts};
27 my $obj;
28 my @localport = exists $arg{ResvPort} ? ( LocalPort => $arg{ResvPort} ): ();
29
30 my $h;
31 foreach $h (@{$hosts})
32 {
33 $obj = $type->SUPER::new(PeerAddr => ($host = $h),
34 PeerPort => $arg{Port} || 'pop3(110)',
35 Proto => 'tcp',
36 @localport,
37 Timeout => defined $arg{Timeout}
38 ? $arg{Timeout}
39 : 120
40 ) and last;
41 }
42
43 return undef
44 unless defined $obj;
45
46 ${*$obj}{'net_pop3_host'} = $host;
47
48 $obj->autoflush(1);
49 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
50
51 unless ($obj->response() == CMD_OK)
52 {
53 $obj->close();
54 return undef;
55 }
56
57 ${*$obj}{'net_pop3_banner'} = $obj->message;
58
59 $obj;
60}
61
62##
63## We don't want people sending me their passwords when they report problems
64## now do we :-)
65##
66
67sub debug_text { $_[2] =~ /^(pass|rpop)/i ? "$1 ....\n" : $_[2]; }
68
69sub login
70{
71 @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->login( USER, PASS )';
72 my($me,$user,$pass) = @_;
73
12df23ee
GB
74 if (@_ <= 2) {
75 ($user, $pass) = $me->_lookup_credentials($user);
76 }
406c51ee
JH
77
78 $me->user($user) and
79 $me->pass($pass);
80}
81
82sub apop
83{
84 @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->apop( USER, PASS )';
85 my($me,$user,$pass) = @_;
86 my $banner;
12df23ee
GB
87 my $md;
88
89 if (eval { local $SIG{__DIE__}; require Digest::MD5 }) {
90 $md = Digest::MD5->new();
91 } elsif (eval { local $SIG{__DIE__}; require MD5 }) {
92 $md = MD5->new();
93 } else {
94 carp "You need to install Digest::MD5 or MD5 to use the APOP command";
406c51ee 95 return undef;
12df23ee 96 }
406c51ee
JH
97
98 return undef
99 unless ( $banner = (${*$me}{'net_pop3_banner'} =~ /(<.*>)/)[0] );
100
12df23ee
GB
101 if (@_ <= 2) {
102 ($user, $pass) = $me->_lookup_credentials($user);
103 }
406c51ee 104
406c51ee
JH
105 $md->add($banner,$pass);
106
107 return undef
108 unless($me->_APOP($user,$md->hexdigest));
109
12df23ee 110 $me->_get_mailbox_count();
406c51ee
JH
111}
112
113sub user
114{
115 @_ == 2 or croak 'usage: $pop3->user( USER )';
116 $_[0]->_USER($_[1]) ? 1 : undef;
117}
118
119sub pass
120{
121 @_ == 2 or croak 'usage: $pop3->pass( PASS )';
122
123 my($me,$pass) = @_;
124
125 return undef
126 unless($me->_PASS($pass));
127
12df23ee 128 $me->_get_mailbox_count();
406c51ee
JH
129}
130
131sub reset
132{
133 @_ == 1 or croak 'usage: $obj->reset()';
134
135 my $me = shift;
136
137 return 0
138 unless($me->_RSET);
686337f3 139
406c51ee
JH
140 if(defined ${*$me}{'net_pop3_mail'})
141 {
142 local $_;
143 foreach (@{${*$me}{'net_pop3_mail'}})
144 {
145 delete $_->{'net_pop3_deleted'};
146 }
147 }
148}
149
150sub last
151{
152 @_ == 1 or croak 'usage: $obj->last()';
153
154 return undef
155 unless $_[0]->_LAST && $_[0]->message =~ /(\d+)/;
156
157 return $1;
158}
159
160sub top
161{
162 @_ == 2 || @_ == 3 or croak 'usage: $pop3->top( MSGNUM [, NUMLINES ])';
163 my $me = shift;
164
165 return undef
166 unless $me->_TOP($_[0], $_[1] || 0);
167
168 $me->read_until_dot;
169}
170
171sub popstat
172{
173 @_ == 1 or croak 'usage: $pop3->popstat()';
174 my $me = shift;
175
176 return ()
177 unless $me->_STAT && $me->message =~ /(\d+)\D+(\d+)/;
178
179 ($1 || 0, $2 || 0);
180}
181
182sub list
183{
184 @_ == 1 || @_ == 2 or croak 'usage: $pop3->list( [ MSGNUM ] )';
185 my $me = shift;
186
187 return undef
188 unless $me->_LIST(@_);
189
190 if(@_)
191 {
192 $me->message =~ /\d+\D+(\d+)/;
193 return $1 || undef;
194 }
686337f3 195
406c51ee
JH
196 my $info = $me->read_until_dot
197 or return undef;
198
199 my %hash = map { (/(\d+)\D+(\d+)/) } @$info;
200
201 return \%hash;
202}
203
204sub get
205{
206 @_ == 2 or @_ == 3 or croak 'usage: $pop3->get( MSGNUM [, FH ])';
207 my $me = shift;
208
209 return undef
210 unless $me->_RETR(shift);
211
212 $me->read_until_dot(@_);
213}
214
12df23ee
GB
215sub getfh
216{
217 @_ == 2 or croak 'usage: $pop3->getfh( MSGNUM )';
218 my $me = shift;
219
220 return unless $me->_RETR(shift);
221 return $me->tied_fh;
222}
223
224
225
406c51ee
JH
226sub delete
227{
228 @_ == 2 or croak 'usage: $pop3->delete( MSGNUM )';
229 $_[0]->_DELE($_[1]);
230}
231
232sub uidl
233{
234 @_ == 1 || @_ == 2 or croak 'usage: $pop3->uidl( [ MSGNUM ] )';
235 my $me = shift;
236 my $uidl;
237
238 $me->_UIDL(@_) or
239 return undef;
240 if(@_)
241 {
242 $uidl = ($me->message =~ /\d+\s+([\041-\176]+)/)[0];
243 }
244 else
245 {
246 my $ref = $me->read_until_dot
247 or return undef;
248 my $ln;
249 $uidl = {};
250 foreach $ln (@$ref) {
251 my($msg,$uid) = $ln =~ /^\s*(\d+)\s+([\041-\176]+)/;
252 $uidl->{$msg} = $uid;
253 }
254 }
255 return $uidl;
256}
257
258sub ping
259{
260 @_ == 2 or croak 'usage: $pop3->ping( USER )';
261 my $me = shift;
262
263 return () unless $me->_PING(@_) && $me->message =~ /(\d+)\D+(\d+)/;
264
265 ($1 || 0, $2 || 0);
266}
267
12df23ee
GB
268sub _lookup_credentials
269{
270 my ($me, $user) = @_;
271
272 require Net::Netrc;
273
274 $user ||= eval { local $SIG{__DIE__}; (getpwuid($>))[0] } ||
275 $ENV{NAME} || $ENV{USER} || $ENV{LOGNAME};
276
277 my $m = Net::Netrc->lookup(${*$me}{'net_pop3_host'},$user);
278 $m ||= Net::Netrc->lookup(${*$me}{'net_pop3_host'});
279
280 my $pass = $m ? $m->password || ""
281 : "";
282
283 ($user, $pass);
284}
285
286sub _get_mailbox_count
287{
288 my ($me) = @_;
289 my $ret = ${*$me}{'net_pop3_count'} = ($me->message =~ /(\d+)\s+message/io)
290 ? $1 : ($me->popstat)[0];
291
292 $ret ? $ret : "0E0";
293}
294
686337f3 295
406c51ee
JH
296sub _STAT { shift->command('STAT')->response() == CMD_OK }
297sub _LIST { shift->command('LIST',@_)->response() == CMD_OK }
298sub _RETR { shift->command('RETR',$_[0])->response() == CMD_OK }
299sub _DELE { shift->command('DELE',$_[0])->response() == CMD_OK }
300sub _NOOP { shift->command('NOOP')->response() == CMD_OK }
301sub _RSET { shift->command('RSET')->response() == CMD_OK }
302sub _QUIT { shift->command('QUIT')->response() == CMD_OK }
303sub _TOP { shift->command('TOP', @_)->response() == CMD_OK }
304sub _UIDL { shift->command('UIDL',@_)->response() == CMD_OK }
305sub _USER { shift->command('USER',$_[0])->response() == CMD_OK }
306sub _PASS { shift->command('PASS',$_[0])->response() == CMD_OK }
307sub _APOP { shift->command('APOP',@_)->response() == CMD_OK }
308sub _PING { shift->command('PING',$_[0])->response() == CMD_OK }
309
310sub _RPOP { shift->command('RPOP',$_[0])->response() == CMD_OK }
311sub _LAST { shift->command('LAST')->response() == CMD_OK }
312
313sub quit
314{
315 my $me = shift;
316
317 $me->_QUIT;
318 $me->close;
319}
320
321sub DESTROY
322{
323 my $me = shift;
324
325 if(defined fileno($me))
326 {
327 $me->reset;
328 $me->quit;
329 }
330}
331
332##
333## POP3 has weird responses, so we emulate them to look the same :-)
334##
335
336sub response
337{
338 my $cmd = shift;
339 my $str = $cmd->getline() || return undef;
340 my $code = "500";
341
342 $cmd->debug_print(0,$str)
343 if ($cmd->debug);
344
345 if($str =~ s/^\+OK\s+//io)
346 {
347 $code = "200"
348 }
349 else
350 {
351 $str =~ s/^-ERR\s+//io;
352 }
353
354 ${*$cmd}{'net_cmd_resp'} = [ $str ];
355 ${*$cmd}{'net_cmd_code'} = $code;
356
357 substr($code,0,1);
358}
359
3601;
361
362__END__
363
364=head1 NAME
365
12df23ee 366Net::POP3 - Post Office Protocol 3 Client class (RFC1939)
406c51ee
JH
367
368=head1 SYNOPSIS
369
370 use Net::POP3;
686337f3 371
406c51ee
JH
372 # Constructors
373 $pop = Net::POP3->new('pop3host');
374 $pop = Net::POP3->new('pop3host', Timeout => 60);
375
376=head1 DESCRIPTION
377
378This module implements a client interface to the POP3 protocol, enabling
379a perl5 application to talk to POP3 servers. This documentation assumes
12df23ee 380that you are familiar with the POP3 protocol described in RFC1939.
406c51ee
JH
381
382A new Net::POP3 object must be created with the I<new> method. Once
383this has been done, all POP3 commands are accessed via method calls
384on the object.
385
386=head1 EXAMPLES
387
388 Need some small examples in here :-)
389
390=head1 CONSTRUCTOR
391
392=over 4
393
394=item new ( [ HOST, ] [ OPTIONS ] )
395
396This is the constructor for a new Net::POP3 object. C<HOST> is the
397name of the remote host to which a POP3 connection is required.
398
399If C<HOST> is not given, then the C<POP3_Host> specified in C<Net::Config>
400will be used.
401
402C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
403Possible options are:
404
405B<ResvPort> - If given then the socket for the C<Net::POP3> object
406will be bound to the local port given using C<bind> when the socket is
407created.
408
409B<Timeout> - Maximum time, in seconds, to wait for a response from the
410POP3 server (default: 120)
411
412B<Debug> - Enable debugging information
413
414=back
415
416=head1 METHODS
417
418Unless otherwise stated all methods return either a I<true> or I<false>
419value, with I<true> meaning that the operation was a success. When a method
420states that it returns a value, failure will be returned as I<undef> or an
421empty list.
422
423=over 4
424
425=item user ( USER )
426
427Send the USER command.
428
429=item pass ( PASS )
430
431Send the PASS command. Returns the number of messages in the mailbox.
432
433=item login ( [ USER [, PASS ]] )
434
d1be9408 435Send both the USER and PASS commands. If C<PASS> is not given the
406c51ee
JH
436C<Net::POP3> uses C<Net::Netrc> to lookup the password using the host
437and username. If the username is not specified then the current user name
438will be used.
439
440Returns the number of messages in the mailbox. However if there are no
441messages on the server the string C<"0E0"> will be returned. This is
442will give a true value in a boolean context, but zero in a numeric context.
443
444If there was an error authenticating the user then I<undef> will be returned.
445
12df23ee 446=item apop ( [ USER [, PASS ]] )
406c51ee
JH
447
448Authenticate with the server identifying as C<USER> with password C<PASS>.
12df23ee 449Similar to L</login>, but the password is not sent in clear text.
406c51ee 450
12df23ee
GB
451To use this method you must have the Digest::MD5 or the MD5 module installed,
452otherwise this method will return I<undef>.
406c51ee
JH
453
454=item top ( MSGNUM [, NUMLINES ] )
455
456Get the header and the first C<NUMLINES> of the body for the message
457C<MSGNUM>. Returns a reference to an array which contains the lines of text
458read from the server.
459
460=item list ( [ MSGNUM ] )
461
462If called with an argument the C<list> returns the size of the message
463in octets.
464
465If called without arguments a reference to a hash is returned. The
466keys will be the C<MSGNUM>'s of all undeleted messages and the values will
467be their size in octets.
468
469=item get ( MSGNUM [, FH ] )
470
471Get the message C<MSGNUM> from the remote mailbox. If C<FH> is not given
472then get returns a reference to an array which contains the lines of
473text read from the server. If C<FH> is given then the lines returned
474from the server are printed to the filehandle C<FH>.
475
12df23ee
GB
476=item getfh ( MSGNUM )
477
478As per get(), but returns a tied filehandle. Reading from this
479filehandle returns the requested message. The filehandle will return
480EOF at the end of the message and should not be reused.
481
406c51ee
JH
482=item last ()
483
484Returns the highest C<MSGNUM> of all the messages accessed.
485
486=item popstat ()
487
488Returns a list of two elements. These are the number of undeleted
489elements and the size of the mbox in octets.
490
491=item ping ( USER )
492
493Returns a list of two elements. These are the number of new messages
494and the total number of messages for C<USER>.
495
496=item uidl ( [ MSGNUM ] )
497
498Returns a unique identifier for C<MSGNUM> if given. If C<MSGNUM> is not
499given C<uidl> returns a reference to a hash where the keys are the
500message numbers and the values are the unique identifiers.
501
502=item delete ( MSGNUM )
503
504Mark message C<MSGNUM> to be deleted from the remote mailbox. All messages
505that are marked to be deleted will be removed from the remote mailbox
506when the server connection closed.
507
508=item reset ()
509
510Reset the status of the remote POP3 server. This includes reseting the
511status of all messages to not be deleted.
512
513=item quit ()
514
515Quit and close the connection to the remote POP3 server. Any messages marked
516as deleted will be deleted from the remote mailbox.
517
518=back
519
520=head1 NOTES
521
522If a C<Net::POP3> object goes out of scope before C<quit> method is called
523then the C<reset> method will called before the connection is closed. This
524means that any messages marked to be deleted will not be.
525
526=head1 SEE ALSO
527
12df23ee 528L<Net::Netrc>,
406c51ee
JH
529L<Net::Cmd>
530
531=head1 AUTHOR
532
533Graham Barr <gbarr@pobox.com>
534
535=head1 COPYRIGHT
536
537Copyright (c) 1995-1997 Graham Barr. All rights reserved.
538This program is free software; you can redistribute it and/or modify
539it under the same terms as Perl itself.
540
686337f3
JH
541=for html <hr>
542
12df23ee 543I<$Id: //depot/libnet/Net/POP3.pm#22 $>
686337f3 544
406c51ee 545=cut