TOP
首頁 > PHP 擴充功能收集與分享 > PHP MAIL SMTP 郵件發送

PHP MAIL SMTP 郵件發送

2022-12-12 260

相關文章

電子郵件是架設網站不可或缺的工具之一,多數人會用 PHPmailer 這個方便的類,但是網路上找到的教學,都是使用 composer 安裝的,因為我功力太弱了,搞了幾次都沒成功很快就放棄了,因為只是要簡單的發信功能,沒有要傳送附件功能, ECSHOP 中的發信程式支援 PHPmail 及 SMTP,也能用 HTML 格式的內文,對多數程式小白來說已經足夠,底下是所有的檔案內容...

mail.php

 
<?php
	/**
	 * 郵件發送
	 *
	 * @param: $name[string]        接收人姓名
	 * @param: $email[string]       接收人郵件地址
	 * @param: $subject[string]     郵件標題
	 * @param: $content[string]     郵件內容
	 * @param: $type[int]           0 普通郵件, 1 HTML郵件
	 * @param: $notification[bool]  true 要求回執, false 不用回執
	 *
	 * @return boolean
	 */
	function send_mail($name, $email, $subject, $content, $type = 1, $notification=false)
	{
		include_once "mail_config.php";
	    // 使用mail函式發送郵件
	    if ($mail_service == 0 && function_exists('mail'))
	    {
	        // 郵件的頭部資訊
	        $content_type = ($type == 0) ? 'Content-Type: text/plain; charset=' . $charset : 'Content-Type: text/html; charset=' . $charset;
	        $headers = array();
	        $headers[] = 'From: "' . '=?' . $charset . '?B?' . base64_encode($shop_name) . '?='.'" <' . $smtp_mail . '>';
	        $headers[] = $content_type . '; format=flowed';
	        if ($notification)
	        {
	            $headers[] = 'Disposition-Notification-To: ' . '=?' . $charset . '?B?' . base64_encode($shop_name) . '?='.'" <' . $smtp_mail . '>';
	        }
	
	        $res = @mail($email, '=?' . $charset . '?B?' . base64_encode($subject) . '?=', $content, implode("\r\n", $headers));
	
	        if (!$res)
	        {
	            $msg['message'] = '郵件發送失敗,請檢查您的郵件伺服器設置!';
	            $msg['status'] = false;
	
	            return $msg;
	        }
	        else
	        {
				$msg['message'] = $email;
				$msg['status'] = true;
				
				return $msg;
	        }
	    }
	    // 使用smtp服務發送郵件
	    else
	    {
	        // 郵件的頭部資訊
	        $content_type = ($type == 0) ?
	            'Content-Type: text/plain; charset=' . $charset : 'Content-Type: text/html; charset=' . $charset;
	        $content   =  base64_encode($content);
	
	        $headers = array();
	        $headers[] = 'Date: ' . gmdate('D, j M Y H:i:s', time()+3600*8);
	        $headers[] = 'To: "' . '=?' . $charset . '?B?' . base64_encode($name) . '?=' . '" <' . $email. '>';
	        $headers[] = 'From: "' . '=?' . $charset . '?B?' . base64_encode($shop_name) . '?='.'" <' . $smtp_mail . '>';
	        $headers[] = 'Subject: ' . '=?' . $charset . '?B?' . base64_encode($subject) . '?=';
	        $headers[] = $content_type . '; format=flowed';
	        $headers[] = 'Content-Transfer-Encoding: base64';
	        $headers[] = 'Content-Disposition: inline';
	        if ($notification)
	        {
	            $headers[] = 'Disposition-Notification-To: ' . '=?' . $charset . '?B?' . base64_encode($shop_name) . '?='.'" <' . $smtp_mail . '>';
	        }
	
	        // 獲得郵件伺服器的參數設定
	        $params['host'] = $smtp_host;
	        $params['port'] = $smtp_port;
	        $params['user'] = $smtp_user;
	        $params['pass'] = $smtp_pass;
	
	        if (empty($params['host']) || empty($params['port']))
	        {
	            // 如果沒有設定主機和埠直接返回 false
	            $msg['message'] = '郵件伺服器設置資訊不完整';
				$msg['status'] = false;
				
				return $msg;
	        }
	        else
	        {
	            // 發送郵件
	            if (!function_exists('fsockopen'))
	            {
	                //如果fsockopen被禁用,直接返回
	                $msg['message'] = '伺服器已禁用 fsocketopen 函數。';
	                $msg['status'] = false;
	                
	                return $msg;
	            }
	
	            include_once('smtp.php');
	            static $smtp;
	
	            $send_params['recipients'] = $email;
	            $send_params['headers']    = $headers;
	            $send_params['from']       = $smtp_mail;
	            $send_params['body']       = $content;
	
	            if (!isset($smtp))
	            {
	                $smtp = new smtp($params);
	            }
	
	            if ($smtp->connect() && $smtp->send($send_params))
	            {
	                $msg['message'] = $email;
	                $msg['status'] = true;
	                
	                return $msg;
	            }
	            else
	            {
	                $err_msg = $smtp->error_msg();
	                if (empty($err_msg))
	                {
	                    $err = '未知錯誤';
	                }
	                else
	                {
	                    if (strpos($err_msg, 'Failed to connect to server') !== false)
	                    {
	                        $err = '無法連接到郵件伺服器'. $params['host'] . ':' . $params['port'];
	                    }
	                    else if (strpos($err_msg, 'AUTH command failed') !== false)
	                    {
	                        $err = '郵件伺服器驗證帳號或密碼不正確';
	                    }
	                    elseif (strpos($err_msg, 'bad sequence of commands') !== false)
	                    {
	                        $err = '伺服器拒絕發送該郵件';
	                    }
	                    else
	                    {
	                        $err = $err_msg;
	                    }
	                }
	
	                $msg['message'] = $err;
	                $msg['status'] = false;
	                
	                return $msg;
	            }
	        }
	    }
	}
	 

