diff options
Diffstat (limited to 'cpan/lib/Mail/Internet.pm')
| -rw-r--r-- | cpan/lib/Mail/Internet.pm | 1151 |
1 files changed, 371 insertions, 780 deletions
diff --git a/cpan/lib/Mail/Internet.pm b/cpan/lib/Mail/Internet.pm index 6b1157ba..bace44be 100644 --- a/cpan/lib/Mail/Internet.pm +++ b/cpan/lib/Mail/Internet.pm @@ -1,963 +1,554 @@ -# Mail::Internet.pm -# -# Copyright (c) 1995-2001 Graham Barr <gbarr@pobox.com>. All rights reserved. -# This program is free software; you can redistribute it and/or -# modify it under the same terms as Perl itself. -# - +# Copyrights 1995-2017 by [Mark Overmeer <perl@overmeer.net>]. +# For other contributors see ChangeLog. +# See the manual pages for details on the licensing terms. +# Pod stripped from pm file by OODoc 2.02. package Mail::Internet; -use strict; +use vars '$VERSION'; +$VERSION = '2.19'; -require 5.002; +use strict; +# use warnings? probably breaking too much code use Carp; -use AutoLoader; use Mail::Header; -use vars qw($VERSION); - -BEGIN { - $VERSION = "1.52"; - *AUTOLOAD = \&AutoLoader::AUTOLOAD; - - unless(defined &UNIVERSAL::isa) { - *UNIVERSAL::isa = sub { - my($obj,$type) = @_; - my $pkg = ref($obj) || $obj; - my @pkg = ($pkg); - my %done; - while(@pkg) { - $pkg = shift @pkg; - return 1 if $pkg eq $type; - next if exists $done{$pkg}; - $done{$pkg} = 1; - - no strict 'refs'; - - unshift @pkg,@{$pkg . "::ISA"} - if(@{$pkg . "::ISA"}); - } - undef; - } - } -} +use Mail::Util qw/mailaddress/; +use Mail::Address; -sub new -{ - my $self = shift; - my $type = ref($self) || $self; - my $arg = @_ % 2 ? shift : undef; - my %arg = @_; +sub new(@) +{ my $call = shift; + my $arg = @_ % 2 ? shift : undef; + my %opt = @_; - my $me = bless {}, $type; + my $class = ref($call) || $call; + my $self = bless {}, $class; - $me->{'mail_inet_head'} = $arg{Header} if exists $arg{Header}; - $me->{'mail_inet_body'} = $arg{Body} if exists $arg{Body}; + $self->{mail_inet_head} = $opt{Header} if exists $opt{Header}; + $self->{mail_inet_body} = $opt{Body} if exists $opt{Body}; - $me->head->fold_length(delete $arg{FoldLength} || 79); # Default fold length - $me->head->mail_from($arg{MailFrom}) if exists $arg{MailFrom}; - $me->head->modify(exists $arg{Modify} ? $arg{Modify} : 1); + my $head = $self->head; + $head->fold_length(delete $opt{FoldLength} || 79); + $head->mail_from($opt{MailFrom}) if exists $opt{MailFrom}; + $head->modify(exists $opt{Modify} ? $opt{Modify} : 1); - if(defined $arg) - { - if(ref($arg) eq 'ARRAY') - { - $me->header($arg) unless exists $arg{Header}; - $me->body($arg) unless exists $arg{Body}; + if(!defined $arg) { } + elsif(ref($arg) eq 'ARRAY') + { $self->header($arg) unless exists $opt{Header}; + $self->body($arg) unless exists $opt{Body}; } - elsif(defined fileno($arg)) - { - $me->read_header($arg) unless exists $arg{Header}; - $me->read_body($arg) unless exists $arg{Body}; + elsif(defined fileno($arg)) + { $self->read_header($arg) unless exists $opt{Header}; + $self->read_body($arg) unless exists $opt{Body}; + } + else + { croak "couldn't understand $arg to Mail::Internet constructor"; } - } - - return $me; -} - -sub read -{ - my $me = shift; - - $me->read_header(@_); - $me->read_body(@_); -} - -sub read_body -{ - my($me,$fd) = @_; - $me->body( [ <$fd> ] ); + $self; } -sub extract -{ - my $me = shift; - my $arg = shift; - - $me->head->extract($arg); - $me->body($arg); +sub read(@) +{ my $self = shift; + $self->read_header(@_); + $self->read_body(@_); } - -sub body -{ - my $me = shift; - my $body = $me->{'mail_inet_body'} ||= []; - - if(@_) - { - my $new = shift; - $me->{'mail_inet_body'} = ref($new) eq 'ARRAY' ? $new : [ $new, @_ ]; - } - - return $body; +sub read_body($) +{ my ($self, $fd) = @_; + $self->body( [ <$fd> ] ); } -sub header { shift->head->header(@_) } -sub fold { shift->head->fold(@_) } -sub fold_length { shift->head->fold_length(@_) } -sub combine { shift->head->combine(@_) } -sub print_header { shift->{'mail_inet_head'}->print(@_) } -sub head { shift->{'mail_inet_head'} ||= new Mail::Header } - -sub read_header -{ - my $me = shift; - my $head = $me->head; - $head->read(@_); - $head->header(); +sub read_header(@) +{ my $head = shift->head; + $head->read(@_); + $head->header; } -sub clean_header -{ - carp "clean_header depreciated, use ->header" if $^W; - shift->header(); -} -sub tidy_headers -{ - carp "tidy_headers no longer required" if $^W; +sub extract($) +{ my ($self, $lines) = @_; + $self->head->extract($lines); + $self->body($lines); } -sub add -{ - my $me = shift; - my $head = $me->head; - my $ret; - while(@_) - { - my ($tag,$line) = splice(@_,0,2); +sub dup() +{ my $self = shift; + my $dup = ref($self)->new; - $ret = $head->add($tag,$line,-1) or - return undef; - } + my $body = $self->{mail_inet_body} || []; + my $head = $self->{mail_inet_head};; - $ret; + $dup->{mail_inet_body} = [ @$body ]; + $dup->{mail_inet_head} = $head->dup if $head; + $dup; } -sub replace -{ - my $me = shift; - my $head = $me->head; - my $ret; +#--------------- - while(@_) - { - my ($tag,$line) = splice(@_,0,2); +sub body(;$@) +{ my $self = shift; - $ret = $head->replace($tag,$line,0) or - return undef; - } + return $self->{mail_inet_body} ||= [] + unless @_; - $ret; + $self->{mail_inet_body} = ref $_[0] eq 'ARRAY' ? $_[0] : [ @_ ]; } -sub get -{ - my $me = shift; - my $head = $me->head; - my @ret = (); - my $tag; - - foreach $tag (@_) - { - last - if push(@ret, $head->get($tag)) && !wantarray; - } - wantarray ? @ret : shift @ret; -} +sub head { shift->{mail_inet_head} ||= Mail::Header->new } -sub delete -{ - my $me = shift; - my $head = $me->head; - my @ret = (); - my $tag; +#--------------- - foreach $tag (@_) - { - push(@ret, $head->delete($tag)); - } +sub print($) +{ my $self = shift; + my $fd = shift || \*STDOUT; - @ret; + $self->print_header($fd) + and print $fd "\n" + and $self->print_body($fd); } -sub dup -{ - my $me = shift; - my $type = ref($me); - my $dup = $type->new; - $dup->{'mail_inet_body'} = [@{$me->body}] - if exists $me->{'mail_inet_body'}; - - $dup->{'mail_inet_head'} = $me->{'mail_inet_head'}->dup - if exists $me->{'mail_inet_head'}; - - $dup; -} +sub print_header($) { shift->head->print(@_) } -sub empty -{ - my $me = shift; +sub print_body($) +{ my $self = shift; + my $fd = shift || \*STDOUT; - %{*$me} = (); - - 1; -} - -sub print_body -{ - my $me = shift; - my $fd = shift || \*STDOUT; - my $ln; - - foreach $ln (@{$me->body}) - { - print $fd $ln or - return 0; - } + foreach my $ln (@{$self->body}) + { print $fd $ln or return 0; + } - 1; + 1; } -sub print -{ - my $me = shift; - my $fd = shift || \*STDOUT; - $me->print_header($fd) - and print $fd "\n" - and $me->print_body($fd); +sub as_string() +{ my $self = shift; + $self->head->as_string . "\n" . join '', @{$self->body}; } -sub as_string -{ - my $me = shift; - - $me->head->as_string . "\n" . join '', @{ $me->body }; -} -sub as_mbox_string -{ - my $me = shift->dup; - my $escaped = shift; +sub as_mbox_string($) +{ my $self = shift->dup; + my $escaped = shift; - $me->head->delete('Content-Length'); - $me->escape_from unless $escaped; - $me->as_string . "\n"; + $self->head->delete('Content-Length'); + $self->escape_from unless $escaped; + $self->as_string . "\n"; } -sub remove_sig -{ - my $me = shift; - my $nlines = shift || 10; +#--------------- - my $body = $me->body; - my($line,$i); +sub header { shift->head->header(@_) } +sub fold { shift->head->fold(@_) } +sub fold_length { shift->head->fold_length(@_) } +sub combine { shift->head->combine(@_) } - $line = scalar(@{$body}); - return unless($line); - while($i++ < $nlines && $line--) - { - if($body->[$line] =~ /\A--\040?[\r\n]+/) - { - splice(@{$body},$line,$i); - last; +sub add(@) +{ my $head = shift->head; + my $ret; + while(@_) + { my ($tag, $line) = splice @_, 0, 2; + $ret = $head->add($tag, $line, -1) + or return undef; } - } + + $ret; } -sub tidy_body -{ - my $me = shift; - my $body = $me->body; - my $line; +sub replace(@) +{ my $head = shift->head; + my $ret; - if(scalar(@{$body})) - { - shift @$body - while(scalar(@{$body}) && $body->[0] =~ /\A\s*\Z/); - pop @$body - while(scalar(@{$body}) && $body->[-1] =~ /\A\s*\Z/); - } + while(@_) + { my ($tag, $line) = splice @_, 0, 2; + $ret = $head->replace($tag, $line, 0) + or return undef; + } - return $body; + $ret; } -sub DESTROY {} -# Auto loaded methods go after __END__ -__END__ +sub get(@) +{ my $head = shift->head; -sub reply; + return map { $head->get($_) } @_ + if wantarray; + foreach my $tag (@_) + { my $r = $head->get($tag); + return $r if defined $r; + } -use Mail::Address; - - sub reply -{ - my $me = shift; - my %arg = @_; - my $pkg = ref $me; - my @reply = (); + undef; +} - local *MAILHDR; - if(open(MAILHDR,"$ENV{HOME}/.mailhdr")) - { - # User has defined a mail header template - @reply = <MAILHDR>; - close(MAILHDR); - } - my $reply = $pkg->new(\@reply); +sub delete(@) +{ my $head = shift->head; + map { $head->delete($_) } @_; +} - my($to,$cc,$name,$body,$id); +# Undocumented; unused??? +sub empty() +{ my $self = shift; + %$self = (); + 1; +} - # The Subject line +#--------------- - my $subject = $me->get('Subject') || ""; +sub remove_sig($) +{ my $body = shift->body; + my $nlines = shift || 10; + my $start = @$body; - $subject = "Re: " . $subject if($subject =~ /\S+/ && $subject !~ /Re:/i); + my $i = 0; + while($i++ < $nlines && $start--) + { next if $body->[$start] !~ /^--[ ]?[\r\n]/; - $reply->replace('Subject',$subject); + splice @$body, $start, $i; + last; + } +} - # Locate who we are sending to - $to = $me->get('Reply-To') - || $me->get('From') - || $me->get('Return-Path') - || ""; - # Mail::Address->parse returns a list of refs to a 2 element array - my $sender = (Mail::Address->parse($to))[0]; +sub sign(@) +{ my ($self, %arg) = @_; + my ($sig, @sig); - $name = $sender->name; - $id = $sender->address; + if($sig = delete $arg{File}) + { local *SIG; - unless(defined $name) - { - my $fr = $me->get('From'); + if(open(SIG, $sig)) + { local $_; + while(<SIG>) { last unless /^(--)?\s*$/ } + @sig = ($_, <SIG>, "\n"); + close SIG; + } + } + elsif($sig = delete $arg{Signature}) + { @sig = ref($sig) ? @$sig : split(/\n/, $sig); + } - $fr = (Mail::Address->parse($fr))[0] if(defined $fr); - $name = $fr->name if(defined $fr); - } + if(@sig) + { $self->remove_sig; + s/[\r\n]*$/\n/ for @sig; + push @{$self->body}, "-- \n", @sig; + } - my $indent = $arg{Indent} || ">"; + $self; +} - if($indent =~ /%/) - { - my %hash = ( '%' => '%'); - my @name = grep(do { length > 0 }, split(/[\n\s]+/,$name || "")); - my @tmp; - @name = "" unless(@name); +sub tidy_body() +{ my $body = shift->body; - $hash{f} = $name[0]; - $hash{F} = $#name ? substr($hash{f},0,1) : $hash{f}; + shift @$body while @$body && $body->[0] =~ /^\s*$/; + pop @$body while @$body && $body->[-1] =~ /^\s*$/; + $body; +} - $hash{l} = $#name ? $name[$#name] : ""; - $hash{L} = substr($hash{l},0,1) || ""; +#--------------- - $hash{n} = $name || ""; - $hash{I} = join("",grep($_ = substr($_,0,1), @tmp = @name)); +sub reply(@) +{ my ($self, %arg) = @_; + my $class = ref $self; + my @reply; - $indent =~ s/%(.)/defined $hash{$1} ? $hash{$1} : $1/eg; - } + local *MAILHDR; + if(open(MAILHDR, "$ENV{HOME}/.mailhdr")) + { # User has defined a mail header template + @reply = <MAILHDR>; + close MAILHDR; + } - $reply->replace('To', $id); + my $reply = $class->new(\@reply); - # Find addresses not to include - my %nocc = (); - my $mailaddresses = $ENV{MAILADDRESSES} || ""; - my $addr; + # The Subject line + my $subject = $self->get('Subject') || ""; + $subject = "Re: " . $subject + if $subject =~ /\S+/ && $subject !~ /Re:/i; - $nocc{lc $id} = 1; + $reply->replace(Subject => $subject); - foreach $addr (Mail::Address->parse($reply->get('Bcc'),$mailaddresses)) - { - my $lc = lc $addr->address; - $nocc{$lc} = 1; - } + # Locate who we are sending to + my $to = $self->get('Reply-To') + || $self->get('From') + || $self->get('Return-Path') + || ""; - if($arg{ReplyAll} || 0) - { - # Who shall we copy this to - my %cc = (); + my $sender = (Mail::Address->parse($to))[0]; - foreach $addr (Mail::Address->parse($me->get('To'),$me->get('Cc'))) - { - my $lc = lc $addr->address; - $cc{$lc} = $addr->format unless(defined $nocc{$lc}); + my $name = $sender->name; + unless(defined $name) + { my $fr = $self->get('From'); + $fr = (Mail::Address->parse($fr))[0] if defined $fr; + $name = $fr->name if defined $fr; } - $cc = join(', ',values %cc); - - $reply->replace('Cc', $cc); - } - - # References - my $refs = $me->get('References') || ""; - my $mid = $me->get('Message-Id'); - - $refs .= " " . $mid if(defined $mid); - $reply->replace('References',$refs); - - # In-Reply-To - my $date = $me->get('Date'); - my $inreply = ""; - - if(defined $mid) - { - $inreply = $mid; - $inreply .= " from " . $name if(defined $name); - $inreply .= " on " . $date if(defined $date); - } - elsif(defined $name) - { - $inreply = $name . "'s message"; - $inreply .= "of " . $date if(defined $date); - } - - $reply->replace('In-Reply-To', $inreply); - - # Quote the body - $body = $reply->body; - - @$body = @{$me->body}; # copy body - $reply->remove_sig; # remove signature, if any - $reply->tidy_body; # tidy up - map { s/\A/$indent/ } @$body; # indent - - # Add references - unshift @{$body}, (defined $name ? $name . " " : "") . "<$id> writes:\n"; - - if(defined $arg{Keep} && 'ARRAY' eq ref($arg{Keep})) - { - # Copy lines from the original - my $keep; - - foreach $keep (@{$arg{Keep}}) - { - my $ln = $me->get($keep); - $reply->replace($keep,$ln) if(defined $ln); - } - } - - if(defined $arg{Exclude} && 'ARRAY' eq ref($arg{Exclude})) - { - # Exclude lines - $reply->delete(@{$arg{Exclude}}); - } - - # remove empty header lins - $reply->head->cleanup; - - $reply; -} - -sub add_signature -{ - my $me = shift; - carp "add_signature depriciated, use ->sign" if $^W; - $me->sign(File => shift || "$ENV{HOME}/.signature"); -} -sub sign -{ - my $me = shift; - my %arg = @_; - my $sig; - my @sig; + my $indent = $arg{Indent} || ">"; + if($indent =~ /\%/) + { my %hash = ( '%' => '%'); + my @name = $name ? grep( {length $_} split /[\n\s]+/, $name) : ''; - if($sig = delete $arg{File}) - { - local *SIG; + $hash{f} = $name[0]; + $hash{F} = $#name ? substr($hash{f},0,1) : $hash{f}; - if(open(SIG,$sig)) - { - local $_; - while(<SIG>) { last unless /\A(--)?\s*\Z/; } + $hash{l} = $#name ? $name[$#name] : ""; + $hash{L} = substr($hash{l},0,1) || ""; - @sig = ($_,<SIG>,"\n"); + $hash{n} = $name || ""; + $hash{I} = join "", map {substr($_,0,1)} @name; - close(SIG); + $indent =~ s/\%(.)/defined $hash{$1} ? $hash{$1} : $1/eg; } - } - elsif($sig = delete $arg{Signature}) - { - @sig = ref($sig) ? @$sig : split(/\n/, $sig); - } - - if(@sig) - { - $me->remove_sig; - map(s/\n?\Z/\n/,@sig); - push(@{$me->body}, "-- \n",@sig); - } -} - -sub _prephdr { - - use Mail::Util; - - my $hdr = shift; - - $hdr->delete('From '); # Just in case :-) - # An original message should not have any Received lines + my $id = $sender->address; + $reply->replace(To => $id); + + # Find addresses not to include + my $mailaddresses = $ENV{MAILADDRESSES} || ""; + + my %nocc = (lc($id) => 1); + $nocc{lc $_->address} = 1 + for Mail::Address->parse($reply->get('Bcc'), $mailaddresses); + + if($arg{ReplyAll}) # Who shall we copy this to + { my %cc; + foreach my $addr (Mail::Address->parse($self->get('To'), $self->get('Cc'))) + { my $lc = lc $addr->address; + $cc{$lc} = $addr->format + unless $nocc{$lc}; + } + my $cc = join ', ', values %cc; + $reply->replace(Cc => $cc); + } - $hdr->delete('Received'); + # References + my $refs = $self->get('References') || ""; + my $mid = $self->get('Message-Id'); - $hdr->replace('X-Mailer', "Perl5 Mail::Internet v".$Mail::Internet::VERSION) - unless $hdr->count('X-Mailer'); + $refs .= " " . $mid if defined $mid; + $reply->replace(References => $refs); - my $name = eval {local $SIG{__DIE__}; (getpwuid($>))[6]} || $ENV{NAME} ||""; + # In-Reply-To + my $date = $self->get('Date'); + my $inreply = ""; - while($name =~ s/\([^\(\)]*\)//) { 1; } + if(defined $mid) + { $inreply = $mid; + my @comment; + push @comment, "from $name" if defined $name; + push @comment, "on $date" if defined $date; + local $" = ' '; + $inreply .= " (@comment)" if @comment; + } + elsif(defined $name) + { $inreply = $name . "'s message"; + $inreply .= "of " . $date if defined $date; + } + $reply->replace('In-Reply-To' => $inreply); + + # Quote the body + my $body = $reply->body; + @$body = @{$self->body}; # copy body + $reply->remove_sig; + $reply->tidy_body; + s/\A/$indent/ for @$body; + + # Add references + unshift @{$body}, (defined $name ? $name . " " : "") . "<$id> writes:\n"; + + if(defined $arg{Keep} && ref $arg{Keep} eq 'ARRAY') # Include lines + { foreach my $keep (@{$arg{Keep}}) + { my $ln = $self->get($keep); + $reply->replace($keep => $ln) if defined $ln; + } + } - if($name =~ /[^\w\s]/) { - $name =~ s/"/\"/g; - $name = '"' . $name . '"'; + if(defined $arg{Exclude} && ref $arg{Exclude} eq 'ARRAY') # Exclude lines + { $reply->delete(@{$arg{Exclude}}); } - my $from = sprintf "%s <%s>", $name, Mail::Util::mailaddress(); - $from =~ s/\s{2,}/ /g; + $reply->head->cleanup; # remove empty header lines + $reply; +} - my $tag; - foreach $tag (qw(From Sender)) { # Sender is deprecated - $hdr->add($tag,$from) - unless($hdr->get($tag)); - } -} +sub smtpsend($@) +{ my ($self, %opt) = @_; -sub smtpsend; + require Net::SMTP; + require Net::Domain; -use Carp; -use Mail::Util qw(mailaddress); -use Mail::Address; -use Net::Domain qw(hostname); -use Net::SMTP; -use strict; + my $host = $opt{Host}; + my $envelope = $opt{MailFrom} || mailaddress(); + my $quit = 1; + + my ($smtp, @hello); - sub smtpsend -{ - my $src = shift; - my %opt = @_; - my $host = $opt{Host}; - my $noquit = 0; - my $smtp; - my @hello = defined $opt{Hello} ? (Hello => $opt{Hello}) : (); + push @hello, Hello => $opt{Hello} + if defined $opt{Hello}; - push(@hello, 'Port', $opt{'Port'}) - if exists $opt{'Port'}; + push @hello, Port => $opt{Port} + if exists $opt{Port}; - push(@hello, 'Debug', $opt{'Debug'}) - if exists $opt{'Debug'}; + push @hello, Debug => $opt{Debug} + if exists $opt{Debug}; - unless(defined($host)) { - local $SIG{__DIE__}; + if(!defined $host) + { local $SIG{__DIE__}; my @hosts = qw(mailhost localhost); - unshift(@hosts, split(/:/, $ENV{SMTPHOSTS})) if(defined $ENV{SMTPHOSTS}); + unshift @hosts, split /\:/, $ENV{SMTPHOSTS} + if defined $ENV{SMTPHOSTS}; - foreach $host (@hosts) { - $smtp = eval { Net::SMTP->new($host, @hello) }; - last if(defined $smtp); + foreach $host (@hosts) + { $smtp = eval { Net::SMTP->new($host, @hello) }; + last if defined $smtp; } } - elsif(ref($host) && UNIVERSAL::isa($host,'Net::SMTP')) { - $smtp = $host; - $noquit = 1; + elsif(UNIVERSAL::isa($host,'Net::SMTP') + || UNIVERSAL::isa($host,'Net::SMTP::SSL')) + { $smtp = $host; + $quit = 0; } - else { - local $SIG{__DIE__}; + else + { local $SIG{__DIE__}; $smtp = eval { Net::SMTP->new($host, @hello) }; } - return () - unless(defined $smtp); - - my $hdr = $src->head->dup; + defined $smtp or return (); - _prephdr($hdr); + my $head = $self->cleaned_header_dup; # Who is it to - my @rcpt = map { ref($_) ? @$_ : $_ } grep { defined } @opt{'To','Cc','Bcc'}; - @rcpt = map { $hdr->get($_) } qw(To Cc Bcc) + my @rcpt = map { ref $_ ? @$_ : $_ } grep { defined } @opt{'To','Cc','Bcc'}; + @rcpt = map { $head->get($_) } qw(To Cc Bcc) unless @rcpt; - my @addr = map($_->address, Mail::Address->parse(@rcpt)); - return () - unless(@addr); + my @addr = map {$_->address} Mail::Address->parse(@rcpt); + @addr or return (); - $hdr->delete('Bcc'); # Remove blind Cc's + $head->delete('Bcc'); # Send it - my $ok = $smtp->mail( mailaddress() ) && - $smtp->to(@addr) && - $smtp->data(join("", @{$hdr->header},"\n",@{$src->body})); - - $smtp->quit - unless $noquit; + my $ok = $smtp->mail($envelope) + && $smtp->to(@addr) + && $smtp->data(join("", @{$head->header}, "\n", @{$self->body})); + $quit && $smtp->quit; $ok ? @addr : (); } -sub send; - -use Mail::Mailer; -use strict; - - sub send -{ - my ($src, $type, @args) = @_; - - my $hdr = $src->head->dup; - _prephdr($hdr); +sub send($@) +{ my ($self, $type, @args) = @_; - my $headers = $hdr->header_hashref; + require Mail::Mailer; - # Actually send it + my $head = $self->cleaned_header_dup; my $mailer = Mail::Mailer->new($type, @args); - $mailer->open($headers); - $src->print_body($mailer); - $mailer->close(); -} -sub nntppost; - -use Mail::Util qw(mailaddress); -use Net::NNTP; -use strict; + $mailer->open($head->header_hashref); + $self->print_body($mailer); + $mailer->close; +} - sub nntppost -{ - my $mail = shift; - my %opt = @_; - my $groups = $mail->get('Newsgroups') || ""; - my @groups = split(/[\s,]+/,$groups); +sub nntppost +{ my ($self, %opt) = @_; - return () - unless @groups; + require Net::NNTP; - my $hdr = $mail->head->dup; + my $groups = $self->get('Newsgroups') || ""; + my @groups = split /[\s,]+/, $groups; + @groups or return (); - _prephdr($hdr); + my $head = $self->cleaned_header_dup; # Remove these incase the NNTP host decides to mail as well as me - $hdr->delete(qw(To Cc Bcc)); + $head->delete(qw(To Cc Bcc)); my $news; - my $noquit = 0; - my $host = $opt{Host}; + my $quit = 1; - if(ref($host) && UNIVERSAL::isa($host,'Net::NNTP')) { - $news = $host; - $noquit = 1; + my $host = $opt{Host}; + if(ref($host) && UNIVERSAL::isa($host,'Net::NNTP')) + { $news = $host; + $quit = 0; } - else { - my @opt = (); + else + { my @opt = $opt{Host}; - push(@opt, $opt{'Host'}); + push @opt, Port => $opt{Port} + if exists $opt{Port}; - push(@opt, 'Port', $opt{'Port'}) - if exists $opt{'Port'}; + push @opt, Debug => $opt{Debug} + if exists $opt{Debug}; - push(@opt, 'Debug', $opt{'Debug'}) - if exists $opt{'Debug'}; - - $news = new Net::NNTP(@opt) + $news = Net::NNTP->new(@opt) or return (); } - $news->post(@{$hdr->header},"\n",@{$mail->body}); - - my $code = $news->code; + $news->post(@{$head->header}, "\n", @{$self->body}); + my $rc = $news->code; - $news->quit - unless $noquit; + $news->quit if $quit; - return 240 == $code ? @groups : (); + $rc == 240 ? @groups : (); } -sub escape_from -{ - my $me = shift; - my $body = $me->body; - local $_; - - scalar grep { s/\A(>*From) />$1 /o } @$body; +sub escape_from +{ my $body = shift->body; + scalar grep { s/\A(>*From) />$1 /o } @$body; } -sub unescape_from -{ - my $me = shift; - my $body = $me->body; - local $_; - scalar grep { s/\A>(>*From) /$1 /o } @$body; +sub unescape_from +{ my $body = shift->body; + scalar grep { s/\A>(>*From) /$1 /o } @$body; } -1; # keep require happy - +# Don't tell people it exists +sub cleaned_header_dup() +{ my $head = shift->head->dup; + $head->delete('From '); # Just in case :-) -=head1 NAME - -Mail::Internet - manipulate Internet format (RFC 822) mail messages - -=head1 SYNOPSIS - - use Mail::Internet; - -=head1 DESCRIPTION - -This package provides a class object which can be used for reading, creating, -manipulating and writing a message with RFC822 compliant headers. - -If you start writing a new application, you may want to use the -L<Mail::Box> set of packages (requires perl 5.6.1), which has more -features. See http://perl.overmeer.net/mailbox. - -=head1 CONSTRUCTOR - -=over 4 - -=item new ( [ ARG ], [ OPTIONS ] ) - -C<ARG> is optiona and may be either a file descriptor (reference to a GLOB) -or a reference to an array. If given the new object will be -initialized with headers and body either from the array of read from -the file descriptor. - -C<OPTIONS> is a list of options given in the form of key-value -pairs, just like a hash table. Valid options are - -=over 8 - -=item B<Header> - -The value of this option should be a C<Mail::Header> object. If given then -C<Mail::Internet> will not attempt to read a mail header from C<ARG>, if -it was specified. - -=item B<Body> - -The value of this option should be a reference to an array which contains -the lines for the body of the message. Each line should be terminated with -C<\n> (LF). If Body is given then C<Mail::Internet> will not attempt to -read the body from C<ARG> (even if it is specified). - -=back - -The Mail::Header options C<Modify>, C<MailFrom> and C<FoldLength> may -also be given. - -=back - -=head1 METHODS - -=over 4 - -=item body ( [ BODY ] ) - -Returns the body of the message. This is a reference to an array. -Each entry in the array represents a single line in the message. - -If I<BODY> is given, it can be a referenc to an aray or an array, then -the body will be replaced. If a reference is passed, it is used directly -and not copied, so any sunsequent changes to the array will change the -contents of the body. - -=item print_header ( [ FILEHANDLE ] ) - -=item print_body ( [ FILEHANDLE ] ) - -=item print ( [ FILEHANDLE ] ) - -Print the header, body or whole message to file descriptor I<FILEHANDLE>. -I<$fd> should be a reference to a GLOB. If I<FILEHANDLE> is not given the -output will be sent to STDOUT. - - $mail->print( \*STDOUT ); # Print message to STDOUT - -=item as_string () - -Returns the message as a single string. - -=item as_mbox_string ( [ ALREADY_ESCAPED ] ) - -Returns the message as a string in mbox format. C<ALREADY_ESCAPED>, if -given and true, indicates that ->escape_from has already been called on -this object. - -=item head () - -Returns the C<Mail::Header> object which holds the headers for the current -message - -=back - -=head1 UTILITY METHODS - -The following methods are more a utility type than a manipulation -type of method. - -=over 4 - -=item remove_sig ( [ NLINES ] ) - -Attempts to remove a users signature from the body of a message. It does this -by looking for a line equal to C<'-- '> within the last C<NLINES> of the -message. If found then that line and all lines after it will be removed. If -C<NLINES> is not given a default value of 10 will be used. This would be of -most use in auto-reply scripts. - -=item tidy_body () - -Removes all leading and trailing lines from the body that only contain -white spaces. - -=item reply () - -Create a new object with header initialised for a reply to the current -object. And the body will be a copy of the current message indented. - -=item add_signature ( [ FILE ] ) - -Append a signature to the message. C<FILE> is a file which contains -the signature, if not given then the file "$ENV{HOME}/.signature" -will be checked for. - -=item send ( [ type [ args.. ]] ) - -Send a Mail::Internet message using Mail::Mailer. Type and args are -passed on to C<Mail::Mailer> - -=item smtpsend ( [ OPTIONS ] ) - -Send a Mail::Internet message via SMTP, requires Net::SMTP - -The return value will be a list of email addresses that the message was sent -to. If the message was not sent the list will be empty. - -Options are passed as key-value pairs. Current options are - -=over 4 - -=item Host - -Name of the SMTP server to connect to, or a Net::SMTP object to use - -If C<Host> is not given then the SMTP host is found by attempting -connections first to hosts specified in C<$ENV{SMTPHOSTS}>, a colon -separated list, then C<mailhost> and C<localhost>. - -=item To - -=item Cc - -=item Bcc - -Send the email to the given addresses, each can be either a string or -a reference to a list of email addresses. If none of C<To>, <Cc> or C<Bcc> -are given then the addresses are extracted from the message being sent. - -=item Hello - -Send a HELO (or EHLO) command to the server with the given name. - -=item Port - -Port number to connect to on remote host - -=item Debug - -Debug value to pass to Net::SMPT, see <Net::SMTP> - -=back - -=item nntppost ( [ OPTIONS ] ) - -Post an article via NNTP, requires Net::NNTP. - -Options are passed as key-value pairs. Current options are - -=over 4 - -=item Host - -Name of NNTP server to connect to, or a Net::NNTP object to use. - -=item Port - -Port number to connect to on remote host - -=item Debug - -Debug value to pass to Net::NNTP, see <Net::NNTP> - -=back - -=item escape_from () - -It can cause problems with some applications if a message contains a line -starting with C<`From '>, in particular when attempting to split a folder. -This method inserts a leading C<`>'> on anyline that matches the regular -expression C</^>*From/> - -=item unescape_from () - -This method will remove the escaping added by escape_from - -=back - -=head1 SEE ALSO + # An original message should not have any Received lines + $head->delete('Received'); -L<Mail::Header> -L<Mail::Address> + $head->replace('X-Mailer', "Perl5 Mail::Internet v".$Mail::Internet::VERSION) + unless $head->count('X-Mailer'); -=head1 AUTHOR + my $name = eval {local $SIG{__DIE__}; (getpwuid($>))[6]} || $ENV{NAME} ||""; -Graham Barr. Maintained by Mark Overmeer <mailtools@overmeer.net> + while($name =~ s/\([^\(\)]*\)//) { 1; } -=head1 COPYRIGHT + if($name =~ /[^\w\s]/) + { $name =~ s/"/\"/g; + $name = '"' . $name . '"'; + } -Copyright (c) 1995-2001 Graham Barr. All rights reserved. This program is free -software; you can redistribute it and/or modify it under the same terms -as Perl itself. + my $from = sprintf "%s <%s>", $name, mailaddress(); + $from =~ s/\s{2,}/ /g; -=cut + foreach my $tag (qw(From Sender)) + { $head->get($tag) or $head->add($tag, $from); + } + $head; +} +1; |
