13 October, 2012 (published)
15 September, 2014 (last modified)

Complete php low-level mailer script with To, ReplyTo, CC, BCC and attachments

  Categories: PHP
  Tags:  , ,

Under certain circumstances one needs to send emails from a script. I am familiar with both Perl and php as script languages. These two script languages have a supporting community supplying all kinds of modules or packages (CPAN and PEAR). If you have those packages installed and they work you will not need this post.

However, installing those packages usually requires a c compiler and the installation is not always that easy. A second complication is that you might want to run the script from a hoster, in which case you have no control over what packages are installed. In such a situation a script that only needs the core of the script language comes in quite handy.

Sending directly from a script requires some form of authentication  or otherwise the script could be used as a spamming script.

In a previous post we showed how you can use the php mail function(). However that function has as limitation that it must be run from an SMTP server on the site where the script is run from. To overcome this limitation we will now show a low-level mail script not suffering from this limitation.

Needed
You need a SMTP server with authetication, like Gmail and Yahoo. You can log on to the SMTP-server (as your email program does as well) and give it an SMTP-formatted text. This is exactly what we do with our script

Our script implements:

  1. Adding a Reply-To address
  2. Adding one or more CC’s
  3. Adding one or more BCC’s
  4. Adding one or more attachments

How to use the script:

First: fill out the smtp input (uri, username, password)

Second: fill out/replace all the necessary addresses and comment out those features you have not used.

Third: replace names of attached files (if any). Copy those files to the script file location. Comment out  those parts of attachment part of the header you are not using.

How to run?
It can run from the command line and from a browser

</pre>
<div>
<pre><?php

//
// copyright StringCat, Amsterdam 2012
//
/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//
// WARNING SCRIPT CONTAINS PLAIN TEXT PASSWORDS
// NEVER EVER CHANGE NAME OF FILE EXTENSION
//

//
// low-level SMTP mailer script
// needed: internet connection + SMMTP server (like GMail of Yahoo)
//
// script can be run from commandline and from browser
//

//
// globals
//

$debug      = TRUE;  // set to FALSE in production code
$newLine     = "\r\n";
$timeout     = 30;
$subject     = "Subject";
$messageBody = "Message";

// find location of script
$path_info = pathinfo(__FILE__);
$dir       = $path_info['dirname'];
chdir($dir);

//
// isValidReturn ()
//
// checks expected return over socket
//
function isValidReturn ($ret,$expected) {
    $retLocal = trim($ret);
    $pos = strpos($retLocal,$expected);
    if ($pos === FALSE) return FALSE;
    if ($pos==0) return TRUE;
    return FALSE;
}

//
// quit()
//
// quit if fails, probably overkill
//
function quit($sock) {
    if ($sock) {
        $cmd="QUIT" . $newLine;
        fputs($sock, $cmd);
    }
}

//
// reply-to
//
$replyToEmailAddress = 'reply_to_address@hosdomain.com'; // replace with your own
$replyToEmailName = 'reply_to Name'; // replace with your own

//
// cc's
//
$ccEmailAddress1 = 'cc@ccdomain.com'; // replace with your own
$ccEmailName1 = 'Name of CC'; // replace with your own

//
// bcc's
//
$bccEmailAddress1 = 'bcc@bccdomain.com'; // replace with your own
$bccEmailName1 = 'Name of BCC'; //replace with your own
//
// attachment
//
$attachmentShortFileName1 = "test.pdf"; // replace with your own
$attachmentFileName1 = $dir. "/".$attachmentShortFileName1;
$attachment1 = file_get_contents($attachmentFileName1);
$b64Attachment1 = chunk_split(base64_encode($attachment1));
$mimeType1 = "application/pdf";  // replace with your own

//
// SMTP SERVER(S)
//

// change with your own smtp server or adjust addresses/usernames/passwords
//

//
// yahoo server example (replace with your own smtp server
//
$smtpServer['yahoo']        = 'ssl://plus.smtp.mail.yahoo.com';
$userName['yahoo']          = 'your_username'; // replace with your own
$passWord['yahoo']          = 'your_password'; // replace with your own
$smtpPort['yahoo']          = '465';
$from['yahoo']              = 'your_email@yahoo.com'; // replace with your own
$nameFrom['yahoo']          = 'Your Name'; // replace with your own
$to1['yahoo']               = "recipient@hisdomain.com"; // replace with your own
$nameTo1['yahoo']           = 'Name of recipient'; // replace with your own

//
// gmail server example
//
$smtpServer['gmail']        = 'ssl://smtp.gmail.com';
$userName['gmail']          = 'your_username'; // replace with your own
$passWord['gmail']          = 'your password'; // replace with your own
$smtpPort['gmail']          = '465';
$from['gmail']              = 'your_email@gmail.com'; // replace with your own
$nameFrom['gmail']          = 'Your Name'; // replace with your own
$to1['gmail']               = "recipient@hisdomain.com"; // replace with your own
$nameTo1['gmail']           = 'Name of recipient'; // replace with your own

// $key = 'yahoo'; // choice of smtp server
$key = 'gmail';

