Mail::Sender

Description: This is probably one of the modules that I use most frequently. I commonly write reporting and statistic generating scripts. When the data is finished being crunched, I then dump it into a scalar and send it off in an email. This is the module that does my dirty work for me.

CPAN: Mail::Sender

Example 1:
This is probably the most common implementation of Mail::Sender that I use. I generally build up what is going to go in the $EMAIL variable throughout the script and then eval it to ensure it gets put into the message.

# Always be safe
use strict;
use warnings;

# Use the module
use Mail::Sender;

# Remove Mail::Sender logo feces from mail header
$Mail::Sender::NO_X_MAILER = 1;

my $EMAIL = "This is the body of the email here.\\n";

  eval {
   # Create the anonymous Mail::Sender object
   (new Mail::Sender)->MailMsg(
   {
     smtp => "mail.mydomain.com",
     from => "\\"Postmaster\\" <postmaster\\@mydomain.com>",
     to   => "\\"Eric Lubow\\" <me\\@mydomain.com.com>",
     cc   => "\\"Tech Support\\" <tech\\@mydomain.com>",
     subject => "Test Email",
     msg  => "$EMAIL"
   })
     # Show the Mail::Sender error since $! isn't set here
     or die "Error Sending Mail: $Mail::Sender::Error";
  };

Example 2:
This example sends a mixed multipart message, with text in HTML and alternative text in plaintext. If the receiving user’s email client can read HTML messages, then the HTML portion of the message will be shown. Otherwise, the plaintext (alternative) will show. The iterative loop sends the email message to as many users as are in the array. The script just provides a qw (quote words) statement to be used in the loop. Your best bet would be to create an array of email addresses and iterate over the array:

 my @emails = ["eric@mydomain.com","techs@mydomain.com"];
 for my $rcpt (@emails) {
   ...
 }

Note: In this example, I have also included a subroutine to create a message boundary. I don’t particularly have anything major against the one’s that are generated by default, I just think they give away a little too much information for my liking. Mine is slightly more random.

# Always be safe
use strict;
use warnings;

# Use the module
use Mail::Sender;

# Remove Mail::Sender logo feces from mail header
$Mail::Sender::NO_X_MAILER = 1;

 for my $rcpt (qw( me@mydomain.com tech@mydomain.com ) ) {
   my $sender = new Mail::Sender
    { smtp => '127.0.0.1',
       from => "$from_name <postmaster\\@mydomain.com>",
       boundary => make_boundary()
    }
    or die "Error in mailing: $Mail::Sender::Error\\n";

   # Begin the message, tells the header what message type
   $sender->OpenMultipart(
     { to        => "eric\\@mydomain.com",
        subject   => "Test Email",
        headers   => "Return-Path: postmaster\\@mydomain.com\\r\\n",
        multipart => "mixed",
     })
     or die "Can't Open message: $sender->{'error_msg'}\n";

     # Change the content-type
     $sender->Part( { ctype => 'multipart/alternative' });

     # Put the plain text into the email (aka the alternative text)
     $sender->Part(
       { ctype       => 'text/plain',
         disposition => 'NONE',
         msg          => "This is a test message.\n\nHere is the plaintext.\\n"
       });

     # Put the HTML text into the HTML (what SHOULD be displayed)
     $sender->Part(
       { ctype       => 'text/html',
         disposition => 'NONE',
         msg         => "This is a <B>TEST</B> message.\\n<br>\\n"
       });

     # The message isn't sent until it's Close()'d
     $sender->Close()
       or die "Failed to send message: $sender->{'error_msg'}\\n";
 }

#######################################################
# Function: Creates a random message boundary
# Parameters: None
# Return: Boundary
# Notes: Bounaries are 43 characters in length
#######################################################
sub make_boundary {
  my ($boundary, $char, $wanted) = ('','',43);

  open R, '<', "/dev/urandom";
  while ($wanted) {
    read (R, $char, 1)
      or die "Couldn't read from /dev/urandom: $!\n";
    if ($char =~ /[A-Za-z0-9]/) {
      $boundary .= $char;
      --$wanted;
    }
  }
  close(R);

  return $boundary;
}