[inseparable changes from patch from perl5.003_12 to perl5.003_13]
[p5sagit/p5-mst-13.2.git] / lib / Net / POP3.pm
CommitLineData
7e1af8bc 1# Net::POP3.pm
2#
3# Copyright (c) 1995 Graham Barr <Graham.Barr@tiuk.ti.com>. All rights
4# reserved. 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
9=head1 NAME
10
11Net::POP3 - Post Office Protocol 3 Client class (RFC1081)
12
13=head1 SYNOPSIS
14
15 use Net::POP3;
16
17 # Constructors
18 $pop = Net::POP3->new('pop3host');
19 $pop = Net::POP3->new('pop3host', Timeout => 60);
20
21=head1 DESCRIPTION
22
23This module implements a client interface to the POP3 protocol, enabling
24a perl5 application to talk to POP3 servers. This documentation assumes
25that you are familiar with the POP3 protocol described in RFC1081.
26
27A new Net::POP3 object must be created with the I<new> method. Once
28this has been done, all POP3 commands are accessed via method calls
29on the object.
30
31=head1 EXAMPLES
32
33 Need some small examples in here :-)
34
35=head1 CONSTRUCTOR
36
37=over 4
38
39=item new ( HOST, [ OPTIONS ] )
40
41This is the constructor for a new Net::POP3 object. C<HOST> is the
42name of the remote host to which a POP3 connection is required.
43
44C<OPTIONS> are passed in a hash like fasion, using key and value pairs.
45Possible options are:
46
47B<Timeout> - Maximum time, in seconds, to wait for a response from the
48POP3 server (default: 120)
49
50B<Debug> - Enable debugging information
51
52=back
53
54=head1 METHODS
55
56Unless otherwise stated all methods return either a I<true> or I<false>
57value, with I<true> meaning that the operation was a success. When a method
58states that it returns a value, falure will be returned as I<undef> or an
59empty list.
60
61=over 4
62
63=item user ( USER )
64
65Send the USER command.
66
67=item pass ( PASS )
68
69Send the PASS command. Returns the number of messages in the mailbox.
70
71=item login ( [ USER [, PASS ]] )
72
73Send both the the USER and PASS commands. If C<PASS> is not given the
74C<Net::POP3> uses C<Net::Netrc> to lookup the password using the host
75and username. If the username is not specified then the current user name
76will be used.
77
78Returns the number of messages in the mailbox.
79
80=item top ( MSGNUM [, NUMLINES ] )
81
82Get the header and the first C<NUMLINES> of the body for the message
83C<MSGNUM>. Returns a reference to an array which contains the lines of text
84read from the server.
85
86=item list ( [ MSGNUM ] )
87
88If called with an argument the C<list> returns the size of the messsage
89in octets.
90
91If called without arguments the a refererence to a hash is returned. The
92keys will be the C<MSGNUM>'s of all undeleted messages and the values will
93be their size in octets.
94
95=item get ( MSGNUM )
96
97Get the message C<MSGNUM> from the remote mailbox. Returns a reference to an
98array which contains the lines of text read from the server.
99
100=item last ()
101
102Returns the highest C<MSGNUM> of all the messages accessed.
103
104=item popstat ()
105
106Returns an array of two elements. These are the number of undeleted
107elements and the size of the mbox in octets.
108
109=item delete ( MSGNUM )
110
111Mark message C<MSGNUM> to be deleted from the remote mailbox. All messages
112that are marked to be deleted will be removed from the remote mailbox
113when the server connection closed.
114
115=item reset ()
116
117Reset the status of the remote POP3 server. This includes reseting the
118status of all messages to not be deleted.
119
120=item quit ()
121
122Quit and close the connection to the remote POP3 server. Any messages marked
123as deleted will be deleted from the remote mailbox.
124
125=back
126
127=head1 NOTES
128
129If a C<Net::POP3> object goes out of scope before C<quit> method is called
130then the C<reset> method will called before the connection is closed. This
131means that any messages marked to be deleted will not be.
132
133=head1 SEE ALSO
134
135L<Net::Netrc>
136L<Net::Cmd>
137
138=head1 AUTHOR
139
140Graham Barr <Graham.Barr@tiuk.ti.com>
141
142=head1 REVISION
143
144$Revision: 2.1 $
145$Date: 1996/07/26 06:44:44 $
146
147The VERSION is derived from the revision by changing each number after the
148first dot into a 2 digit number so
149
150 Revision 1.8 => VERSION 1.08
151 Revision 1.2.3 => VERSION 1.0203
152
153=head1 COPYRIGHT
154
155Copyright (c) 1995 Graham Barr. All rights reserved. This program is free
156software; you can redistribute it and/or modify it under the same terms
157as Perl itself.
158
159=cut
160
161use strict;
162use IO::Socket;
163use vars qw(@ISA $VERSION $debug);
164use Net::Cmd;
165use Carp;
166
167$VERSION = do{my @r=(q$Revision: 2.1 $=~/(\d+)/g);sprintf "%d."."%02d"x$#r,@r};
168
169@ISA = qw(Net::Cmd IO::Socket::INET);
170
171sub new
172{
173 my $self = shift;
174 my $type = ref($self) || $self;
175 my $host = shift;
176 my %arg = @_;
177 my $obj = $type->SUPER::new(PeerAddr => $host,
178 PeerPort => $arg{Port} || 'pop3(110)',
179 Proto => 'tcp',
180 Timeout => defined $arg{Timeout}
181 ? $arg{Timeout}
182 : 120
183 ) or return undef;
184
185 ${*$obj}{'net_pop3_host'} = $host;
186
187 $obj->autoflush(1);
188 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
189
190 unless ($obj->response() == CMD_OK)
191 {
192 $obj->close();
193 return undef;
194 }
195
196 $obj;
197}
198
199##
200## We don't want people sending me their passwords when they report problems
201## now do we :-)
202##
203
204sub debug_text { $_[2] =~ /^(pass|rpop)/i ? "$1 ....\n" : $_[2]; }
205
206sub login
207{
208 @_ >= 1 && @_ <= 3 or croak 'usage: $pop3->login( USER, PASS )';
209 my($me,$user,$pass) = @_;
210
211 if(@_ < 2)
212 {
213 require Net::Netrc;
214
215 $user ||= (getpwuid($>))[0];
216
217 my $m = Net::Netrc->lookup(${*$me}{'net_pop3_host'},$user);
218
219 $m ||= Net::Netrc->lookup(${*$me}{'net_pop3_host'});
220
221 $pass = $m ? $m->password || ""
222 : "";
223 }
224
225 $me->user($user) and
226 $me->pass($pass);
227}
228
229sub user
230{
231 @_ == 2 or croak 'usage: $pop3->user( USER )';
232 $_[0]->_USER($_[1]);
233}
234
235sub pass
236{
237 @_ == 2 or croak 'usage: $pop3->pass( PASS )';
238
239 my($me,$pass) = @_;
240
241 return undef
242 unless($me->_PASS($pass));
243
244 $me->message =~ /(\d+)\s+message/io;
245
246 ${*$me}{'net_pop3_count'} = $1 || 0;
247}
248
249sub reset
250{
251 @_ == 1 or croak 'usage: $obj->reset()';
252
253 my $me = shift;
254
255 return 0
256 unless($me->_RSET);
257
258 if(defined ${*$me}{'net_pop3_mail'})
259 {
260 local $_;
261 foreach (@{${*$me}{'net_pop3_mail'}})
262 {
263 delete $_->{'net_pop3_deleted'};
264 }
265 }
266}
267
268sub last
269{
270 @_ == 1 or croak 'usage: $obj->last()';
271
272 return undef
273 unless $_[0]->_LAST && $_[0]->message =~ /(\d+)/;
274
275 return $1;
276}
277
278sub top
279{
280 @_ == 2 || @_ == 3 or croak 'usage: $pop3->top( MSGNUM [, NUMLINES ])';
281 my $me = shift;
282
283 return undef
284 unless $me->_TOP($_[0], $_[1] || 0);
285
286 $me->read_until_dot;
287}
288
289sub popstat
290{
291 @_ == 1 or croak 'usage: $pop3->popstat()';
292 my $me = shift;
293
294 return ()
295 unless $me->_STAT && $me->message =~ /(\d+)\D+(\d+)/;
296
297 ($1 || 0, $2 || 0);
298}
299
300sub list
301{
302 @_ == 1 || @_ == 2 or croak 'usage: $pop3->list( [ MSGNUM ] )';
303 my $me = shift;
304
305 return undef
306 unless $me->_LIST(@_);
307
308 if(@_)
309 {
310 $me->message =~ /\d+\D+(\d+)/;
311 return $1 || undef;
312 }
313
314 my $info = $me->read_until_dot;
315 my %hash = ();
316 map { /(\d+)\D+(\d+)/; $hash{$1} = $2; } @$info;
317
318 return \%hash;
319}
320
321sub get
322{
323 @_ == 2 or croak 'usage: $pop3->get( MSGNUM )';
324 my $me = shift;
325
326 return undef
327 unless $me->_RETR(@_);
328
329 $me->read_until_dot;
330}
331
332sub delete
333{
334 @_ == 2 or croak 'usage: $pop3->delete( MSGNUM )';
335 $_[0]->_DELE($_[1]);
336}
337
338sub _USER { shift->command('USER',$_[0])->response() == CMD_OK }
339sub _PASS { shift->command('PASS',$_[0])->response() == CMD_OK }
340sub _RPOP { shift->command('RPOP',$_[0])->response() == CMD_OK }
341sub _RETR { shift->command('RETR',$_[0])->response() == CMD_OK }
342sub _DELE { shift->command('DELE',$_[0])->response() == CMD_OK }
343sub _TOP { shift->command('TOP', @_)->response() == CMD_OK }
344sub _LIST { shift->command('LIST',@_)->response() == CMD_OK }
345sub _NOOP { shift->command('NOOP')->response() == CMD_OK }
346sub _RSET { shift->command('RSET')->response() == CMD_OK }
347sub _LAST { shift->command('LAST')->response() == CMD_OK }
348sub _QUIT { shift->command('QUIT')->response() == CMD_OK }
349sub _STAT { shift->command('STAT')->response() == CMD_OK }
350
351sub close
352{
353 my $me = shift;
354
355 return 1
356 unless (ref($me) && defined fileno($me));
357
358 $me->_QUIT && $me->SUPER::close;
359}
360
361sub quit { shift->close }
362
363sub DESTROY
364{
365 my $me = shift;
366
367 if(fileno($me))
368 {
369 $me->reset;
370 $me->quit;
371 }
372}
373
374##
375## POP3 has weird responses, so we emulate them to look the same :-)
376##
377
378sub response
379{
380 my $cmd = shift;
381 my $str = $cmd->getline() || return undef;
382 my $code = "500";
383
384 $cmd->debug_print(0,$str)
385 if ($cmd->debug);
386
387 if($str =~ s/^\+OK\s+//io)
388 {
389 $code = "200"
390 }
391 else
392 {
393 $str =~ s/^\+ERR\s+//io;
394 }
395
396 ${*$cmd}{'net_cmd_resp'} = [ $str ];
397 ${*$cmd}{'net_cmd_code'} = $code;
398
399 substr($code,0,1);
400}
401
4021;