I need to write a perl script for sending emails. The script should read .txt document containing the e-mail addresses as its first argument (there could be more than one address, and they are all separated with ";") and an .html document that should be the body of the e-mail as its second.
#!/usr/bin/perl -w
use Net::SMTP::SSL;
sub send_mail {
my $to = $ARGV[0];
open(MYFILE, $to) || die("Could not open file!");
@recepients=<MYFILE>;
close(MYFILE);
my $body = $ARGV[1];
open (TXTFILE, $body);
@lines = <TXTFILE>;
close(TXTFILE);
$body = join("",@lines);
my $from = 'theAddress@gmail.com';
my $password = 'thePassword';
my $smtp;
if (not $smtp = Net::SMTP::SSL->new('smtp.gmail.com',
Port => 465,
Debug => 1)) {
die "Could not connect to server\n";
}
$smtp->auth($from, $password) || die "Authe开发者_高级运维ntication failed!\n";
$smtp->mail($from . "\n");
my @recepients = split(/;/, $to);
foreach my $recp (@recepients) {
$smtp->to($recp . "\n");
}
$smtp->data();
$smtp->datasend("From: " . $from . "\n");
$smtp->datasend("To: " . $to . "\n");
$smtp->datasend("Subject: " . $subject . "\n");
$smtp->datasend("\n");
$smtp->datasend($body . "\n");
$smtp->dataend();
$smtp->quit;
}
&send_mail()
So I tried to work something out, but I have a problem with extracting the information both from the .txt and .html documents. So the error should be somewhere at the splitting of the recipients.
There were several issues in your script. I would suggest you to use Perl::Critic as it analyzes your code and usually gives helpful hints.
The following works:
#!/usr/bin/env perl
Always use strict
and warnings
use strict;
use warnings;
use Net::SMTP::SSL;
English
will give a textual representation of error messages
use English qw(-no_match_vars);
Carp
issues warnings and error from the perspective of the caller
use Carp;
our $VERSION = '1.0.0';
sub send_mail {
my ( $to, $body ) = @_;
it is better to have filehandles as variables too
my $to_handle;
my $text_handle;
Always declare variables
my @recipients;
my @lines;
Always check the return value of system calls (open, close, ...)
# print the error message in case of errors
open $to_handle, '<', $to
or croak "Error opening $to: $OS_ERROR";
@recipients = <$to_handle>;
close $to_handle
or croak "Error closing $to: $OS_ERROR";
open $text_handle, '<', $body
or croak "Error opening $body: $OS_ERROR";
@lines = <$text_handle>;
close $text_handle
or croak "Error closing $body: $OS_ERROR";
$body = join '', @lines;
my $from = '.....@gmail.com';
I would avoid putting a password in the script source
my $password = '*****';
my $smtp;
Don't put a new line at the end of die/warn/... as it will remove the line number where the error occurred
$smtp = Net::SMTP::SSL->new(
'smtp.gmail.com',
Port => 465,
Debug => 1
) or croak 'Could not connect to server';
$smtp->auth( $from, $password )
or croak 'Authentication failed!';
$smtp->mail( $from . "\n" );
# removed trailing \n
chomp $recipients[0];
The ;
separated list is in the first line (the first element of your array): you have to split the first line.
foreach my $recp ( split /;/mxs, $recipients[0] ) {
$smtp->to( $recp . "\n" );
}
$smtp->data();
$smtp->datasend( "From: $from\n" );
$smtp->datasend( "To: $to\n" );
$subject
was not defined, you would have detected it with strict
and warnings
$smtp->datasend("Subject: Test\n");
$smtp->datasend("\n");
$smtp->datasend("$body\n" );
$smtp->dataend();
$smtp->quit;
It is a good practice to end subroutines with a return as perl uses the result of the last evaluation as a result if return is not specified.
return;
}
Evaluate ARGV
in the main body. You will loose clarity if you scatter the processing in one or several subroutines
if ( !$ARGV[0] || !$ARGV[1] ) {
print STDERR "usage: send to content\n";
exit 1;
}
There was a missing semicolon. You don't need to use & to call subroutines
send_mail( $ARGV[0], $ARGV1 );
1;
精彩评论