Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 475
  • Last Modified:

How to modify Perl subroutine to add extra parameter

Hi,

I've been trying to modify a simple SMTP mail send script that I found online, but am struggling, being a Perl newbie and all. The script is as follows:
 
sub send_mail # send SMTP mail
	{
        my ($from, $to_addr, $subject, $body, $msg);

        $from       = shift;
        $to_addr    = shift;
        $subject	= shift;
        $body       = shift;
		$date 		= strftime "%a, %d %b %y %H:%M:%S %z",localtime;
        
        $msg = "MIME-Version: 1.0\n"
             . "From: $from\n"
             . "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
             . "Date: $date\n"
             . "Subject: $subject\n\n"      # Double \n
             . $body;
		
        #
        # Open an SMTP session
        #
        $smtp = Net::SMTP->new( $SMTP_HOST,
                                'Debug' => 0,       # Change to a 1 to turn on debug messages
                            );

        if(!defined($smtp) || !($smtp))
        {
            print "SMTP ERROR: Unable to open smtp session.\n";

            return 0;
        }

        #
        # Pass the 'from' email address, exit if error
        #
        if (! ($smtp->mail( $from ) ) )
        {
            return 0;
        }

        #
        # Pass the recipient address(es)
        #
        if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) )
        {
            return 0;
        }

        #
        # Send the message
        #
        $smtp->data( $msg );

        $smtp->quit;
    }

Open in new window


I would like to pass the subroutine an extra parameter "bcc" which it would then use, if passed, to bcc the email. At the moment I can't work out how to do it.

Also I don't understand how comes the script can handle multiple "to" addresses, which it apparently can - how does it know which parameter is an email address and which is one of the parameters passed after the email addys? I get the impression its this line : ( ref($to_addr) ? join(';', @$to_addr) : $to_addr )  -- but no idea how it works!

Thanks
0
georgemason
Asked:
georgemason
  • 4
  • 3
1 Solution
 
wilcoxonCommented:
Here's a slightly reformatted and modified version of your sub that will accept bcc addresses as the third argument (after to addresses).  Just change the order of arguments on the "my (...) = @_" line if you want it to be in a different order.

For to (and bcc), if you want to pass multiple addresses, they need to be in an array ref.  You are correct that it is the line with the ref($to_addr) that handles multiple vs single.  Here's a few examples to help illustrate it.

send_mail('me@here.net', 'you@there.net', undef, 'single recipient, no bcc', $body, $msg);
send_mail('me@here.net', ['you@there.net', 'him@elsewhere.net'], 'me@here.net', 'multiple to and single bcc', $body, $msg);
# send SMTP mail
sub send_mail {
    my ($from, $to_addr, $bcc, $subject, $body, $msg) = @_;

    $date = strftime "%a, %d %b %y %H:%M:%S %z",localtime;
    
    $msg = "MIME-Version: 1.0\n"
         . "From: $from\n"
         . "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
         . "Date: $date\n"
         . "Subject: $subject\n\n"      # Double \n
         . $body;
            
    #
    # Open an SMTP session
    #
    $smtp = Net::SMTP->new( $SMTP_HOST,
                            Debug => 0, # Change to 1 to turn on debug messages
                        );

    unless ($smtp) {
        print "SMTP ERROR: Unable to open smtp session.\n";
        return 0;
    }

    #
    # Pass the 'from' email address, exit if error
    #
    $smtp->mail($from) or return 0;

    #
    # Pass the recipient address(es)
    #
    $smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) or return 0;
    $smtp->bcc( ( ref($bcc) ? @$bcc : $bcc ) ) or return 0;

    #
    # Send the message
    #
    $smtp->data( $msg );

    $smtp->quit;
}

Open in new window

0
 
zicevaCommented:
Try this:

[code]
sub send_mail # send SMTP mail
      {
        my ($from, $to_addr,$bcc, $subject, $body, $msg);

        $from       = shift;
        $to_addr    = shift;
        $bcc        = shift;
        $subject      = shift;
        $body       = shift;
      $date             = strftime "%a, %d %b %y %H:%M:%S %z",localtime;
       
        $msg = "MIME-Version: 1.0\n"
             . "From: $from\n"
             . "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
             . "Bcc: $bcc\n"
             . "Date: $date\n"
             . "Subject: $subject\n\n"      # Double \n
             . $body;
            
        #
        # Open an SMTP session
        #
        $smtp = Net::SMTP->new( $SMTP_HOST,
                                'Debug' => 0,       # Change to a 1 to turn on debug messages
                            );

        if(!defined($smtp) || !($smtp))
        {
            print "SMTP ERROR: Unable to open smtp session.\n";

            return 0;
        }

        #
        # Pass the 'from' email address, exit if error
        #
        if (! ($smtp->mail( $from ) ) )
        {
            return 0;
        }

        #
        # Pass the recipient address(es)
        #
        if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) )
        {
            return 0;
        }

        #
        # Send the message
        #
        $smtp->data( $msg );

        $smtp->quit;
    }

[/code]

The "To" param can be an array like this:
@mail_list=("user1@domain1.com","user2@domain2.com");
0
 
wilcoxonCommented:
ziceva's solution has three problems:
1) It will probably (not 100% sure) print the bcc recipient in the message (the $msg is the data/body)
2) It will not actually send the email to the bcc recipient ($smtp->recipient or $smtp->bcc must be called)
3) His description of the "To" param is inaccurate - it has to be an arrey reference (not an array)
0
A proven path to a career in data science

At Springboard, we know how to get you a job in data science. With Springboard’s Data Science Career Track, you’ll master data science  with a curriculum built by industry experts. You’ll work on real projects, and get 1-on-1 mentorship from a data scientist.

 
georgemasonAuthor Commented:
@wilcoxon - excellent post in the first place, and thanks for the critique of the other poster's code. I've implemented your suggestions and the script works flawlessly.

One more question I have, since you're so good at explanations!

I notice you're using "unless (condition) command" to only run commands in the event that the condition evaluates to something other than zero - I assume this would occur if there was an error. Is there any way that I can use the same idea, to only run commands if something completes without error?

What I'm thinking is that I'm making some system calls to reset passwords etc. as below:

system("echo $password | passwd --stdin $reseller");
            print LOGFILE &currentTime . " Created user $reseller with password $password\n";

I'd like the log entry to only occur if the passwd command exits correctly - i'm guessing this can be done with unless?
0
 
wilcoxonCommented:
Sure.  In the case of system, it would need to be something like these...

# simplest that works because system returns 0 on success
system("echo $password | passwd --stdin $reseller") or
print LOGFILE &currentTime . " Created user $reseller with password $password\n";

# alternate that is a little more readable - only does print on successful system call
my $stat = system("echo $password | passwd --stdin $reseller");
print LOGFILE &currentTime . " Created user $reseller with password $password\n" unless $stat;

On a system or exec call failure, you can examine $? to figure out exactly what the problem is (see "perldoc -f system" for more details).
0
 
georgemasonAuthor Commented:
Great explanation, for your extra help I'll double the points. Thanks for taking the time to post - really appreciated.
0
 
georgemasonAuthor Commented:
Apologies, awarded points to wrong person, have requested it be changed.

DOH!
0
 
georgemasonAuthor Commented:
Excellent response, worked perfectly and I learnt a bit in the process. Thanks very much!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Build your data science skills into a career

Are you ready to take your data science career to the next step, or break into data science? With Springboard’s Data Science Career Track, you’ll master data science topics, have personalized career guidance, weekly calls with a data science expert, and a job guarantee.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now