All Products
Search
Document Center

Direct Mail:PHP call examples for SMTP

Last Updated:May 27, 2026

Send emails through the Direct Mail SMTP endpoint using PHP, with either the PHPMailer library or a custom SMTP class.

Prerequisites

Before you begin, make sure you have:

  • PHP 7.4 or later installed

  • Composer installed (for Method 1)

  • A sender address configured in the Direct Mail console, with its SMTP password set

  • Your SMTP credentials (sender address and SMTP password) stored as environment variables — never hardcode credentials in source code

To store credentials as environment variables:

export DM_SMTP_USER="your-sender@example.com"
export DM_SMTP_PASS="your-smtp-password"

Send emails using PHP through the SMTP protocol

Choose a method based on your project setup. Method 1 uses PHPMailer, the most widely adopted PHP email library. Method 2 uses a lightweight custom class that requires no package manager.

Method 1: PHPMailer

Install PHPMailer with Composer:

composer require phpmailer/phpmailer
Note: To install manually without Composer, download PHPMailer.php, Exception.php, and SMTP.php from PHPMailer v6.6.5 on GitHub. Then open PHPMailer.php and change the default charset from self::CHARSET_ISO88591 to self::CHARSET_UTF8.
<?php
require 'vendor/autoload.php'; // Use this line if installed via Composer

// Uncomment the three lines below if you installed PHPMailer manually:
// require 'PHPMailer.php';
// require 'Exception.php';
// require 'SMTP.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

$mail = new PHPMailer(true);

try {
    // SMTP server settings
    $mail->CharSet    = 'UTF-8';
    $mail->isSMTP();
    $mail->SMTPDebug  = SMTP::DEBUG_SERVER;           // Remove or set to DEBUG_OFF in production

    // SSL on port 465 (recommended)
    $mail->Host       = 'ssl://smtpdm.aliyun.com';   // Direct Mail SMTP endpoint
    $mail->Port       = 465;

    // Alternative: STARTTLS on port 80
    // $mail->Host       = 'smtpdm.aliyun.com';
    // $mail->Port       = 80;
    // $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

    $mail->SMTPAuth   = true;
    $mail->Username   = getenv('DM_SMTP_USER');       // Sender address (from environment variable)
    $mail->Password   = getenv('DM_SMTP_PASS');       // SMTP password (from environment variable)

    // Sender and recipients
    $mail->setFrom(getenv('DM_SMTP_USER'), 'Mailer'); // Display sender address; supports send-on-behalf
    $mail->addAddress('recipient@example.com', 'Recipient Name');
    // $mail->addAddress('recipient2@example.com', 'Second Recipient'); // Add multiple recipients as needed
    $mail->addReplyTo('replyto@example.com', 'Reply Contact');
    $mail->addCC('cc@example.com');
    $mail->addBCC('bcc@example.com');

    // Optional: custom message header for unsubscribe policy and IP pool
    // $createJson = [
    //     "Version" => "1.0",
    //     "Unsubscribe" => [
    //         "LinkType"    => "default",
    //         "FilterLevel" => "mailfrom_domain"
    //     ],
    //     "OutboundIp" => [
    //         "IpPoolId" => "<your-ip-pool-id>"    // Replace with your IP pool ID
    //     ]
    // ];
    // $jsonString  = json_encode($createJson, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    // $base64Trace = base64_encode($jsonString);
    // $mail->addCustomHeader('X-AliDM-Settings', $base64Trace);

    // Attachment (optional)
    $mail->addAttachment('/path/to/file.jpg', 'attachment.jpg');

    // Email content
    $mail->isHTML(true);
    $mail->Subject = 'Subject test';
    $mail->Body    = 'Test content';
    // $mail->AltBody = 'Plain-text fallback for non-HTML clients';

    $mail->Sender = getenv('DM_SMTP_USER');

    $mail->send();
    echo 'Message sent successfully.';
} catch (Exception $e) {
    echo "Message could not be sent. Mailer error: {$mail->ErrorInfo}";
}
?>

The following table describes the key settings in the example:

Setting

Description

Host and Port

Use ssl://smtpdm.aliyun.com with port 465 for SSL (encrypted from the start). Use smtpdm.aliyun.com with port 80 and ENCRYPTION_STARTTLS to start unencrypted and upgrade. Port 465 with SSL is recommended.

SMTPAuth

Set to true to enable authentication with your sender address and SMTP password.

setFrom

Sets the display sender address. This address can differ from Username if you are sending on behalf of another address.

Sender

Sets the envelope sender (the MAIL FROM address used during the SMTP handshake).

SMTPDebug

Set to SMTP::DEBUG_OFF or remove this line before deploying to production.

Method 2: Custom SMTP class (email.class.php)

Use this method when you cannot use Composer or prefer a self-contained solution.

