Let perl_clone copy PL_exit_flags
[p5sagit/p5-mst-13.2.git] / lib / Net / SMTP.pm
CommitLineData
406c51ee 1# Net::SMTP.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::SMTP;
8
9require 5.001;
10
11use strict;
12use vars qw($VERSION @ISA);
13use Socket 1.3;
14use Carp;
15use IO::Socket;
16use Net::Cmd;
17use Net::Config;
18
19$VERSION = "2.15"; # $Id$
20
21@ISA = qw(Net::Cmd IO::Socket::INET);
22
23sub new
24{
25 my $self = shift;
26 my $type = ref($self) || $self;
27 my $host = shift if @_ % 2;
28 my %arg = @_;
29 my $hosts = defined $host ? [ $host ] : $NetConfig{smtp_hosts};
30 my $obj;
31
32 my $h;
33 foreach $h (@{$hosts})
34 {
35 $obj = $type->SUPER::new(PeerAddr => ($host = $h),
36 PeerPort => $arg{Port} || 'smtp(25)',
37 Proto => 'tcp',
38 Timeout => defined $arg{Timeout}
39 ? $arg{Timeout}
40 : 120
41 ) and last;
42 }
43
44 return undef
45 unless defined $obj;
46
47 $obj->autoflush(1);
48
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_smtp_host'} = $host;
58
59 (${*$obj}{'net_smtp_banner'}) = $obj->message;
60 (${*$obj}{'net_smtp_domain'}) = $obj->message =~ /\A\s*(\S+)/;
61
62 unless($obj->hello($arg{Hello} || ""))
63 {
64 $obj->close();
65 return undef;
66 }
67
68 $obj;
69}
70
71##
72## User interface methods
73##
74
75sub banner
76{
77 my $me = shift;
78
79 return ${*$me}{'net_smtp_banner'} || undef;
80}
81
82sub domain
83{
84 my $me = shift;
85
86 return ${*$me}{'net_smtp_domain'} || undef;
87}
88
89sub etrn {
90 my $self = shift;
91 defined($self->supports('ETRN',500,["Command unknown: 'ETRN'"])) &&
92 $self->_ETRN(@_);
93}
94
95sub hello
96{
97 my $me = shift;
98 my $domain = shift ||
99 eval {
100 require Net::Domain;
101 Net::Domain::hostfqdn();
102 } ||
103 "";
104 my $ok = $me->_EHLO($domain);
105 my @msg = $me->message;
106
107 if($ok)
108 {
109 my $h = ${*$me}{'net_smtp_esmtp'} = {};
110 my $ln;
111 foreach $ln (@msg) {
112 $h->{$1} = $2
113 if $ln =~ /(\S+)\b[ \t]*([^\n]*)/;
114 }
115 }
116 elsif($me->status == CMD_ERROR)
117 {
118 @msg = $me->message
119 if $ok = $me->_HELO($domain);
120 }
121
122 $ok && $msg[0] =~ /\A(\S+)/
123 ? $1
124 : undef;
125}
126
127sub supports {
128 my $self = shift;
129 my $cmd = uc shift;
130 return ${*$self}{'net_smtp_esmtp'}->{$cmd}
131 if exists ${*$self}{'net_smtp_esmtp'}->{$cmd};
132 $self->set_status(@_)
133 if @_;
134 return;
135}
136
137sub _addr
138{
139 my $addr = shift || "";
140
141 return $1
142 if $addr =~ /(<[^>]+>)/so;
143
144 $addr =~ s/\n/ /sog;
145 $addr =~ s/(\A\s+|\s+\Z)//sog;
146
147 return "<" . $addr . ">";
148}
149
150
151sub mail
152{
153 my $me = shift;
154 my $addr = _addr(shift);
155 my $opts = "";
156
157 if(@_)
158 {
159 my %opt = @_;
160 my($k,$v);
161
162 if(exists ${*$me}{'net_smtp_esmtp'})
163 {
164 my $esmtp = ${*$me}{'net_smtp_esmtp'};
165
166 if(defined($v = delete $opt{Size}))
167 {
168 if(exists $esmtp->{SIZE})
169 {
170 $opts .= sprintf " SIZE=%d", $v + 0
171 }
172 else
173 {
174 carp 'Net::SMTP::mail: SIZE option not supported by host';
175 }
176 }
177
178 if(defined($v = delete $opt{Return}))
179 {
180 if(exists $esmtp->{DSN})
181 {
182 $opts .= " RET=" . uc $v
183 }
184 else
185 {
186 carp 'Net::SMTP::mail: DSN option not supported by host';
187 }
188 }
189
190 if(defined($v = delete $opt{Bits}))
191 {
192 if(exists $esmtp->{'8BITMIME'})
193 {
194 $opts .= $v == 8 ? " BODY=8BITMIME" : " BODY=7BIT"
195 }
196 else
197 {
198 carp 'Net::SMTP::mail: 8BITMIME option not supported by host';
199 }
200 }
201
202 if(defined($v = delete $opt{Transaction}))
203 {
204 if(exists $esmtp->{CHECKPOINT})
205 {
206 $opts .= " TRANSID=" . _addr($v);
207 }
208 else
209 {
210 carp 'Net::SMTP::mail: CHECKPOINT option not supported by host';
211 }
212 }
213
214 if(defined($v = delete $opt{Envelope}))
215 {
216 if(exists $esmtp->{DSN})
217 {
218 $v =~ s/([^\041-\176]|=|\+)/sprintf "+%02x", ord($1)/sge;
219 $opts .= " ENVID=$v"
220 }
221 else
222 {
223 carp 'Net::SMTP::mail: DSN option not supported by host';
224 }
225 }
226
227 carp 'Net::SMTP::recipient: unknown option(s) '
228 . join(" ", keys %opt)
229 . ' - ignored'
230 if scalar keys %opt;
231 }
232 else
233 {
234 carp 'Net::SMTP::mail: ESMTP not supported by host - options discarded :-(';
235 }
236 }
237
238 $me->_MAIL("FROM:".$addr.$opts);
239}
240
241sub send { shift->_SEND("FROM:" . _addr($_[0])) }
242sub send_or_mail { shift->_SOML("FROM:" . _addr($_[0])) }
243sub send_and_mail { shift->_SAML("FROM:" . _addr($_[0])) }
244
245sub reset
246{
247 my $me = shift;
248
249 $me->dataend()
250 if(exists ${*$me}{'net_smtp_lastch'});
251
252 $me->_RSET();
253}
254
255
256sub recipient
257{
258 my $smtp = shift;
259 my $opts = "";
260 my $skip_bad = 0;
261
262 if(@_ && ref($_[-1]))
263 {
264 my %opt = %{pop(@_)};
265 my $v;
266
267 $skip_bad = delete $opt{'SkipBad'};
268
269 if(exists ${*$smtp}{'net_smtp_esmtp'})
270 {
271 my $esmtp = ${*$smtp}{'net_smtp_esmtp'};
272
273 if(defined($v = delete $opt{Notify}))
274 {
275 if(exists $esmtp->{DSN})
276 {
277 $opts .= " NOTIFY=" . join(",",map { uc $_ } @$v)
278 }
279 else
280 {
281 carp 'Net::SMTP::recipient: DSN option not supported by host';
282 }
283 }
284
285 carp 'Net::SMTP::recipient: unknown option(s) '
286 . join(" ", keys %opt)
287 . ' - ignored'
288 if scalar keys %opt;
289 }
290 elsif(%opt)
291 {
292 carp 'Net::SMTP::recipient: ESMTP not supported by host - options discarded :-(';
293 }
294 }
295
296 my @ok;
297 my $addr;
298 foreach $addr (@_)
299 {
300 if($smtp->_RCPT("TO:" . _addr($addr) . $opts)) {
301 push(@ok,$addr) if $skip_bad;
302 }
303 elsif(!$skip_bad) {
304 return 0;
305 }
306 }
307
308 return $skip_bad ? @ok : 1;
309}
310
311sub to { shift->recipient(@_) }
312
313sub data
314{
315 my $me = shift;
316
317 my $ok = $me->_DATA() && $me->datasend(@_);
318
319 $ok && @_ ? $me->dataend
320 : $ok;
321}
322
323sub expand
324{
325 my $me = shift;
326
327 $me->_EXPN(@_) ? ($me->message)
328 : ();
329}
330
331
332sub verify { shift->_VRFY(@_) }
333
334sub help
335{
336 my $me = shift;
337
338 $me->_HELP(@_) ? scalar $me->message
339 : undef;
340}
341
342sub quit
343{
344 my $me = shift;
345
346 $me->_QUIT;
347 $me->close;
348}
349
350sub DESTROY
351{
352# ignore
353}
354
355##
356## RFC821 commands
357##
358
359sub _EHLO { shift->command("EHLO", @_)->response() == CMD_OK }
360sub _HELO { shift->command("HELO", @_)->response() == CMD_OK }
361sub _MAIL { shift->command("MAIL", @_)->response() == CMD_OK }
362sub _RCPT { shift->command("RCPT", @_)->response() == CMD_OK }
363sub _SEND { shift->command("SEND", @_)->response() == CMD_OK }
364sub _SAML { shift->command("SAML", @_)->response() == CMD_OK }
365sub _SOML { shift->command("SOML", @_)->response() == CMD_OK }
366sub _VRFY { shift->command("VRFY", @_)->response() == CMD_OK }
367sub _EXPN { shift->command("EXPN", @_)->response() == CMD_OK }
368sub _HELP { shift->command("HELP", @_)->response() == CMD_OK }
369sub _RSET { shift->command("RSET")->response() == CMD_OK }
370sub _NOOP { shift->command("NOOP")->response() == CMD_OK }
371sub _QUIT { shift->command("QUIT")->response() == CMD_OK }
372sub _DATA { shift->command("DATA")->response() == CMD_MORE }
373sub _TURN { shift->unsupported(@_); }
374sub _ETRN { shift->command("ETRN", @_)->response() == CMD_OK }
375
3761;
377
378__END__
379
380=head1 NAME
381
382Net::SMTP - Simple Mail Transfer Protocol Client
383
384=head1 SYNOPSIS
385
386 use Net::SMTP;
387
388 # Constructors
389 $smtp = Net::SMTP->new('mailhost');
390 $smtp = Net::SMTP->new('mailhost', Timeout => 60);
391
392=head1 DESCRIPTION
393
394This module implements a client interface to the SMTP and ESMTP
395protocol, enabling a perl5 application to talk to SMTP servers. This
396documentation assumes that you are familiar with the concepts of the
397SMTP protocol described in RFC821.
398
399A new Net::SMTP object must be created with the I<new> method. Once
400this has been done, all SMTP commands are accessed through this object.
401
402The Net::SMTP class is a subclass of Net::Cmd and IO::Socket::INET.
403
404=head1 EXAMPLES
405
406This example prints the mail domain name of the SMTP server known as mailhost:
407
408 #!/usr/local/bin/perl -w
409
410 use Net::SMTP;
411
412 $smtp = Net::SMTP->new('mailhost');
413 print $smtp->domain,"\n";
414 $smtp->quit;
415
416This example sends a small message to the postmaster at the SMTP server
417known as mailhost:
418
419 #!/usr/local/bin/perl -w
420
421 use Net::SMTP;
422
423 $smtp = Net::SMTP->new('mailhost');
424
425 $smtp->mail($ENV{USER});
426 $smtp->to('postmaster');
427
428 $smtp->data();
429 $smtp->datasend("To: postmaster\n");
430 $smtp->datasend("\n");
431 $smtp->datasend("A simple test message\n");
432 $smtp->dataend();
433
434 $smtp->quit;
435
436=head1 CONSTRUCTOR
437
438=over 4
439
440=item new Net::SMTP [ HOST, ] [ OPTIONS ]
441
442This is the constructor for a new Net::SMTP object. C<HOST> is the
443name of the remote host to which a SMTP connection is required.
444
445If C<HOST> is not given, then the C<SMTP_Host> specified in C<Net::Config>
446will be used.
447
448C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
449Possible options are:
450
451B<Hello> - SMTP requires that you identify yourself. This option
452specifies a string to pass as your mail domain. If not
453given a guess will be taken.
454
455B<Timeout> - Maximum time, in seconds, to wait for a response from the
456SMTP server (default: 120)
457
458B<Debug> - Enable debugging information
459
460
461Example:
462
463
464 $smtp = Net::SMTP->new('mailhost',
465 Hello => 'my.mail.domain'
466 Timeout => 30,
467 Debug => 1,
468 );
469
470=head1 METHODS
471
472Unless otherwise stated all methods return either a I<true> or I<false>
473value, with I<true> meaning that the operation was a success. When a method
474states that it returns a value, failure will be returned as I<undef> or an
475empty list.
476
477=over 4
478
479=item banner ()
480
481Returns the banner message which the server replied with when the
482initial connection was made.
483
484=item domain ()
485
486Returns the domain that the remote SMTP server identified itself as during
487connection.
488
489=item hello ( DOMAIN )
490
491Tell the remote server the mail domain which you are in using the EHLO
492command (or HELO if EHLO fails). Since this method is invoked
493automatically when the Net::SMTP object is constructed the user should
494normally not have to call it manually.
495
496=item etrn ( DOMAIN )
497
498Request a queue run for the DOMAIN given.
499
500=item mail ( ADDRESS [, OPTIONS] )
501
502=item send ( ADDRESS )
503
504=item send_or_mail ( ADDRESS )
505
506=item send_and_mail ( ADDRESS )
507
508Send the appropriate command to the server MAIL, SEND, SOML or SAML. C<ADDRESS>
509is the address of the sender. This initiates the sending of a message. The
510method C<recipient> should be called for each address that the message is to
511be sent to.
512
513The C<mail> method can some additional ESMTP OPTIONS which is passed
514in hash like fashion, using key and value pairs. Possible options are:
515
516 Size => <bytes>
517 Return => <???>
518 Bits => "7" | "8"
519 Transaction => <ADDRESS>
520 Envelope => <ENVID>
521
522
523=item reset ()
524
525Reset the status of the server. This may be called after a message has been
526initiated, but before any data has been sent, to cancel the sending of the
527message.
528
529=item recipient ( ADDRESS [, ADDRESS [ ...]] [, OPTIONS ] )
530
531Notify the server that the current message should be sent to all of the
532addresses given. Each address is sent as a separate command to the server.
533Should the sending of any address result in a failure then the
534process is aborted and a I<false> value is returned. It is up to the
535user to call C<reset> if they so desire.
536
537The C<recipient> method can some additional OPTIONS which is passed
538in hash like fashion, using key and value pairs. Possible options are:
539
540 Notify =>
541 SkipBad => ignore bad addresses
542
543If C<SkipBad> is true the C<recipient> will not return an error when a
544bad address is encountered and it will return an array of addresses
545that did succeed.
546
547=item to ( ADDRESS [, ADDRESS [...]] )
548
549A synonym for C<recipient>.
550
551=item data ( [ DATA ] )
552
553Initiate the sending of the data from the current message.
554
555C<DATA> may be a reference to a list or a list. If specified the contents
556of C<DATA> and a termination string C<".\r\n"> is sent to the server. And the
557result will be true if the data was accepted.
558
559If C<DATA> is not specified then the result will indicate that the server
560wishes the data to be sent. The data must then be sent using the C<datasend>
561and C<dataend> methods described in L<Net::Cmd>.
562
563=item expand ( ADDRESS )
564
565Request the server to expand the given address Returns an array
566which contains the text read from the server.
567
568=item verify ( ADDRESS )
569
570Verify that C<ADDRESS> is a legitimate mailing address.
571
572=item help ( [ $subject ] )
573
574Request help text from the server. Returns the text or undef upon failure
575
576=item quit ()
577
578Send the QUIT command to the remote SMTP server and close the socket connection.
579
580=back
581
582=head1 SEE ALSO
583
584L<Net::Cmd>
585
586=head1 AUTHOR
587
588Graham Barr <gbarr@pobox.com>
589
590=head1 COPYRIGHT
591
592Copyright (c) 1995-1997 Graham Barr. All rights reserved.
593This program is free software; you can redistribute it and/or modify
594it under the same terms as Perl itself.
595
596=cut