This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
remove C<my $x if foo> construct from core modules
[perl5.git] / lib / Net / SMTP.pm
CommitLineData
406c51ee
JH
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
dea4d7df 19$VERSION = "2.26"; # $Id: //depot/libnet/Net/SMTP.pm#31 $
406c51ee
JH
20
21@ISA = qw(Net::Cmd IO::Socket::INET);
22
23sub new
24{
25 my $self = shift;
26 my $type = ref($self) || $self;
76df5e8f
DM
27 my $host;
28 $host = shift if @_ % 2;
406c51ee 29 my %arg = @_;
dea4d7df 30 my $hosts = defined $host ? $host : $NetConfig{smtp_hosts};
406c51ee
JH
31 my $obj;
32
33 my $h;
dea4d7df 34 foreach $h (@{ref($hosts) ? $hosts : [ $hosts ]})
406c51ee
JH
35 {
36 $obj = $type->SUPER::new(PeerAddr => ($host = $h),
37 PeerPort => $arg{Port} || 'smtp(25)',
12df23ee
GB
38 LocalAddr => $arg{LocalAddr},
39 LocalPort => $arg{LocalPort},
406c51ee
JH
40 Proto => 'tcp',
41 Timeout => defined $arg{Timeout}
42 ? $arg{Timeout}
43 : 120
44 ) and last;
45 }
46
47 return undef
48 unless defined $obj;
49
50 $obj->autoflush(1);
51
52 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
53
54 unless ($obj->response() == CMD_OK)
55 {
56 $obj->close();
57 return undef;
58 }
59
dea4d7df 60 ${*$obj}{'net_smtp_exact_addr'} = $arg{ExactAddresses};
406c51ee
JH
61 ${*$obj}{'net_smtp_host'} = $host;
62
63 (${*$obj}{'net_smtp_banner'}) = $obj->message;
64 (${*$obj}{'net_smtp_domain'}) = $obj->message =~ /\A\s*(\S+)/;
65
66 unless($obj->hello($arg{Hello} || ""))
67 {
68 $obj->close();
69 return undef;
70 }
71
72 $obj;
73}
74
75##
76## User interface methods
77##
78
79sub banner
80{
81 my $me = shift;
82
83 return ${*$me}{'net_smtp_banner'} || undef;
84}
85
86sub domain
87{
88 my $me = shift;
89
90 return ${*$me}{'net_smtp_domain'} || undef;
91}
92
93sub etrn {
94 my $self = shift;
95 defined($self->supports('ETRN',500,["Command unknown: 'ETRN'"])) &&
96 $self->_ETRN(@_);
97}
98
16f7bb68
GB
99sub auth {
100 my ($self, $username, $password) = @_;
c8570720
GB
101
102 require MIME::Base64;
16f7bb68 103 require Authen::SASL;
c8570720
GB
104
105 my $mechanisms = $self->supports('AUTH',500,["Command unknown: 'AUTH'"]);
106 return unless defined $mechanisms;
107
16f7bb68
GB
108 my $sasl;
109
110 if (ref($username) and UNIVERSAL::isa($username,'Authen::SASL')) {
111 $sasl = $username;
112 $sasl->mechanism($mechanisms);
113 }
114 else {
115 die "auth(username, password)" if not length $username;
116 $sasl = Authen::SASL->new(mechanism=> $mechanisms,
117 callback => { user => $username,
118 pass => $password,
119 authname => $username,
120 });
121 }
122
123 # We should probably allow the user to pass the host, but I don't
124 # currently know and SASL mechanisms that are used by smtp that need it
125 my $client = $sasl->client_new('smtp',${*$self}{'net_smtp_host'},0);
126 my $str = $client->client_start;
127 # We dont support sasl mechanisms that encrypt the socket traffic.
128 # todo that we would really need to change the ISA hierarchy
129 # so we dont inherit from IO::Socket, but instead hold it in an attribute
130
edd55068 131 my @cmd = ("AUTH", $client->mechanism);
16f7bb68
GB
132 my $code;
133
edd55068
GB
134 push @cmd, MIME::Base64::encode_base64($str,'')
135 if defined $str and length $str;
136
16f7bb68
GB
137 while (($code = $self->command(@cmd)->response()) == CMD_MORE) {
138 @cmd = (MIME::Base64::encode_base64(
139 $client->client_step(
140 MIME::Base64::decode_base64(
141 ($self->message)[0]
142 )
143 ), ''
144 ));
c8570720 145 }
c8570720 146
16f7bb68 147 $code == CMD_OK;
c8570720
GB
148}
149
406c51ee
JH
150sub hello
151{
152 my $me = shift;
046d9f47 153 my $domain = shift || "localhost.localdomain";
406c51ee
JH
154 my $ok = $me->_EHLO($domain);
155 my @msg = $me->message;
156
157 if($ok)
158 {
159 my $h = ${*$me}{'net_smtp_esmtp'} = {};
160 my $ln;
161 foreach $ln (@msg) {
686337f3 162 $h->{uc $1} = $2
67ada6d4 163 if $ln =~ /(\w+)\b[= \t]*([^\n]*)/;
406c51ee
JH
164 }
165 }
166 elsif($me->status == CMD_ERROR)
167 {
168 @msg = $me->message
169 if $ok = $me->_HELO($domain);
170 }
171
dea4d7df
GB
172 return undef unless $ok;
173
174 $msg[0] =~ /\A\s*(\S+)/;
175 return ($1 || " ");
406c51ee
JH
176}
177
178sub supports {
179 my $self = shift;
180 my $cmd = uc shift;
181 return ${*$self}{'net_smtp_esmtp'}->{$cmd}
182 if exists ${*$self}{'net_smtp_esmtp'}->{$cmd};
183 $self->set_status(@_)
184 if @_;
185 return;
186}
187
16f7bb68 188sub _addr {
dea4d7df 189 my $self = shift;
16f7bb68
GB
190 my $addr = shift;
191 $addr = "" unless defined $addr;
dea4d7df
GB
192
193 if (${*$self}{'net_smtp_exact_addr'}) {
194 return $1 if $addr =~ /^\s*(<.*>)\s*$/s;
195 }
196 else {
197 return $1 if $addr =~ /(<[^>]*>)/;
198 $addr =~ s/^\s+|\s+$//sg;
199 }
200
16f7bb68 201 "<$addr>";
406c51ee
JH
202}
203
406c51ee
JH
204sub mail
205{
206 my $me = shift;
dea4d7df 207 my $addr = _addr($me, shift);
406c51ee
JH
208 my $opts = "";
209
210 if(@_)
211 {
212 my %opt = @_;
213 my($k,$v);
214
215 if(exists ${*$me}{'net_smtp_esmtp'})
216 {
217 my $esmtp = ${*$me}{'net_smtp_esmtp'};
218
219 if(defined($v = delete $opt{Size}))
220 {
221 if(exists $esmtp->{SIZE})
222 {
223 $opts .= sprintf " SIZE=%d", $v + 0
224 }
225 else
226 {
227 carp 'Net::SMTP::mail: SIZE option not supported by host';
228 }
229 }
230
231 if(defined($v = delete $opt{Return}))
232 {
233 if(exists $esmtp->{DSN})
234 {
dea4d7df 235 $opts .= " RET=" . ((uc($v) eq "FULL") ? "FULL" : "HDRS");
406c51ee
JH
236 }
237 else
238 {
239 carp 'Net::SMTP::mail: DSN option not supported by host';
240 }
241 }
242
243 if(defined($v = delete $opt{Bits}))
244 {
dea4d7df
GB
245 if($v eq "8")
246 {
247 if(exists $esmtp->{'8BITMIME'})
248 {
249 $opts .= " BODY=8BITMIME";
250 }
251 else
252 {
253 carp 'Net::SMTP::mail: 8BITMIME option not supported by host';
254 }
255 }
256 elsif($v eq "binary")
257 {
258 if(exists $esmtp->{'BINARYMIME'} && exists $esmtp->{'CHUNKING'})
259 {
260 $opts .= " BODY=BINARYMIME";
261 ${*$me}{'net_smtp_chunking'} = 1;
262 }
263 else
264 {
265 carp 'Net::SMTP::mail: BINARYMIME option not supported by host';
266 }
267 }
268 elsif(exists $esmtp->{'8BITMIME'} or exists $esmtp->{'BINARYMIME'})
406c51ee 269 {
dea4d7df 270 $opts .= " BODY=7BIT";
406c51ee
JH
271 }
272 else
273 {
dea4d7df 274 carp 'Net::SMTP::mail: 8BITMIME and BINARYMIME options not supported by host';
406c51ee
JH
275 }
276 }
277
278 if(defined($v = delete $opt{Transaction}))
279 {
280 if(exists $esmtp->{CHECKPOINT})
281 {
dea4d7df 282 $opts .= " TRANSID=" . _addr($me, $v);
406c51ee
JH
283 }
284 else
285 {
286 carp 'Net::SMTP::mail: CHECKPOINT option not supported by host';
287 }
288 }
289
290 if(defined($v = delete $opt{Envelope}))
291 {
292 if(exists $esmtp->{DSN})
293 {
294 $v =~ s/([^\041-\176]|=|\+)/sprintf "+%02x", ord($1)/sge;
295 $opts .= " ENVID=$v"
296 }
297 else
298 {
299 carp 'Net::SMTP::mail: DSN option not supported by host';
300 }
301 }
302
303 carp 'Net::SMTP::recipient: unknown option(s) '
304 . join(" ", keys %opt)
305 . ' - ignored'
306 if scalar keys %opt;
307 }
308 else
309 {
310 carp 'Net::SMTP::mail: ESMTP not supported by host - options discarded :-(';
311 }
312 }
313
314 $me->_MAIL("FROM:".$addr.$opts);
315}
316
dea4d7df
GB
317sub send { my $me = shift; $me->_SEND("FROM:" . _addr($me, $_[0])) }
318sub send_or_mail { my $me = shift; $me->_SOML("FROM:" . _addr($me, $_[0])) }
319sub send_and_mail { my $me = shift; $me->_SAML("FROM:" . _addr($me, $_[0])) }
406c51ee
JH
320
321sub reset
322{
323 my $me = shift;
324
325 $me->dataend()
326 if(exists ${*$me}{'net_smtp_lastch'});
327
328 $me->_RSET();
329}
330
331
332sub recipient
333{
334 my $smtp = shift;
335 my $opts = "";
336 my $skip_bad = 0;
337
338 if(@_ && ref($_[-1]))
339 {
340 my %opt = %{pop(@_)};
341 my $v;
342
343 $skip_bad = delete $opt{'SkipBad'};
344
345 if(exists ${*$smtp}{'net_smtp_esmtp'})
346 {
347 my $esmtp = ${*$smtp}{'net_smtp_esmtp'};
348
349 if(defined($v = delete $opt{Notify}))
350 {
351 if(exists $esmtp->{DSN})
352 {
353 $opts .= " NOTIFY=" . join(",",map { uc $_ } @$v)
354 }
355 else
356 {
357 carp 'Net::SMTP::recipient: DSN option not supported by host';
358 }
359 }
360
361 carp 'Net::SMTP::recipient: unknown option(s) '
362 . join(" ", keys %opt)
363 . ' - ignored'
364 if scalar keys %opt;
365 }
366 elsif(%opt)
367 {
368 carp 'Net::SMTP::recipient: ESMTP not supported by host - options discarded :-(';
369 }
370 }
371
372 my @ok;
373 my $addr;
374 foreach $addr (@_)
375 {
dea4d7df 376 if($smtp->_RCPT("TO:" . _addr($smtp, $addr) . $opts)) {
406c51ee
JH
377 push(@ok,$addr) if $skip_bad;
378 }
379 elsif(!$skip_bad) {
380 return 0;
381 }
382 }
383
384 return $skip_bad ? @ok : 1;
385}
386
686337f3
JH
387BEGIN {
388 *to = \&recipient;
389 *cc = \&recipient;
390 *bcc = \&recipient;
391}
406c51ee
JH
392
393sub data
394{
395 my $me = shift;
396
dea4d7df
GB
397 if(exists ${*$me}{'net_smtp_chunking'})
398 {
399 carp 'Net::SMTP::data: CHUNKING extension in use, must call bdat instead';
400 }
401 else
402 {
403 my $ok = $me->_DATA() && $me->datasend(@_);
404
405 $ok && @_ ? $me->dataend
406 : $ok;
407 }
408}
409
410sub bdat
411{
412 my $me = shift;
413
414 if(exists ${*$me}{'net_smtp_chunking'})
415 {
416 my $data = shift;
406c51ee 417
dea4d7df
GB
418 $me->_BDAT(length $data) && $me->rawdatasend($data) &&
419 $me->response() == CMD_OK;
420 }
421 else
422 {
423 carp 'Net::SMTP::bdat: CHUNKING extension is not in use, call data instead';
424 }
425}
426
427sub bdatlast
428{
429 my $me = shift;
430
431 if(exists ${*$me}{'net_smtp_chunking'})
432 {
433 my $data = shift;
434
435 $me->_BDAT(length $data, "LAST") && $me->rawdatasend($data) &&
436 $me->response() == CMD_OK;
437 }
438 else
439 {
440 carp 'Net::SMTP::bdat: CHUNKING extension is not in use, call data instead';
441 }
406c51ee
JH
442}
443
12df23ee
GB
444sub datafh {
445 my $me = shift;
446 return unless $me->_DATA();
447 return $me->tied_fh;
448}
449
406c51ee
JH
450sub expand
451{
452 my $me = shift;
453
454 $me->_EXPN(@_) ? ($me->message)
455 : ();
456}
457
458
459sub verify { shift->_VRFY(@_) }
460
461sub help
462{
463 my $me = shift;
464
465 $me->_HELP(@_) ? scalar $me->message
466 : undef;
467}
468
469sub quit
470{
471 my $me = shift;
472
473 $me->_QUIT;
474 $me->close;
475}
476
477sub DESTROY
478{
479# ignore
480}
481
482##
483## RFC821 commands
484##
485
486sub _EHLO { shift->command("EHLO", @_)->response() == CMD_OK }
487sub _HELO { shift->command("HELO", @_)->response() == CMD_OK }
488sub _MAIL { shift->command("MAIL", @_)->response() == CMD_OK }
489sub _RCPT { shift->command("RCPT", @_)->response() == CMD_OK }
490sub _SEND { shift->command("SEND", @_)->response() == CMD_OK }
491sub _SAML { shift->command("SAML", @_)->response() == CMD_OK }
492sub _SOML { shift->command("SOML", @_)->response() == CMD_OK }
493sub _VRFY { shift->command("VRFY", @_)->response() == CMD_OK }
494sub _EXPN { shift->command("EXPN", @_)->response() == CMD_OK }
495sub _HELP { shift->command("HELP", @_)->response() == CMD_OK }
496sub _RSET { shift->command("RSET")->response() == CMD_OK }
497sub _NOOP { shift->command("NOOP")->response() == CMD_OK }
498sub _QUIT { shift->command("QUIT")->response() == CMD_OK }
499sub _DATA { shift->command("DATA")->response() == CMD_MORE }
dea4d7df 500sub _BDAT { shift->command("BDAT", @_) }
406c51ee
JH
501sub _TURN { shift->unsupported(@_); }
502sub _ETRN { shift->command("ETRN", @_)->response() == CMD_OK }
c8570720 503sub _AUTH { shift->command("AUTH", @_)->response() == CMD_OK }
406c51ee
JH
504
5051;
506
507__END__
508
509=head1 NAME
510
511Net::SMTP - Simple Mail Transfer Protocol Client
512
513=head1 SYNOPSIS
514
515 use Net::SMTP;
686337f3 516
406c51ee
JH
517 # Constructors
518 $smtp = Net::SMTP->new('mailhost');
519 $smtp = Net::SMTP->new('mailhost', Timeout => 60);
520
521=head1 DESCRIPTION
522
523This module implements a client interface to the SMTP and ESMTP
524protocol, enabling a perl5 application to talk to SMTP servers. This
525documentation assumes that you are familiar with the concepts of the
526SMTP protocol described in RFC821.
527
528A new Net::SMTP object must be created with the I<new> method. Once
529this has been done, all SMTP commands are accessed through this object.
530
531The Net::SMTP class is a subclass of Net::Cmd and IO::Socket::INET.
532
533=head1 EXAMPLES
534
535This example prints the mail domain name of the SMTP server known as mailhost:
536
537 #!/usr/local/bin/perl -w
686337f3 538
406c51ee 539 use Net::SMTP;
686337f3 540
406c51ee
JH
541 $smtp = Net::SMTP->new('mailhost');
542 print $smtp->domain,"\n";
543 $smtp->quit;
544
545This example sends a small message to the postmaster at the SMTP server
546known as mailhost:
547
548 #!/usr/local/bin/perl -w
686337f3 549
406c51ee 550 use Net::SMTP;
686337f3 551
406c51ee 552 $smtp = Net::SMTP->new('mailhost');
686337f3 553
406c51ee
JH
554 $smtp->mail($ENV{USER});
555 $smtp->to('postmaster');
686337f3 556
406c51ee
JH
557 $smtp->data();
558 $smtp->datasend("To: postmaster\n");
559 $smtp->datasend("\n");
560 $smtp->datasend("A simple test message\n");
561 $smtp->dataend();
686337f3 562
406c51ee
JH
563 $smtp->quit;
564
565=head1 CONSTRUCTOR
566
567=over 4
568
569=item new Net::SMTP [ HOST, ] [ OPTIONS ]
570
571This is the constructor for a new Net::SMTP object. C<HOST> is the
d1be9408 572name of the remote host to which an SMTP connection is required.
406c51ee 573
dea4d7df
GB
574If C<HOST> is an array reference then each value will be attempted
575in turn until a connection is made.
576
406c51ee
JH
577If C<HOST> is not given, then the C<SMTP_Host> specified in C<Net::Config>
578will be used.
579
580C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
581Possible options are:
582
583B<Hello> - SMTP requires that you identify yourself. This option
584specifies a string to pass as your mail domain. If not
585given a guess will be taken.
586
12df23ee
GB
587B<LocalAddr> and B<LocalPort> - These parameters are passed directly
588to IO::Socket to allow binding the socket to a local port.
589
406c51ee
JH
590B<Timeout> - Maximum time, in seconds, to wait for a response from the
591SMTP server (default: 120)
592
dea4d7df
GB
593B<ExactAddresses> - If true the all ADDRESS arguments must be as
594defined by C<addr-spec> in RFC2822. If not given, or false, then
595Net::SMTP will attempt to extract the address from the value passed.
596
406c51ee
JH
597B<Debug> - Enable debugging information
598
599
600Example:
601
602
603 $smtp = Net::SMTP->new('mailhost',
604 Hello => 'my.mail.domain'
605 Timeout => 30,
606 Debug => 1,
607 );
608
686337f3
JH
609=back
610
406c51ee
JH
611=head1 METHODS
612
613Unless otherwise stated all methods return either a I<true> or I<false>
614value, with I<true> meaning that the operation was a success. When a method
615states that it returns a value, failure will be returned as I<undef> or an
616empty list.
617
618=over 4
619
620=item banner ()
621
622Returns the banner message which the server replied with when the
623initial connection was made.
624
625=item domain ()
626
627Returns the domain that the remote SMTP server identified itself as during
628connection.
629
630=item hello ( DOMAIN )
631
632Tell the remote server the mail domain which you are in using the EHLO
633command (or HELO if EHLO fails). Since this method is invoked
634automatically when the Net::SMTP object is constructed the user should
635normally not have to call it manually.
636
637=item etrn ( DOMAIN )
638
639Request a queue run for the DOMAIN given.
640
c8570720
GB
641=item auth ( USERNAME, PASSWORD )
642
16f7bb68 643Attempt SASL authentication.
c8570720 644
406c51ee
JH
645=item mail ( ADDRESS [, OPTIONS] )
646
647=item send ( ADDRESS )
648
649=item send_or_mail ( ADDRESS )
650
651=item send_and_mail ( ADDRESS )
652
653Send the appropriate command to the server MAIL, SEND, SOML or SAML. C<ADDRESS>
654is the address of the sender. This initiates the sending of a message. The
655method C<recipient> should be called for each address that the message is to
656be sent to.
657
658The C<mail> method can some additional ESMTP OPTIONS which is passed
659in hash like fashion, using key and value pairs. Possible options are:
660
661 Size => <bytes>
dea4d7df
GB
662 Return => "FULL" | "HDRS"
663 Bits => "7" | "8" | "binary"
406c51ee
JH
664 Transaction => <ADDRESS>
665 Envelope => <ENVID>
666
dea4d7df
GB
667The C<Return> and C<Envelope> parameters are used for DSN (Delivery
668Status Notification).
406c51ee
JH
669
670=item reset ()
671
672Reset the status of the server. This may be called after a message has been
673initiated, but before any data has been sent, to cancel the sending of the
674message.
675
676=item recipient ( ADDRESS [, ADDRESS [ ...]] [, OPTIONS ] )
677
678Notify the server that the current message should be sent to all of the
679addresses given. Each address is sent as a separate command to the server.
680Should the sending of any address result in a failure then the
681process is aborted and a I<false> value is returned. It is up to the
682user to call C<reset> if they so desire.
683
684The C<recipient> method can some additional OPTIONS which is passed
685in hash like fashion, using key and value pairs. Possible options are:
686
687 Notify =>
688 SkipBad => ignore bad addresses
689
690If C<SkipBad> is true the C<recipient> will not return an error when a
691bad address is encountered and it will return an array of addresses
692that did succeed.
693
686337f3
JH
694 $smtp->recipient($recipient1,$recipient2); # Good
695 $smtp->recipient($recipient1,$recipient2, { SkipBad => 1 }); # Good
696 $smtp->recipient("$recipient,$recipient2"); # BAD
697
406c51ee
JH
698=item to ( ADDRESS [, ADDRESS [...]] )
699
686337f3
JH
700=item cc ( ADDRESS [, ADDRESS [...]] )
701
702=item bcc ( ADDRESS [, ADDRESS [...]] )
703
704Synonyms for C<recipient>.
406c51ee
JH
705
706=item data ( [ DATA ] )
707
708Initiate the sending of the data from the current message.
709
710C<DATA> may be a reference to a list or a list. If specified the contents
711of C<DATA> and a termination string C<".\r\n"> is sent to the server. And the
712result will be true if the data was accepted.
713
714If C<DATA> is not specified then the result will indicate that the server
715wishes the data to be sent. The data must then be sent using the C<datasend>
716and C<dataend> methods described in L<Net::Cmd>.
717
718=item expand ( ADDRESS )
719
720Request the server to expand the given address Returns an array
721which contains the text read from the server.
722
723=item verify ( ADDRESS )
724
725Verify that C<ADDRESS> is a legitimate mailing address.
726
727=item help ( [ $subject ] )
728
729Request help text from the server. Returns the text or undef upon failure
730
731=item quit ()
732
733Send the QUIT command to the remote SMTP server and close the socket connection.
734
735=back
736
16f7bb68
GB
737=head1 ADDRESSES
738
dea4d7df
GB
739Net::SMTP attempts to DWIM with addresses that are passed. For
740example an application might extract The From: line from an email
741and pass that to mail(). While this may work, it is not reccomended.
742The application should really use a module like L<Mail::Address>
743to extract the mail address and pass that.
744
745If C<ExactAddresses> is passed to the contructor, then addresses
746should be a valid rfc2821-quoted address, although Net::SMTP will
747accept accept the address surrounded by angle brackets.
16f7bb68
GB
748
749 funny user@domain WRONG
750 "funny user"@domain RIGHT, recommended
751 <"funny user"@domain> OK
752
406c51ee
JH
753=head1 SEE ALSO
754
755L<Net::Cmd>
756
757=head1 AUTHOR
758
759Graham Barr <gbarr@pobox.com>
760
761=head1 COPYRIGHT
762
763Copyright (c) 1995-1997 Graham Barr. All rights reserved.
764This program is free software; you can redistribute it and/or modify
765it under the same terms as Perl itself.
766
686337f3
JH
767=for html <hr>
768
dea4d7df 769I<$Id: //depot/libnet/Net/SMTP.pm#31 $>
686337f3 770
406c51ee 771=cut