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 郵件發送有任何問題請到討論區發帖。