smtp.php

 
<?php
	
	/**
	 * SMTP 郵件類
	*/
	
	define('SMTP_STATUS_NOT_CONNECTED', 1, true);
	define('SMTP_STATUS_CONNECTED',     2, true);
	
	class smtp
	{
	    var $connection;
	    var $recipients;
	    var $headers;
	    var $timeout;
	    var $errors;
	    var $status;
	    var $body;
	    var $from;
	    var $host;
	    var $port;
	    var $helo;
	    var $auth;
	    var $user;
	    var $pass;
	
	    /**
	     *  參數為一個陣列
	     *  host        SMTP 伺服器的主機       預設:localhost
	     *  port        SMTP 伺服器的埠       預設:25
	     *  helo        發送HELO命令的名稱      預設:localhost
	     *  user        SMTP 伺服器的帳號     預設:空值
	     *  pass        SMTP 伺服器的登陸密碼   預設:空值
	     *  timeout     連線超時的時間          預設:5
	     *  @return  bool
	     */
	    function __construct($params = array())
	    {
	        if (!defined('CRLF'))
	        {
	            define('CRLF', "\r\n", true);
	        }
	
	        $this->timeout  = 10;
	        $this->status   = SMTP_STATUS_NOT_CONNECTED;
	        $this->host     = 'localhost';
	        $this->port     = 25;
	        $this->auth     = false;
	        $this->user     = '';
	        $this->pass     = '';
	        $this->errors   = array();
	
	        foreach ($params AS $key => $value)
	        {
	            $this->$key = $value;
	        }
	
	        $this->helo     = $this->host;
	
	        //  如果沒有設定帳號則不驗證
	        $this->auth = ('' == $this->user) ? false : true;
	    }
	
	    function connect($params = array())
	    {
	        if (!isset($this->status))
	        {
	            $obj = new smtp($params);
	
	            if ($obj->connect())
	            {
	                $obj->status = SMTP_STATUS_CONNECTED;
	            }
	
	            return $obj;
	        }
	        else
	        {
	            if (!empty($GLOBALS['_CFG']['smtp_ssl']))
	            {
	                $this->host = "ssl://" . $this->host;
	            }
	            $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
	
	            if ($this->connection === false)
	            {
	                $this->errors[] = 'Access is denied.';
	
	                return false;
	            }
	
	            @socket_set_timeout($this->connection, 0, 250000);
	
	            $greeting = $this->get_data();
	
	            if (is_resource($this->connection))
	            {
	                $this->status = 2;
	
	                return $this->auth ? $this->ehlo() : $this->helo();
	            }
	            else
	            {
	                log_write($errstr, __FILE__, __LINE__);
	                $this->errors[] = 'Failed to connect to server: ' . $errstr;
	
	                return false;
	            }
	        }
	    }
	
	    /**
	     * 參數為陣列
	     * recipients      接收人的陣列
	     * from            發件人的地址,也將作為回覆地址
	     * headers         頭部資訊的陣列
	     * body            郵件的主體
	     */
	
	    function send($params = array())
	    {
	        foreach ($params AS $key => $value)
	        {
	            $this->$key = $value;
	        }
	
	        if ($this->is_connected())
	        {
	            //  伺服器是否需要驗證
	            if ($this->auth)
	            {
	                if (!$this->auth())
	                {
	                    return false;
	                }
	            }
	
	            $this->mail($this->from);
	
	            if (is_array($this->recipients))
	            {
	                foreach ($this->recipients AS $value)
	                {
	                    $this->rcpt($value);
	                }
	            }
	            else
	            {
	                $this->rcpt($this->recipients);
	            }
	
	            if (!$this->data())
	            {
	                return false;
	            }
	
	            $headers = str_replace(CRLF . '.', CRLF . '..', trim(implode(CRLF, $this->headers)));
	            $body    = str_replace(CRLF . '.', CRLF . '..', $this->body);
	            $body    = substr($body, 0, 1) == '.' ? '.' . $body : $body;
	
	            $this->send_data($headers);
	            $this->send_data('');
	            $this->send_data($body);
	            $this->send_data('.');
	
	            return (substr($this->get_data(), 0, 3) === '250');
	        }
	        else
	        {
	            $this->errors[] = 'Not connected!';
	
	            return false;
	        }
	    }
	
	    function helo()
	    {
	        if (is_resource($this->connection)
	                AND $this->send_data('HELO ' . $this->helo)
	                AND substr($error = $this->get_data(), 0, 3) === '250' )
	        {
	            return true;
	        }
	        else
	        {
	            $this->errors[] = 'HELO command failed, output: ' . trim(substr($error, 3));
	
	            return false;
	        }
	    }
	
	    function ehlo()
	    {
	        if (is_resource($this->connection)
	                AND $this->send_data('EHLO ' . $this->helo)
	                AND substr($error = $this->get_data(), 0, 3) === '250' )
	        {
	            return true;
	        }
	        else
	        {
	            $this->errors[] = 'EHLO command failed, output: ' . trim(substr($error, 3));
	
	            return false;
	        }
	    }
	
	    function auth()
	    {
	        if (is_resource($this->connection)
	                AND $this->send_data('AUTH LOGIN')
	                AND substr($error = $this->get_data(), 0, 3) === '334'
	                AND $this->send_data(base64_encode($this->user))            // Send username
	                AND substr($error = $this->get_data(),0,3) === '334'
	                AND $this->send_data(base64_encode($this->pass))            // Send password
	                AND substr($error = $this->get_data(),0,3) === '235' )
	        {
	            return true;
	        }
	        else
	        {
	            $this->errors[] = 'AUTH command failed: ' . trim(substr($error, 3));
	
	            return false;
	        }
	    }
	
	    function mail($from)
	    {
	        if ($this->is_connected()
	            AND $this->send_data('MAIL FROM:<' . $from . '>')
	            AND substr($this->get_data(), 0, 2) === '250' )
	        {
	            return true;
	        }
	        else
	        {
	            return false;
	        }
	    }
	
	    function rcpt($to)
	    {
	        if ($this->is_connected()
	            AND $this->send_data('RCPT TO:<' . $to . '>')
	            AND substr($error = $this->get_data(), 0, 2) === '25')
	        {
	            return true;
	        }
	        else
	        {
	            $this->errors[] = trim(substr($error, 3));
	
	            return false;
	        }
	    }
	
	    function data()
	    {
	        if ($this->is_connected()
	            AND $this->send_data('DATA')
	            AND substr($error = $this->get_data(), 0, 3) === '354' )
	        {
	            return true;
	        }
	        else
	        {
	            $this->errors[] = trim(substr($error, 3));
	
	            return false;
	        }
	    }
	
	    function is_connected()
	    {
	        return (is_resource($this->connection) AND ($this->status === SMTP_STATUS_CONNECTED));
	    }
	
	    function send_data($data)
	    {
	        if (is_resource($this->connection))
	        {
	            return fwrite($this->connection, $data . CRLF, strlen($data) + 2);
	        }
	        else
	        {
	            return false;
	        }
	    }
	
	    function get_data()
	    {
	        $return = '';
	        $line   = '';
	
	        if (is_resource($this->connection))
	        {
	            while (strpos($return, CRLF) === false OR $line{3} !== ' ')
	            {
	                $line    = fgets($this->connection, 512);
	                $return .= $line;
	            }
	
	            return trim($return);
	        }
	        else
	        {
	            return '';
	        }
	    }
	
	    /**
	     * 獲得最後一個錯誤資訊
	     *
	     * @access  public
	     * @return  string
	     */
	    function error_msg()
	    {
	        if (!empty($this->errors))
	        {
	            $len = count($this->errors) - 1;
	            return $this->errors[$len];
	        }
	        else
	        {
	            return '';
	        }
	    }
	} 