<?php
require 'email.class.php';

$mailto      = 'recipient@example.com';      // Recipient address
$mailsubject = "Test email";
$mailbody    = 'This is the email content';

// SMTP connection settings
$smtpserver     = "smtpdm.aliyun.com";
$smtpserverport = 80;
// For SSL, use the two lines below instead:
// $smtpserver     = "ssl://smtpdm.aliyun.com";
// $smtpserverport = 465;

$smtpusermail = getenv('DM_SMTP_USER');   // Sender address (from environment variable)
$smtpuser     = getenv('DM_SMTP_USER');   // Full sender address, e.g. test@example.net
$smtppass     = getenv('DM_SMTP_PASS');   // SMTP password (from environment variable)

$mailsubject = "=?UTF-8?B?" . base64_encode($mailsubject) . "?=";
$mailtype    = "HTML";

$smtpreplyto = "replyto@example.com";     // Optional reply-to address

$smtp = new smtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
$smtp->debug = false;

$cc                 = "";
$bcc                = "";
$additional_headers = "";
$sender             = "Display Name";      // Sender display name

$smtp->sendmail($mailto, $smtpusermail, $mailsubject, $mailbody, $mailtype,
                $cc, $bcc, $additional_headers, $sender, $smtpreplyto);
?>

Before using email.class.php, make sure the file includes the Reply-To header in the sendmail method. Add the following line if it is missing:

$header .= "Reply-To: " . $replyToAddress . "\r\n"; // $replyToAddress is the $smtpreplyto parameter
  • email.class.php is not bundled with Direct Mail. Download it from a trusted source or use the reference implementation below.

  • $mailto accepts a single recipient address. To send to multiple recipients, pass a comma-separated string.

  • $smtpuser must be the complete sender address, exactly as configured in the Direct Mail console.

email.class.php reference implementation

<?php

/**
 * email smtp (support php7)
 *
 */

class Smtp
{
    /* Public Variables */
    public $smtp_port;

    public $time_out;

    public $host_name;

    public $log_file;

    public $relay_host;

    public $debug;

    public $auth;

    public $user;

    public $pass;

    /* Private Variables */
    private $sock;

    /* Constractor */
    function __construct($relay_host = "", $smtp_port = 80,$auth = false,$user,$pass)
    {
        $this->debug = FALSE;

        $this->smtp_port = $smtp_port;

        $this->relay_host = $relay_host;

        $this->time_out = 30; //is used in fsockopen()

        $this->auth = $auth;//auth

        $this->user = $user;

        $this->pass = $pass;

        $this->host_name = "localhost"; //is used in HELO command
        $this->log_file = "";

        $this->sock = FALSE;

    }

    /* Main Function */

    function sendmail($to, $from, $subject, $body, $mailtype, $cc, $bcc, $additional_headers, $fromUser, $replyToAddress)
    {

        $mail_from = $this->get_address($this->strip_comment($from));

        $body = preg_replace("/(^|(\r\n))(\.)/", "\1.\3", $body);

        $header = "MIME-Version:1.0\r\n";

        if($mailtype=="HTML"){

            $header .= "Content-Type:text/html; charset=utf-8\r\n";

        }

        $header .= "To: ".$to."\r\n";

        if ($cc != "") {

            $header .= "Cc: ".$cc."\r\n";

        }

        $header .= "From: $fromUser<".$from.">\r\n";

        $header .= "Subject: ".$subject."\r\n";

        $header .= "Reply-To: ".$replyToAddress."\r\n";

        $header .= $additional_headers;

        $header .= "Date: ".date("r")."\r\n";

        $header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n";

        list($msec, $sec) = explode(" ", microtime());

        $header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n";

        // To enable the email tracking feature, use the following code to set the tracking link in the message header. For more information about the prerequisites and constraints, see Enable the data tracking feature.
        //$header .= "Content-Transfer-Encoding: quoted-printable\r\n";
        //$header .= "X-AliDM-Trace: ". base64_encode(json_encode(['TagName'=>'user_created_tag','OpenTrace'=>"1"]))."\r\n";
        $TO = explode(",", $this->strip_comment($to));

        if ($cc != "") {

            $TO = array_merge($TO, explode(",", $this->strip_comment($cc)));

        }

        if ($bcc != "") {

            $TO = array_merge($TO, explode(",", $this->strip_comment($bcc)));

        }

        $sent = TRUE;

        foreach ($TO as $rcpt_to) {

            $rcpt_to = $this->get_address($rcpt_to);

            if (!$this->smtp_sockopen($rcpt_to)) {

                $this->log_write("Error: Cannot send email to ".$rcpt_to."\n");

                $sent = FALSE;

                continue;

            }

            if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) {

                $this->log_write("E-mail has been sent to <".$rcpt_to.">\n");

            } else {

                $this->log_write("Error: Cannot send email to <".$rcpt_to.">\n");

                $sent = FALSE;

            }

            fclose($this->sock);

            $this->log_write("Disconnected from remote host\n");

        }

