PHP-SMTP發送郵件

/**
 * 郵件發送類
 */
class Mail
{
    // SMTP服務器名稱
    private $SmtpHost;
    /* SMTP服務端口
     + 標準服務端口,默認爲25
     */
    private $SmtpPort = 25;
    // SMTP用戶名
    private $SmtpUser = '';
    // SMTP用戶密碼
    private $SmtpPassword = '';
    /* 超時時間
     + 用於fsockopen()函數,超過該時間未連上則中斷
     */
    private $TimeOut = 30;
    /* 用戶身份
     + 用於HELO指令
     */
    private $HostName = 'localhost';
    /* 開啓調試模式 */
    private $Debug = false;
    /* 是否進行身份驗證 */
    private $Authentication = false;
    /* Private Variables */
    private $Socket = false;

    /**
     * 構造方法
     */
    public function __construct($smtpHost = '', $smtpUser = '', $smtpPassword = '', $authentication = false, $smtpPort = 25)
    {
        $this->SmtpHost = $smtpHost;
        $this->SmtpPort = $smtpPort;
        $this->SmtpUser = $smtpUser;
        $this->SmtpPassword = $smtpPassword;
        $this->Authentication = $authentication;
    }

    /** 發送郵件
     * @param string $maiTo 收件人
     * @param string $mailFrom 發件人(支持名稱:Email)
     * @param string $subject 主題
     * @param string $body 內容
     * @param string $mailType 郵件類型
     * @param string $cc 抄送郵件地址
     * @param string $bcc 隱藏抄送郵件地址
     * @param string $additionalHeaders 附加內容
     * @return boolean
     */
    public function SendMail($maiTo, $mailFrom, $subject = '', $body = '', $mailType = 'HTML', $cc = '', $bcc = '', $additionalHeaders = '')
    {

        $header = '';
        $header .= "MIME-Version:1.0\r\n";
        if ($mailType == 'HTML') {
            $header .= "Content-Type:text/html;";
        }
        $header .= "charset='utf-8'\r\n";
        $header .= "Content-Language='zh-cn'\r\n";
        $header .= "To: " . $maiTo . "\r\n";
        if ($cc != '') {
            $header .= "Cc: " . $cc . "\r\n";
        }
        $header .= "From:" . $mailFrom . "<" . $mailFrom . ">\r\n";
        $header .= "Subject:=?UTF-8?B?" . base64_encode($subject). "?=\r\n";
        $header .= $additionalHeaders;
        $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) . "." . $mailFrom . ">\r\n";

        //收件人地址解析
        $maiTo = explode(",", $maiTo);
        if ($cc != "") {
            $maiTo = array_merge($maiTo, explode(",", $cc));
        }
        if ($bcc != "") {
            $maiTo = array_merge($maiTo, explode(",", $bcc));
        }

