how to send SMTP email in perl - perl

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;

Related

sending multipart mail in perl

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'} );

Why is MIME::Lite->new() is not working in my server?

I have the following code to mail
#!perl
use MIME::Lite;
open (LOG_FILE, '>Mail_Log.txt');
print LOG_FILE " creating mail\n";
$msg = MIME::Lite->new(
From =>'me#mine.com',
To =>'me#mine.com',
Subject =>'Congrats',
Data =>"some messgae."
);
print LOG_FILE " attaching to mail\n";
$msg->attach
(
Type=>'TEXT',
Path=>'Log.txt',
Filename=>'log File.txt',
Disposition => 'attachment'
);
print LOG_FILE " sending the mail\n";
$msg->send( "smtp", "mailout.server.com" );
print "message sent successfully";
print LOG_FILE " mail sent\n";
The above code works fine in my local. :)
I am able to send and receive mails.
I converted this Perl(.pl) file executable(.exe) using PerlPackager(pp), and transferred this to my windows server where it should actually perform the function. But the execution is stopping after
print LOG_FILE " creating mail\n";
As i can see the log written on to the Mail_Log.txt.
Help me in solving this.
Thanks in advance. :)
You didn't say you have any error messages but this thread may be helpful: Missing MIME\types.db from pp-generated code

Email::MIME can't parse message from Gmail

So I'm using PERL and Email::MIME to get an email from gmail. Here is my code:
use Net::IMAP::Simple::Gmail;
use Email::Mime;
# Creat the object that will read the emails
$server = 'imap.gmail.com';
$imap = Net::IMAP::Simple::Gmail->new($server);
# User and password
$user = 'username#gmail.com';
$password = 'passowrd';
$imap->login($user => $password);
# Select the INBOX and returns the number of messages
$numberOfMessages = $imap->select('INBOX');
# Now let's go through the messages from the top
for ($i = 1; $i <= $numberOfMessages; $i++)
{
$top = $imap->top($i);
print "top = $top\n";
$email = Email::MIME->new( join '', #{ $imap->top($i) } );
$body = $email->body_str;
print "Body = $body\n";
}#end for i
When I run it, I get the following error:
can't get body as a string for multipart/related; boundary="----=_Part_6796768_17893472.1369009276778"; type="text/html" at /Library/Perl/5.8.8/Email/Mime.pm line 341
Email::MIME::body_str('Email::MIME=HASH(0x87afb4)') called at readPhoneEmailFeed.pl line 37
If I replace
$body = $email->body_str;
with
$body = $email->body;
I get the output:
Body =
(i.e. empty string)
What's going on here? is there a way for me to get the raw body of the message (->body_raw doesn't work either)? I'm okay with parsing out the body using regex
Email::MIME is not the best documented package I have ever seen.
The body and body_str methods only work on a single mime part. Mostly that would be a simple text message. For anything more complex use the parts method to get each mime component which is itself an Email::MIME object. The body and body_str methods should work on that. An html formatted message will generally have two MIME parts: text/plain and text/html.
This isn't exactly what you want but should be enough to show you what is going on.
my #parts = $email->parts;
for my $part (#parts) {
print "type: ", $part->content_type, "\n";
print "body: ", $part->body, "\n";
}

Send an Email Perl Using MIME::Lite

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.

Perl - How to get the email address from the FROM part of header?

I am trying to set up this script for my local bands newsletter.
Currently, someone sends an email with a request to be added, we manually add it to newsletter mailer I set up.
(Which works great thanks to help I found here!)
The intent now is to have my script below log into the email account I set up for the list on our server, grab the info to add the email automatically.
I know there are a bunch of apps that do this but, I want to learn myself.
I already have the "add to list" working when there is an email address returned from the header(from) below BUT, sometimes the header(from) is a name and not the email address (eg "persons name" is returned from persons name<email#address> but, not the <email#address>.)
Now, I am not set in stone on the below method but, it works famously... to a point.
I read all the docs on these modules and there was nothing I could find to get the darn email in there all the time.
Can someone help me here? Verbose examples are greatly appreciated since I am struggling learning Perl.
#!/usr/bin/perl -w
##########
use CGI;
use Net::IMAP::Simple;
use Email::Simple;
use IO::Socket::SSL; #optional i think if no ssl is needed
use strict;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
######################################################
# fill in your details here
my $username = '#########';
my $password = '#############';
my $mailhost = '##############';
#######################################################
print CGI::header();
# Connect
my $imap = Net::IMAP::Simple->new($mailhost, port=> 143, use_ssl => 0, ) || die "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";
# Log in
if ( !$imap->login( $username, $password ) ) {
print STDERR "Login failed: " . $imap->errstr . "\n";
exit(64);
}
# Look in the INBOX
my $nm = $imap->select('INBOX');
# How many messages are there?
my ($unseen, $recent, $num_messages) = $imap->status();
print "unseen: $unseen, <br />recent: $recent, <br />total: $num_messages<br />\n\n";
## Iterate through unseen messages
for ( my $i = 1 ; $i <= $nm ; $i++ ) {
if ( $imap->seen($i) ) {
my $es = Email::Simple->new( join '', #{ $imap->top($i) } );
printf( "[%03d] %s\n\t%s\n", $i, $es->header('From'), $es->header('Subject'));
print "<br />";
next;
}## in the long version these are pushed into different arrays for experimenting purposes
else {
my $es = Email::Simple->new( join '', #{ $imap->top($i) } );
printf( "[%03d] %s\n\t%s\n", $i, $es->header('From'), $es->header('Subject'));
print "<br />";
}
}
# Disconnect
$imap->quit;
exit;
use Email::Address;
my #addresses = Email::Address->parse('persons name <email#address>');
print $addresses[0]->address;
The parse method returns an array, so the above way works for me.
I'm making this a separate answer because even though this information is hidden in the comments of the accepted answer, it took me all day to figure that out.
First you need to get the From header using something like Email::Simple. THEN you need to extract the address portion with Email::Address.
use Email::Simple;
use Email::Address;
my $email = Email::Simple->new($input);
my $from = $email->header('From');
my #addrs = Email::Address->parse($from);
my $from_address = $addrs[0]->address; # finally, the naked From address.
Those 4 steps in that order.
The final step is made confusing by the fact that Email::Address uses some voodoo where if you print the parts that Email::Address->parse returns, they will look like simple strings, but they are actually objects. For example if you print the result of Email::Address->parse like so,
my #addrs = Email::Address->parse($from);
foreach my $addr (#addrs) { say $addr; }
You will get the complete address as output:
"Some Name" <address#example.com>
This was highly confusing when working on this. Granted, I caused the confusion by printing the results in the first place, but I do that out of habit when debugging.