        return $sent;

    }

    /* Private Functions */

    function smtp_send($helo, $from, $to, $header, $body = "")
    {

        if (!$this->smtp_putcmd("HELO", $helo)) {

            return $this->smtp_error("sending HELO command");

        }

        //auth
        if($this->auth){

            if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) {

                return $this->smtp_error("sending HELO command");

            }

            if (!$this->smtp_putcmd("", base64_encode($this->pass))) {

                return $this->smtp_error("sending HELO command");

            }

        }

        if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">")) {

            return $this->smtp_error("sending MAIL FROM command");

        }

        if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">")) {

            return $this->smtp_error("sending RCPT TO command");

        }

        if (!$this->smtp_putcmd("DATA")) {

            return $this->smtp_error("sending DATA command");

        }

        if (!$this->smtp_message($header, $body)) {

            return $this->smtp_error("sending message");

        }

        if (!$this->smtp_eom()) {

            return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]");

        }

        if (!$this->smtp_putcmd("QUIT")) {

            return $this->smtp_error("sending QUIT command");

        }

        return TRUE;

    }

    function smtp_sockopen($address)
    {

        if ($this->relay_host == "") {

            return $this->smtp_sockopen_mx($address);

        } else {

            return $this->smtp_sockopen_relay();

        }

    }

    function smtp_sockopen_relay()
    {

        $this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n");

        $this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out);

        if (!($this->sock && $this->smtp_ok())) {

            $this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n");

            $this->log_write("Error: ".$errstr." (".$errno.")\n");

            return FALSE;

        }

        $this->log_write("Connected to relay host ".$this->relay_host."\n");

        return TRUE;

    }

    function smtp_sockopen_mx($address)
    {

        $domain = preg_replace("/^.+@([^@]+)$/", "\1", $address);

        if (!@getmxrr($domain, $MXHOSTS)) {

            $this->log_write("Error: Cannot resolve MX \"".$domain."\"\n");

            return FALSE;

        }

        foreach ($MXHOSTS as $host) {

            $this->log_write("Trying to ".$host.":".$this->smtp_port."\n");

            $this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out);

            if (!($this->sock && $this->smtp_ok())) {

                $this->log_write("Warning: Cannot connect to mx host ".$host."\n");

                $this->log_write("Error: ".$errstr." (".$errno.")\n");

                continue;

            }

            $this->log_write("Connected to mx host ".$host."\n");

            return TRUE;

        }

        $this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n");

        return FALSE;

    }

    function smtp_message($header, $body)
    {

        fputs($this->sock, $header."\r\n".$body);

        $this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> "));

        return TRUE;

    }

    function smtp_eom()
    {

        fputs($this->sock, "\r\n.\r\n");

        $this->smtp_debug(". [EOM]\n");

        return $this->smtp_ok();

    }

    function smtp_ok()
    {

        $response = str_replace("\r\n", "", fgets($this->sock, 512));

        $this->smtp_debug($response."\n");

        if (!preg_match("/^[23]/", $response)) {

            fputs($this->sock, "QUIT\r\n");

            fgets($this->sock, 512);

            $this->log_write("Error: Remote host returned \"".$response."\"\n");

            return FALSE;

        }

        return TRUE;

    }

    function smtp_putcmd($cmd, $arg = "")
    {

        if ($arg != "") {

            if($cmd=="") $cmd = $arg;

            else $cmd = $cmd." ".$arg;

        }

        fputs($this->sock, $cmd."\r\n");

        $this->smtp_debug("> ".$cmd."\n");

        return $this->smtp_ok();

    }

    function smtp_error($string)
    {

        $this->log_write("Error: Error occurred while ".$string.".\n");

        return FALSE;

    }

    function log_write($message)
    {

        $this->smtp_debug($message);

        if ($this->log_file == "") {

            return TRUE;

        }

        $message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message;

        if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a"))) {

            $this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n");

            return FALSE;

        }

        flock($fp, LOCK_EX);

        fputs($fp, $message);

        fclose($fp);

        return TRUE;

    }

    function strip_comment($address)
    {

        $comment = "/\([^()]*\)/";

        while (preg_match($comment, $address)) {

            $address = preg_replace($comment, "", $address);

        }

        return $address;

    }

    function get_address($address)
    {

        $address = preg_replace("/([ \t\r\n])+/", "", $address);

        $address = preg_replace("/^.*<(.+)>.*$/", "\1", $address);

        return $address;

    }

    function smtp_debug($message)
    {

        if ($this->debug) {

            echo $message;

        }

    }

}
?>