        //郵件是否發送成功標誌
        $mailSent = true;
        foreach ($maiTo as $value) {
            if (!$this->SmtpSockopen($value)) {
                $this->SmtpDebug("[錯誤]: 無法發送郵件至 \"" . $value . "\"\n");
                $mailSent = false;
                continue;
            }
            if ($this->SmtpSend($this->HostName, $mailFrom, $value, $header, $body)) {
                $this->SmtpDebug("[成功]: E-mail已經成功發送至 <" . $value . ">\n");
            } else {
                $this->SmtpDebug("[失敗]: E-mail無法發送至 <" . $value . ">\n");
                $mailSent = false;
            }
            fclose($this->Socket);
            //$this->SmtpDebug("[失敗]:  連接服務器失敗\n");
        }
        $this->SmtpDebug($header);
        return $mailSent;
    }

    /**
     * 發送郵件
     * @param $helo
     * @param $maiFrom
     * @param $maiTo
     * @param $header
     * @param string $body
     * @return bool
     */
    function SmtpSend($helo, $maiFrom, $maiTo, $header, $body = "")
    {
        //發送連接命令
        if (!$this->SmtpPutcmd("HELO", $helo)) {
            return $this->SmtpError("發送 HELO 命令");
        }

        //身份驗證
        if ($this->Authentication) {
            if (!$this->SmtpPutcmd("AUTH LOGIN", base64_encode($this->SmtpUser))) {
                return $this->SmtpError("發送 HELO 命令");
            }

            if (!$this->SmtpPutcmd("", base64_encode($this->SmtpPassword))) {
                return $this->SmtpError("發送 HELO 命令");
            }
        }

        //發件人信息
        if (!$this->SmtpPutcmd("MAIL", "FROM:<" . $maiFrom . ">")) {
            return $this->SmtpError("發送 MAIL FROM 命令");
        }

        //收件人信息
        if (!$this->SmtpPutcmd("RCPT", "TO:<" . $maiTo . ">")) {
            return $this->SmtpError("發送 RCPT TO 命令");
        }

        //發送數據
        if (!$this->SmtpPutcmd("DATA")) {
            return $this->SmtpError("發送 DATA 命令");
        }

        //發送消息
        if (!$this->SmtpMessage($header, $body)) {
            return $this->SmtpError("發送 信息");
        }

        //發送EOM
        if (!$this->SmtpEom()) {
            return $this->SmtpError("發送 <CR><LF>.<CR><LF> [EOM]");
        }

        //發送退出命令
        if (!$this->SmtpPutcmd("QUIT")) {
            return $this->SmtpError("發送 QUIT 命令");
        }

        return true;
    }

    /** 發送SMTP命令
     * @param $cmd
     * @param $arg
     * @return bool
     */
    function SmtpPutcmd($cmd, $arg = "")
    {
        if ($arg != '') {
            if ($cmd == '') {
                $cmd = $arg;
            } else {
                $cmd = $cmd . ' ' . $arg;
            }
        }
        fputs($this->Socket, $cmd . "\r\n");
        $this->SmtpDebug("> " . $cmd . "\n");
        return $this->SmtpOk();
    }

    /** SMTP錯誤信息
     * @param string $string 錯誤信息
     * @return bool
     */
    function SmtpError($string)
    {
        $this->SmtpDebug("[錯誤]: 在 " . $string . " 時發生了錯誤\n");
        return false;
    }

    /** SMTP信息
     * @param string $header 頭部消息
     * @param string $body 內容
     * @return bool
     */
    function SmtpMessage($header, $body)
    {
        fputs($this->Socket, $header . "\r\n" . $body);
        $this->SmtpDebug("> " . str_replace("\r\n", "\n" . "> ", $header . "\n> " . $body . "\n> "));
        return true;
    }

    /* EOM */
    function SmtpEom()
    {
        fputs($this->Socket, "\r\n.\r\n");
        $this->SmtpDebug(". [EOM]\n");
        return $this->SmtpOk();
    }

    /* SMTP OK */
    function SmtpOk()
    {
        $response = str_replace("\r\n", "", fgets($this->Socket, 512));
        $this->SmtpDebug($response . "\n");

        if (preg_match("/^[23]/", $response) == 0) {
            fputs($this->Socket, "QUIT\r\n");
            fgets($this->Socket, 512);
            $this->SmtpDebug("[錯誤]: 服務器返回 \"" . $response . "\"\n");
            return false;
        }
        return true;
    }

    /* debug
     * @param string $message 錯誤消息
     */
    private function SmtpDebug($message)
    {
        if ($this->Debug) {
            echo $message . "<br />";
        }
    }

    /** 網絡Socket鏈接準備
     * @param string $address 郵件地址
     * @return boolean
     */
    private function SmtpSockopen($address)
    {
        if ($this->SmtpHost == '') {
            return $this->SmtpSockopenMx($address);
        } else {
            return $this->SmtpSockopenRelay($this->SmtpHost);
        }
    }

    /** 獲取MX記錄
     * @param string $address 郵件地址
     * @return boolean
     */
    private function SmtpSockopenMx($address)
    {
        $domain = ereg_replace("^.+@([^@]+)$", "\\1", $address);
        if (!$this->MyCheckdnsrr($domain, 'mx')) {
            $this->SmtpDebug("[錯誤]: 無法找到 MX記錄 \"" . $domain . "\"\n");
            return false;
        }
        $this->SmtpSockopenRelay($domain);
        $this->SmtpDebug('[錯誤]: 無法連接 MX主機 (' . $domain . ")\n");
        return false;
    }

    /** 打開網絡Socket鏈接
     * @param string $smtpHost 服務器名稱
     * @return boolean
     */
    private function SmtpSockopenRelay($smtpHost)
    {
        $this->SmtpDebug('[操作]: 嘗試連接 "' . $smtpHost . ':' . $this->SmtpPort . "\"\n");
        $this->Socket = @stream_socket_client('tcp://' . $smtpHost . ':' . $this->SmtpPort, $errno, $errstr, $this->TimeOut);
        if (!($this->Socket && $this->SmtpOk())) {
            $this->SmtpDebug('[錯誤]: 無法連接服務器 "' . $smtpHost . "\n");
            $this->SmtpDebug('[錯誤]: ' . $errstr . " (" . $errno . ")\n");
            return false;
        }
        $this->SmtpDebug('[成功]: 成功連接 ' . $smtpHost . ':' . $this->SmtpPort . "\"\n");
        return true;;
    }

    /** 自定義郵箱有效性驗證
     * + 解決window下checkdnsrr函數無效情況
     * @param string $hostName 主機名
     * @param string $recType 類型(可以是MX、NS、SOA、PTR、CNAME 或 ANY)
     * @return boolean
     */
    function MyCheckdnsrr($hostName, $recType = 'MX')
    {
        if ($hostName != '') {
            $recType = $recType == '' ? 'MX' : $recType;
            exec("nslookup -type=$recType $hostName", $result);
            foreach ($result as $line) {
                if (preg_match("/^$hostName/", $line) > 0) {
                    return true;
                }
            }
            return false;
        }
        return false;
    }
}

//郵件配置
$title = 'xxx';
$sm = new Mail('xxx.xxx.xxx', 'xxx', 'xxx',true);
$sendTo = "[email protected]";
$end = $sm->SendMail($sendTo,'[email protected]',$title,$content);
if ($end) echo $end;
else echo "發送成功!";


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章