mail_config.php

 
<?php
	$smtp_host = 'localhost';// 郵件主機域名 預設:localhost
	$smtp_port = '25';// 連接埠(預設),Gmail 456
	$smtp_user = 'xxx@xxxxx.xxx'; // SMTP 帳號
	$smtp_pass = '********';// SMTP 密碼
	$mail_service = '1';// 寄件方式 1(SMTP) 或 0(PHP mail)
	$shop_name = '網站名稱';// 寄件者姓名或網站名稱
	$smtp_mail = 'xxx@xxxxx.xxx';// 寄件者郵件地址
	$charset   = 'utf-8';// 郵件編碼 

修改 mail_config.php 填入正確的郵件資訊
將 mail.php、smtp.php、mail_config.php 放在同一個資料夾內

調用方法:

發信時需要四個參數:

 
<?php
	$name = '收件人姓名';
	$email = '收件者信箱';
	$subject = '郵件主旨';
	$content = '郵件內文';
	include_once "mail.php";
	$msg = send_mail($name, $email, $subject, $content);
	if($msg['status'] == true){
		echo '<h1 style="color:green">'.$msg.' 發送成功!</h1>';
	}else{
		echo '<h1 style="color:red">'.$msg.'</h1>';
	} 
如果你對PHP MAIL SMTP 郵件發送有任何問題請到討論區發帖。