AtomicSoft.com Add power to your website!
Home Products Services Support Free
EasyData/SQL
easy-to-use web interface for SQL databases with countless features
AtomicDesk
help desk, FAQ, knowledge base, live support chat - all in one product
Custom programming
Installation
Documentation
HelpDesk
Libraries
Join our newsletter for information on software updates and new releases. You may unsubscribe at any time.



Click here to download plain text source code.

# subroutine name: send_mail
# Sends e-mail message via sendmail (standard Unix program) or
# via SMTP server (requires sendmail.pm module).
# Input:
#   $from - "from" (sender) e-mail address
#   $to - "to" (recipient) e-mail address
#   $subject - subject of message
#   $message - e-mail message body
#   $bcc - reference to array of BCC recipients
#   $bcc_max_addresses - max. number of BCC recipients in one envelope
#
# If mailing variables ($mailprog, $smtp_server) are set incorrectly,
# makes CGI process exit with error.
#
# Returns: string containing errors during sending e-mails (empty is successful).
#
# Global variables used:
#    $mailprog - path to sendmail program (or compatible)
#   $smtp_server - SMTP server address
#    $log_emails - enable/disable logging of all e-mails sent
#    $x_mailer - content of X-Mailer header
sub send_mail {
    my ($from,$to,$subject,$message,$bcc,$bcc_max_addresses) = @_;
    $bcc_max_addresses = int($bcc_max_addresses) || 99;
    my ($errors,$allerrors);
    
    START_MAIL:
    $errors="";
    # split @$bcc array on blocks 99 emails each
    my @bcc_slice;
    if (@$bcc) {
        @bcc_slice=@$bcc[0..($bcc_max_addresses>scalar @$bcc?scalar @$bcc-1:($bcc_max_addresses-1))];
        splice(@$bcc,0,$bcc_max_addresses);
    };
    
    # Open The Mail Program
    if  ($mailprog && -e $mailprog) {
        # Using UNIX Sendmail
        
        # Use 3-pipes module only when STDOUT is open (required to work-around problem with open3 [or sendmail?] when STDOUT is closed)
        my $ipc_ok=defined fileno(STDOUT);
        eval "use IPC::Open3" if $ipc_ok;
        my $child_pid;
        if (!$ipc_ok || $@) {
            $ipc_ok=0;
            # failed to open 3-pipes module.
            # Open sendmail as usual (widely suppurted)
            open(MAIL,"|$mailprog -t")
                || die("Error in subroutine send_mail: Can't open $mailprog. Reason: $!");
        } else {
            # Module IPC exists, use 3-pipes open function
            # Specifying STDIN, STDOUT, STDERR for sendmail program
            # Reason for it: sendmail may print errors in STDOUT of our script
            $child_pid = open3(\*MAIL,\*MAILOUTPUT, \*MAILERR, "$mailprog -t")
                || die("Error in subroutine send_mail: Can't open $mailprog. Reason: $!");
            select(MAILERR); $| = 1;    # make unbuffered
            select(MAILOUTPUT); $| = 1;    # make unbuffered
        }

        select(MAIL); $| = 1;    # make unbuffered
        select(STDOUT);
        print MAIL "To: $to\n" or $errors.="Unable to send e-mail: can't print to pipe, ipc_ok=$ipc_ok. To: $to\n";
        unless ($errors) {
            print MAIL "Bcc: ".join(",\n\t",@bcc_slice)."\n" if (@bcc_slice);
            print MAIL "X-Mailer: $x_mailer\n" if ($x_mailer);
            print MAIL "From: $from\n";
            print MAIL "Subject: $subject\n\n";
            print MAIL "$message\n"  or print "Unable to send e-mail to $to\n";
        }
        close (MAIL) or $errors.="Unable to send e-mail: can't close pipe, ipc_ok=$ipc_ok. To: $to \n";
        if ($ipc_ok) {
            # Pick up error messages from sendmail's output
            my $sendmail_response;
            while (my $line = <MAILOUTPUT>) {
                $sendmail_response .= "$line" unless ($line =~ m/^\s*$/s);
            };
            $errors.= "SENDMAIL RESPONSE:$sendmail_response" if ($sendmail_response ne "");
            close (MAILOUTPUT);
            my $sendmail_errors;
            while (my $line = <MAILERR>) {
                $sendmail_errors .= "$line" unless ($line =~ m/^\s*$/s);
            };
            $errors.= "SENDMAIL ERROR:$sendmail_errors" if ($sendmail_errors ne "");
            close (MAILERR);
            waitpid($child_pid, 0) if ($child_pid);
        }
    } elsif ($smtp_server) {    
        # Direct socket connection to SMTP server
        # prepare mail message to send
        eval ("use sendmail");
        if ($@) {
            die("Can't load 'sendmail.pm' module");
        };
        @{$sendmail::mailcfg{'smtp'}} = ($smtp_server);
        my %mail = (
                To      => $to,
                Bcc     => join(",", @bcc_slice),
                From    => $from,
                Subject => $subject,
                Message => $message,
        );
        $mail{"X-Mailer"} = $x_mailer if ($x_mailer);
        
        &sendmail(%mail) or ($errors.=$sendmail::error);
    } else {
        die("send_mail failed: SMTP server not defined, sendmail program '$mailprog' not found");
    }
    if ($log_emails) {
        if ($errors) {
            &LOG("mail_err","Failed to send email FROM:$from; TO:$to; SUBJECT:$subject; ERRORS: $errors");
        } else {
            &LOG("mail","Email FROM:$from; TO:$to; SUBJECT:$subject\nMESSAGE:\n$message");
        }
    }

    $allerrors.="$errors\n" if ($errors);
    goto START_MAIL if (@$bcc);
    $allerrors;
}
 
Copyright © 1999-2007 Atomicsoft Ltd. All Rights Reserved.