//
// start smtp
//
$sock = fsockopen($smtpServer[$key], $smtpPort[$key], $errno, $errstr, $timeout);
if (!$sock) return ;     // or loop over more smtp servers
$res = fgets($sock, 515);
if ($debug) print $res . "\n";
if (!empty($res)) {
    //
    // send "HELO"
    //
    $cmd ="HELO 127.0.0.1" . $newLine;  // you can change this into more relevant uri
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"250")) { quit($sock); }
    //
    // send "AUTH LOGIN"
    //
    $cmd = "AUTH LOGIN" . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"334 VXNlcm5hbWU6")) { quit($sock);  }
    //
    // SEND USERNAME base64 encoded
    //
    $cmd = base64_encode($userName[$key]) . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"334 UGFzc3dvcmQ6")) { quit($sock); }
    // SEND PASSWORD base64 encoded
    $cmd = base64_encode($passWord[$key]) . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"235")) { quit($sock);}
    //
    // send SMTP command "MAIL FROM"
    //
    $cmd = "MAIL FROM: <" . $from[$key] . ">" . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"250")) { quit($sock);}
    //
    // tell the SMTP server who are the recipients
    //
    $cmd = "RCPT TO: " . " <" . $to1[$key] . ">" . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"250")) { quit($sock); }
    //
    // if more recipienta add a line for each recipient
    //
    //
    // send SMTP command "DATA"
    //
    $cmd = "DATA" . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"354")) { quit($sock); }
    //
    // send SMTP command containing whole whole message
    //
    // comment out if not relevant
    $headers  = "TO: "       . $nameTo1[$key]    . " <" . $to1[$key]           . ">"  . $newLine;
    $headers .= "From: "     . $nameFrom[$key]   . " <" . $from[$key]          . ">"  . $newLine ;
    $headers .= "Reply-To: " . $replyToEmailName . " <" . $replyToEmailAddress . ">"  . $newLine ;
    $headers .= "cc: "       . $ccEmailName1     . " <" . $ccEmailAddress1     . ">"  . $newLine ;
    $headers .= "bcc: "      . $bccEmailName1    . " <" . $bccEmailAddress1    . ">"  . $newLine ;
    //
    // Generate a mime boundary string
    //
    $rnd_str = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$rnd_str}x";
    //
    // Add headers for file attachment
    //
    $headers .= "MIME-Version: 1.0" . $newLine .
            "Content-Type: multipart/mixed;" . $newLine .
            " boundary=\"{$mime_boundary}\" ";
    //
    // Add a multipart boundary above the plain message
    //
    $headers .= "This is a multi-part message in MIME format"  . $newLine . $newLine .
        "--{$mime_boundary}". $newLine ;
    //
    // add the plaintext message body
    //
    $headers .= "Content-Type: text/plain; charset=\"iso-8859-1\"". $newLine .
        "Content-Transfer-Encoding: 7bit" . $newLine. $newLine .
        $messageBody . $newLine. $newLine;
    //
    // Add file attachment to the message
    //
    $headers .= "--{$mime_boundary}". $newLine .
        "Content-Type: {$mimeType1};". $newLine  .
        " name=\"{$attachmentShortFileName1}\" ". $newLine .
        "Content-Disposition: attachment;" . $newLine .
        " filename=\"{$attachmentShortFileName1}\"  " . $newLine .
        "Content-Transfer-Encoding: base64". $newLine . $newLine  .
        $b64Attachment1 . $newLine. $newLine .
    //
    // comment out one of the two following lines
    // dependent on number of attached files
    // last mime boundary must end in "--"
    //
    //        "--{$mime_boundary}". $newLine;
    "--{$mime_boundary}--". $newLine;

    // we are done
    $headers .= $newLine. "." .$newLine;
    $cmd      = $headers;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
    if (!isValidReturn($res,"250")) { quit($sock);}
    // tell SMTP we are done
    $cmd = "QUIT" . $newLine;
    fputs($sock, $cmd);
    $res = fgets($sock, 515);
    if ($debug) print "+ $cmd- $res\n";
 }
?></pre>
</div>
<pre>

The file can also directly downloaded here.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         

10 reactions op “Complete php low-level mailer script with To, ReplyTo, CC, BCC and attachments”

  1. Herve says:

    Hi,

    I tried your script but always have this error line :
    Warning: fsockopen() [function.fsockopen]: unable to connect to ssl://smtp.gmail.com:465 (Connection refused) in /homepages/40/d427345472/htdocs/test_email.php on line 147

    Do you have any idea of the reason

    Waiting for your feedback

    Best regards

  2. Herve says:

    Hi again…

    I have a other question…
    What should be here if we have a webhosting like 1and1 :
    $cmd =”HELO 127.0.0.1″ . $newLine; // you can change this into more relevant uri

    Thanks in advance

  3. adlag says:

    Are you running this from a web server on a Windows OS or from a Linux (Apache) server?
    In the first case php needs to have the openssl.dll activated. That is: uncomment the line
    ;extension=php_openssl.dll
    in the php ini file.

  4. adlag says:

    This command is usually not very critical. The idea is that you tell the web server who (that is your url) you are. Usually the web server is not very critical in what url it accepts. It is just a kind of greeting.

  5. I. Fimbres says:

    This script has been very useful, thank you. I do have one question: How is the “subject” included in the email? I see the $subject variable towards the top of the script but don’t see its inclusion in the actual email…

  6. I. Fimbres says:

    My apologies, I just answered my own question and added the subject header to the script. Thanks again…

  7. [...] For sending simple emails from a script I always use a low-level SMTP script. In such a way I am not at all dependent on what the hoster has installed. Here is an example. [...]

  8. [...] here for a general low-level smtp mail script that can run from command line and from a [...]

  9. Zaf says:

    works great! :D

Write a reaction

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution.