i am trying to send a mail through Perl script using net::smtp module.It works fine when i send the normal mail without any attachment.i wont receive any mail.
use Net::SMTP;
use MIME::Base64;
use File::Basename;
use MIME::Base64 qw( encode_base64 );
use MIME::Base64 qw( decode_base64 );
#attachments = 'C:\Users\ups7kor\Desktop\scripts\commadnline\appending.pl';
$toAddress = '***';
$fromAddress = '***';
$ServerName = '***';
my $boundary = 'End Of mail';
my $smtp = Net::SMTP->new($ServerName, Timeout => 60) or print $failureLogHandler ++$errrorCount.")ERROR:Could not create SMTP object . \n\t please check SMPT Adress in $iniFileData{INI_SMTP_SERVER_NAME} of $iniFileSection{INI_EMAIL} section ";
$smtp->mail($fromAddress);
$smtp->recipient($toAddress, { SkipBad => 1 });
$smtp->data();
$smtp->datasend("To: $toAddress\n");
$smtp->datasend("From: $fromAddress\n");
$smtp->datasend("Subject: $subject\n");
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-type: multipart/mixed;\n\tboundary=\"$boundary\"\n");
$smtp->datasend("--$boundary\n");
$smtp->datasend("Content-type: text/plain\n");
$smtp->datasend("Content-Disposition: quoted-printable\n");
$smtp->datasend("\n $messageBody\n");
if(#attachments)
{
$smtp->datasend("--$boundary\n");
foreach $attachment (#attachments)
{
open(DAT, $attachment) || die("Could not open text file!");
my #textFile = <DAT>;
close(DAT);
my $filename = basename($attachment);
$smtp->datasend("Content-Type: application/text; name=\"$filename\"\n");
$smtp->datasend("Content-Disposition: attachment; filename=\"$filename\"\n");
$smtp->datasend("\n");
$smtp->datasend("#textFile\n");
}
}
$smtp->datasend("--$boundary --\n");
$smtp->dataend();
$smtp->quit;
But if i try the same code in other machine it works file.
Why the same code is not working in my machine and working fine in other machine.
Please help out.
You're using some rather low-level tools for building your message. That would probably work, but you'd need to implement all of the rules for building MIME messages - which sounds far too much like hard work.
Whenever I want to do something with email and Perl, I look for the appropriate module in the Email::* namespace. I'd probably start with Email::MIME, but I note that now includes a pointer to Email::Stuffer, which might well be even simpler.
You could use MIME::Lite module.
See: https://metacpan.org/pod/MIME::Lite#Create-a-multipart-message
Synopsis:
### Create the multipart "container":
$msg = MIME::Lite->new(
From =>'me#myhost.com',
To =>'you#yourhost.com',
Cc =>'some#other.com, some#more.com',
Subject =>'A message with 2 parts...',
Type =>'multipart/mixed'
);
### Add the text message part:
### (Note that "attach" has same arguments as "new"):
$msg->attach(
Type =>'TEXT',
Data =>"Here's the GIF file you wanted"
);
### Add the image part:
$msg->attach(
Type =>'image/gif',
Path =>'aaa000123.gif',
Filename =>'logo.gif',
Disposition => 'attachment'
);
Update: As per Dave's comment:
Check out Email::Stuffer module. Creating multipart message with it is really simple.
Email::Stuffer->to('Simon Cozens<simon#somewhere.jp>')
->from('Santa#northpole.org')
->text_body("You've been good this year. No coal for you.")
->attach_file('choochoo.gif')
->send;
You can use Mail::Sender module to send mails with attachment with body included. Just a small example of how to implement if you have this module in place.
my $sender = new Mail::Sender {smtp => 'server name', from =>
'emailId'};
$sender->MailFile( {to => 'xxx.gmail.com,yyy.gmail.com', subject => 'some subject that you want to put',
msg => "Body of the mail", file => 'path for the attachment that you need to send'} );
Related
I have a legacy app that needs to change. it is written in perl and uses send::mail to send mails to users. Previously we sent links in the email message body but now they want pdf attachments instead. The PDF's are generated on another server using php.
the workflow would be
create the email body
get the pdf from another server via a URL
add the pdf as an attachment to the email
send it.
I think I can use
use LWP::Simple;
unless (defined ($content = get $URL)) {
die "could not get $URL\n";
}
to get the contents of the URL but I can't figure out how to use that var as an attachment in sendmail. current sendmail code is:
my %maildata = (To => $to,
From => 'OurSite - Billing <billing#ourSite.com>',
Organization => 'OurSite, LLC http://www.OurSite.com/',
Bcc => 'sent-billing#ourSite.com',
Subject => $subject{$message} || 'ourSite invoice',
Message => $body
);
print STDERR "notify1 now calling sendmail\n";
sendmail(%maildata) || print STDERR $Mail::Sendmail::error;
The other issue I have is I don't know how to find out if the version of sendmail I have (old freebsd system) is even capable of sending attachments ?
ok thanks for the posters who gave me some direction / the will to give it a go.
In the end I built the mime body doing the following
use LWP::Simple;
use MIME::Base64;
unless (defined ($content = get $URL)) {
die "could not get $URL\n";
}
my $pdfencoded = encode_base64($content);
my %maildata = (To => $to,
From => 'OurSite - Billing <billing#ourSite.com>',
Organization => 'OurSite, LLC http://www.OurSite.com/',
Bcc => 'sent-billing#ourSite.com',
Subject => $subject{$message} || 'ourSite invoice',
);
my $boundary = "====" . time() . "====";
$maildata{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";
$maildata{'Message'} = "--".$boundary."\n"."Content-Type: text/plain\n".$body.
"\n--".$boundary."\nContent-Transfer-Encoding: base64\nContent-Type:
application/pdf; name=\"invoice.pdf\"\n".$pdfencoded."\n--".$boundary."--";
sendmail(%maildata) || print STDERR $Mail::Sendmail::error;
This gave me a hand built MIME format for the body content.
Thanks for the help !
The following Perl program gives an access denied error at line 44 when I try to print either the entire string or the encoded portion. If I print just the header using $msg->print_header(\*STDOUT).
What I am trying to do is generate a text file that contains all the information that could be used in a telnet command to test a Message Transfer Agent (MTA) by sending an email with an attachment.
use MIME::Lite;
use Net::SMTP;
### Add the sender, recipient and your SMTP mailhost
my $from_address = 'temp999 at gmail.com';
my $to_address = 'test05#gmail.com';
my $mail_host = 'gmail.com';
### Adjust subject and body message
my $subject = 'Testing script';
my $message_body = "I am sending an email with an attachment";
### Adjust the filenames
my $my_file_xlsx = 'c:/temp';
my $your_file_xlsx = 'count.xlsx';
### Create the multipart container
$msg = MIME::Lite->new(
From => $from_address,
To => $to_address,
Subject => $subject,
Type => 'multipart/mixed'
) or die "Error creating multipart container: $!\n";
### Add the text for the message body
$msg->attach(
Type => 'TEXT',
Data => $message_body
) or die "Error adding the text message part: $!\n";
### Adding an Excel file
$msg->attach(
Type => 'application/octet-stream',
Path => $my_file_xlsx,
Filename => $your_file_xlsx,
Disposition => 'attachment'
) or die "Error adding $file_xls: $!\n";
### Send the Message
MIME::Lite->send('smtp', $mail_host, Timeout => 60);
#$msg->send;
$msg->print(\*STDOUT); # Write to a file handle ### LINE 44 ###
#$msg->print_header(\*STDOUT); # Write the header
#$msg->print_body(\*STDOUT); # Write the encoded body
I haven't found anything matching exactly what I am trying to do, but I might not be using the correct terminology when searching.
You're trying to attach the file c:/temp, which is (presumably) a directory, not a file. When MIME::Lite tries to open it as a file to read the contents,it fails with that error. You probably meant to pass c:/temp/count.xlsx as Path.
500 Internal server error when attaching a file, but not when sending without attachment.
use MIME::Lite;
$msg = MIME::Lite->new(
From =>'email#domain.com',
To =>'email#domain2.com',
Subject =>'A message with 2 parts...',
CC => '',
Type =>'TEXT',
Data =>'Thank you for your interest in'
);
### If I comment out the following attachment code the email sends OK, otherwise i get 500 internal server error
$msg->attach(
Type =>'image/gif',
Path =>'/images/tree.gif',
Filename =>'tree.gif',
Disposition => 'attachment'
)or die "error attaching file\n";
$msg->send;
Just a suggestion and a few things I can recommend for this also. Applying this method will allow you to split your text/html parts and attachments to include, so you can send a message with multi attributes if you would like.
use strict;
use warnings;
use MIME::Lite;
my $msg = MIME::Lite->new(
To => 'email#domain2.com',
From => 'email#domain.com',
Subject => 'A message with 2 parts...',
Type => 'multipart/alternative',
);
# Make my text part
my $txt = MIME::Lite->new(
Type => "text/plain",
Data => 'Thank you for your interest in',
);
# Make my html part
my $html = MIME::Lite->new(
Type => 'multipart/related',
);
# Here you can attach what html tags you would like to include.
$html->attach(
Type => 'text/html',
Data => "<b>my html is here</b>",
);
$html->attach(
Type => 'image/gif',
Id => 'tree.gif',
Path => "../images/tree.gif",
);
$msg->attach($txt);
$msg->attach($html);
my $data = $msg->as_string;
Also I seen where you were using die for error handling, no need to do that here.
The error ended up being in that the URI has to be written relative to the script.
So I had to change /images/tree.gif
To
../images/tree.gif
Below is what I wrote to send an email from my mailhost to my individual email address and the error I'm getting.
Could someone please help me with why we are getting the error:
Can't call method "mail" on an undefined value at cmm_ping.pl line 2.
use Net::SMTP;
$smtp->mail("jo-sched#abcd.com");
$smtp->recipient("Myname#XXX-XXXX.com");
$smtp->datasend("From: jo-sched#abcd.com");
$smtp->datasend("To: Myname#xxxx-xxxxxx.com");
$smtp->datasend("Subject: This is a test");
$smtp->datasend("\n");
$smtp->datasend("This is a test");
$smtp->dataend;
$smtp->quit;
The variable $smtp has not yet been defined. Take a look at the usage examples of Net::SMTP. This example pretty much does what your code shall do:
use Net::SMTP;
$smtp = Net::SMTP->new('mailhost');
$smtp->mail($ENV{USER});
$smtp->to('postmaster');
$smtp->data();
$smtp->datasend("To: postmaster\n");
$smtp->datasend("\n");
$smtp->datasend("A simple test message\n");
$smtp->dataend();
$smtp->quit;
Are you familiar with how Object Oriented Perl works?
In order to use an object oriented Perl module, you have to first create an object of that class type. Normally, this is done via the new method:
my $smtp = Net::SMTP->new($mailhost);
Now, $smtp is an object of class Net::SMTP. Basically, it's a reference to a glob where you can store your data structure (who are you sending to, your message, etc.). Then Perl can use this information during method calls (which are just subroutines that are part of the package Net::SMTP).
Here's an example from a program I wrote:
use Net::SMTP;
my $smtp = Net::SMTP->new(
Host => $watch->Smtp_Host,
Debug => $debug_level,
);
if ( not defined $smtp ) {
croak qq(Unable to connect to mailhost "#{[$watch->Smtp_Host]}");
}
if ($smtp_user) {
$smtp->auth( $watch->Smtp_User, $watch->Smtp_Password )
or croak
qq(Unable to connect to mailhost "#{[$watch->Smtp_Host]}")
. qq( as user "#{[$watch->Smtp_User]}");
}
if ( not $smtp->mail( $watch->Sender ) ) {
carp qq(Cannot send as user "#{[$watch->Sender]}")
. qq( on mailhost "#{[$watch->Smtp_Host]}");
next;
}
if ( not $smtp->to($email) ) {
$smtp->reset;
next; #Can't send email to this address. Skip it
}
#
# Prepare Message
#
# In Net::SMTP, the Subject and the To fields are actually part
# of the message with a separate blank line separating the
# actual message from the header.
#
my $message = $watch->Munge_Message( $watcher, $email );
my $subject =
$watch->Munge_Message( $watcher, $email, $watch->Subject );
$message = "To: $email\n" . "Subject: $subject\n\n" . $message;
$smtp->data;
$smtp->datasend("$message");
$smtp->dataend;
$smtp->quit;
I am just trying to send a basic email using Perl and MIME::Lite and I am receiving the following error: SMTP mail() command failed: 5.1.7 Invalid adderess
Here is my code:
#!perl
use MIME::Lite;
#Create Mail
$msg = MIME::Lite->new(
From =>'someone#someplace.com',
To =>'someone#someplace.com',
Cc =>'some#other.com',
Subject =>'Subject Test',
Data =>"Data Test"
);
#Send Mail
$msg->send( "smtp", "mail.place.com" );
Thanks.
I ended up solving it:
sub EMailReport
{
use MIME::Lite;
my $theSubject = "Sub";
my $theData = "Data";
my $theEmail = MIME::Lite->new(
From =>'From#someplace.somewhere.com',
To =>'fistname.lastname#company.com',
Subject =>$theSubject,
Data =>$theData
);
$theEmail->add( "Type" => "multipart/mixed" );
$theEmail->send( "smtp", "somemail.company.com" );
}
You need to pass to send() the smtp arguments I think.