PHP SendMail in under 100 LOC

First : build up the body

function smtp_sendmail(
	$mailfrom,
	$mailto,
	$replyto,
	$subject,
	$message,
	$username,
	$password,
	$filename,
	$attachment)
{
	$divider = md5(time());
	$msg=
"From: $mailfrom\r
To: $mailto\r
Reply-To: $replyto\r
Subject: $subject\r
MIME-Version: 1.0\r
Content-Type: multipart/mixed; boundary=\"$divider\"\r
Content-Transfer-Encoding: 7bit\r
\r --$divider\r
Content-Type: text/plain; charset=\"iso-8859-1\"\r
Content-Transfer-Encoding: 8bit\r
\r
$message\r
\r --$divider\r
Content-Type: application/octet-stream; name=\"$filename\"\r
Content-Transfer-Encoding: base64\r
Content-Disposition: attachment\r
\r
".chunk_split(base64_encode($attachment))."\r
\r --$divider--";

	if(($ret=smtp_mail("mail.habibur.com",$username,$password,$mailfrom,$mailto,$msg))) return $ret;
	return;
}

Next : send the mail using SMTP

The whole SMTP protocol with authentication is written bellow.
function smtp_mail($host,$username,$password,$mailfrom,$mailto,$data){
    if(!($conn = @fsockopen($host, 587))) return "Could not open SMTP Port 587";
    if(($ret=smtp_msg($conn,'',220))) return $ret;
    if(($ret=smtp_msg($conn,"EHLO $host",250))) return $ret;
    if(($ret=smtp_msg($conn,"STARTTLS",220))) return $ret;
    if(!($ret=stream_socket_enable_crypto($conn, true, STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT))) return "Crypto enable failed";
    if(($ret=smtp_msg($conn,"EHLO $host",250))) return $ret;
    if(($ret=smtp_msg($conn,"AUTH PLAIN",334))) return $ret;
    if(($ret=smtp_msg($conn,base64_encode("\0$username\0$password"),235))) return $ret;
    if(($ret=smtp_msg($conn,"MAIL FROM:".mail_address($mailfrom),250))) return $ret;
    if(is_string($mailto)) $mailto=[$mailto];
    foreach($mailto as $v)
        if(($ret=smtp_msg($conn,"RCPT TO:".mail_address($v),250))) return $ret;

    if(($ret=smtp_msg($conn,"DATA",354))) return $ret;
    if(($ret=smtp_msg($conn,$data."\r\n.",250))) return $ret;
    if(($ret=smtp_msg($conn,"QUIT",221))) return $ret;
    fclose($conn);
}
function smtp_log($msg){
    return;
    print $msg."\n";
    flush();
}
function smtp_msg($conn,$msg,$code){
    if(strlen($msg)){
        smtp_log("send>$msg");
        $msg.="\r\n";
        fputs($conn,$msg,strlen($msg));
    }
    while($ret=fgets($conn,515)){
        smtp_log("recv<$ret");
        if(substr($ret,3,1)==" "){
            $res=substr($ret,0,3);
            if($res!=$code)
                return "server error $res [expected $code]: $msg => $ret";
            else{
                smtp_log("--- good");
                return;
            }
            
        }
    }
}

Test script

function smtp_test(){
    $ret=smtp_sendmail(
        "Mr Habib <habib@habibur.com>",
        "Habib Client <habib@habibur.com>",
        "Reply <habibur@gmail.com>",
        "php mail test with attachment",
        "Please find a fake attachment here.",
        "USERNAME",
        "PASSWORD",
        "habib-bank.pdf",
        file_get_contents("out.pdf")
    );
    if($ret)
        print "ERROR: $ret\n";
    else
        print "Done\n";
    return;
}
Published
8-Oct-2022
Updated
24-Oct-2022