0%

正威網路行銷工作室,專注於基隆、台北與全台客製化網頁設計,提供專業 RWD 響應式、SEO 搜尋引擎優化、品牌形象設計與網站維護託管服務。

搜尋文章
聯絡資訊
地址基隆市仁二路 220 號 5 樓
追蹤我們

WordPress 寄不出信怎麼辦?寄測試信、記錄錯誤原因、改用 SMTP 寄信

WordPress 寄不出信怎麼辦?寄測試信、記錄錯誤原因、改用 SMTP 寄信 封面

聯絡表單、忘記密碼、新會員通知、新訂單通知、留言通知,WordPress 裡這些信,幾乎都是同一個函式 wp_mail() 寄出去的。

所以只要寄信出問題,所有通知會一起收不到。最常見的情況是:客人打電話來問「表單送出好幾天了,怎麼都沒回?」,這時才發現網站已經好幾個月沒寄出任何一封信。

這篇有 3 段程式碼:

  1. 後台加一個「寄測試信」的頁面,按一下就知道網站寄不寄得出信
  2. 寄信失敗時,把原因記下來
  3. 改用 SMTP(Gmail、公司信箱)寄信

程式碼放在子佈景主題的 functions.php,或用 Code Snippets 這類外掛新增。

WordPress 為什麼會寄不出信

WordPress 預設的寄信方式,是把信交給主機上的寄信程式(PHP 的 mail() 函式)。問題通常出在這裡:

  • 主機沒有可以用的寄信程式:很多 VPS、雲端主機沒有安裝,或是主機商把它關掉了。
  • 寄出去了,但被當成垃圾信或直接退回:預設的寄件人是 wordpress@你的網域,這個信箱多半不存在;網域的 SPF、DKIM 設定也沒有包含這台主機。Gmail 這類信箱收到這種信,會懷疑是冒名寄的。
  • 連對外寄信的連線都被擋:有些雲端主機預設擋住對外的 25 埠。

還有一點要知道:wp_mail() 回傳「成功」,只代表信已經交給寄信程式,不代表對方真的收到了。

1. 後台加一個「寄測試信」頁面

PHP
// 後台「工具 → 寄測試信」:輸入信箱按一下,馬上知道網站寄不寄得出信,寄不出去會顯示原因
add_action( 'admin_menu', function () {
	add_management_page( '寄測試信', '寄測試信', 'manage_options', 'zw-test-mail', 'zw_test_mail_page' );
} );

function zw_test_mail_page() {
	$result = '';
	if ( isset( $_POST['zw_to'] ) && check_admin_referer( 'zw_test_mail' ) ) {
		$to    = sanitize_email( wp_unslash( $_POST['zw_to'] ) );
		$error = '';
		$catch = function ( $e ) use ( &$error ) {
			$error = $e->get_error_message();
		};
		add_action( 'wp_mail_failed', $catch );
		$ok = wp_mail( $to, '【' . get_bloginfo( 'name' ) . '】測試信', "收到這封信,代表網站可以正常寄信。\n寄出時間:" . wp_date( 'Y-m-d H:i:s' ) );
		remove_action( 'wp_mail_failed', $catch );
		$result = $ok
			? '<div class="notice notice-success"><p>已經交給寄信程式寄出,請到 ' . esc_html( $to ) . ' 收信(也看一下垃圾信件匣)。</p></div>'
			: '<div class="notice notice-error"><p>寄不出去:' . esc_html( $error ? $error : '沒有錯誤訊息' ) . '</p></div>';
	}
	?>
	<div class="wrap">
		<h1>寄測試信</h1>
		<?php echo $result; // 上面已經跳脫過 ?>
		<form method="post">
			<?php wp_nonce_field( 'zw_test_mail' ); ?>
			<p><input type="email" name="zw_to" class="regular-text" required value="<?php echo esc_attr( wp_get_current_user()->user_email ); ?>"></p>
			<?php submit_button( '寄一封測試信' ); ?>
		</form>
	</div>
	<?php
}

加上之後,後台「工具」底下會多一個「寄測試信」:

  • 預設填的是自己登入帳號的 Email,可以改成別的信箱,例如老闆的手機常用信箱。
  • 寄不出去:紅色框直接顯示原因,例如「寄不出去:無法具現化 mail 函式。」
  • 交給寄信程式成功:綠色框提醒去收信,也要看垃圾信件匣。成功交出但收不到,問題就在後面的「垃圾信、退信」那一段。
  • 只有管理員(manage_options 權限)看得到這個頁面,送出時會檢查 nonce,別人沒辦法用外部表單叫你的網站亂寄信。

建議收 Gmail、Outlook、公司信箱各寄一封,看看是不是每一家都收得到。

2. 寄信失敗時記下原因

PHP
// 寄信失敗時記下原因:寫進 PHP 錯誤紀錄(主機的 error_log,或開了 WP_DEBUG_LOG 時的 wp-content/debug.log)
add_action( 'wp_mail_failed', function ( $error ) {
	$data = (array) $error->get_error_data();
	$to   = isset( $data['to'] ) ? implode( ', ', (array) $data['to'] ) : '';
	error_log( sprintf(
		'[寄信失敗] %s|收件人:%s|主旨:%s',
		$error->get_error_message(),
		$to,
		isset( $data['subject'] ) ? $data['subject'] : ''
	) );
} );
  • wp_mail_failed 是寄信失敗時 WordPress 會觸發的動作,錯誤物件裡有錯誤訊息,以及收件人、主旨、內容。
  • 這裡把「錯誤訊息、收件人、主旨」寫成一行,存進 PHP 的錯誤紀錄。有開 WP_DEBUG_LOG 的網站會寫進 wp-content/debug.log;沒開的話,寫進主機的 PHP 錯誤紀錄(位置問主機商,或在主機控制台找 error log)。
  • 信的內容沒有記,避免把客人填的資料寫進紀錄檔。

debug.log 怎麼開、看完要記得關,可以看〈WordPress 出現 500 錯誤怎麼辦〉裡的說明。

3. 改用 SMTP 寄信

SMTP 就是用一個真的信箱帳號登入寄信,像用 Outlook 寄公司信一樣。對方收到的信,寄件人是真的存在、網域也對得上的信箱,比較不會被當成垃圾信。

PHP
// 改用 SMTP 寄信:帳號、密碼寫在 wp-config.php,這裡只讀常數
add_action( 'phpmailer_init', function ( $phpmailer ) {
	if ( ! defined( 'ZW_SMTP_HOST' ) ) {
		return; // 沒設定就照 WordPress 原本的方式寄
	}
	$phpmailer->isSMTP();
	$phpmailer->Host       = ZW_SMTP_HOST;
	$phpmailer->Port       = (int) ZW_SMTP_PORT;
	$phpmailer->SMTPAuth   = true;
	$phpmailer->Username   = ZW_SMTP_USER;
	$phpmailer->Password   = ZW_SMTP_PASS;
	$phpmailer->SMTPSecure = 465 === (int) ZW_SMTP_PORT ? 'ssl' : 'tls';
	// 寄件人改成 SMTP 帳號本身,避免被收件端當成冒名
	$phpmailer->setFrom( ZW_SMTP_USER, get_bloginfo( 'name' ), false );
} );

帳號、密碼不要寫在 functions.php。這段程式碼只讀常數,常數寫在網站根目錄的 wp-config.php,放在 require_once ABSPATH . 'wp-settings.php'; 這一行的上面:

PHP
// SMTP 寄信設定
define( 'ZW_SMTP_HOST', 'smtp.gmail.com' );
define( 'ZW_SMTP_PORT', 587 );
define( 'ZW_SMTP_USER', 'shop@example.com' );
define( 'ZW_SMTP_PASS', '應用程式密碼' );
  • wp-config.php 沒加常數,程式碼就不會改任何東西,照 WordPress 原本的方式寄。可以先放程式碼,確定帳號後再加常數。
  • 埠號:587 用 TLS、465 用 SSL,程式碼會依埠號自動選。兩個都可以就用 587。
  • 寄件人改成 SMTP 帳號本身,名稱用網站名稱。很多 SMTP 服務只允許用登入的帳號當寄件人,寫別的信箱會被拒絕或改掉。

用 Gmail 寄:主機填 smtp.gmail.com。密碼不是 Gmail 的登入密碼,要先開啟兩步驟驗證,再建立一組「應用程式密碼」,填那 16 個字元。細節可以看〈用 Gmail 收發公司企業信箱〉的寄件(SMTP)設定。

用公司信箱(主機商、網域商提供的)寄:SMTP 主機名稱、埠號,問提供信箱的廠商,或看他們的設定說明。

已經裝了 SMTP 外掛(例如 WP Mail SMTP)的網站,就不要再加這一段,兩邊會改同一組設定。寄測試信頁面和記錄錯誤的程式碼,和外掛一起用沒有問題。

常見的錯誤訊息代表什麼

以下是 WordPress 繁體中文介面會顯示的訊息(括號裡是英文原文):

  • 「無法具現化 mail 函式。」(Could not instantiate mail function.) 主機沒有可以用的寄信程式。最直接的解法:改用上面的 SMTP 寄信。
  • 「SMTP 錯誤: 無法連線至 SMTP 主機。」(Could not connect to SMTP host.) 連不到 SMTP 主機。檢查主機名稱、埠號有沒有打錯;587 不行換 465 試試;還是不行,問主機商有沒有擋對外的連線。
  • 「SMTP 錯誤: 無法驗證。」(Could not authenticate.) 連上了,但帳號或密碼錯。用 Gmail 的話,確認填的是應用程式密碼。
  • 「無效的電子郵件地址」(Invalid address) 收件人或寄件人的 Email 格式不對。常見是表單外掛的收件人欄位多打了空白、全形符號,或用分號隔開好幾個信箱。
  • 顯示成功,卻收不到 先看垃圾信件匣。接著檢查寄件網域的 SPF、DKIM 設定(寄信服務商、主機商的說明裡都有該填什麼)。網域的 Email 設定可以用〈網站自我檢查的免費工具〉裡的 Email 檢查工具看。

實際測試的結果

測試站:WordPress 7.1.3(繁體中文)、PHP 8.3,主機本身沒有寄信程式,模擬最常見的寄不出信情況。

沒有加任何程式碼

  • WordPress 用主機的 mail() 寄,寄件人是 wordpress@(網站網域)、名稱是「WordPress」。
  • 寄信失敗,錯誤訊息是「無法具現化 mail 函式。」,但網站上什麼都看不到,沒有任何提示。

加上寄測試信頁面

  • 後台「工具」底下出現「寄測試信」,預設填好管理員的 Email。
  • 按下寄出,紅色框顯示「寄不出去:無法具現化 mail 函式。」
  • 換成信件可以順利交出的情況,綠色框顯示「已經交給寄信程式寄出,請到…收信(也看一下垃圾信件匣)。」信的主旨是「【網站名稱】測試信」,內容有寄出時間。

加上記錄錯誤

debug.log 多了這樣一行(時間是 UTC):

純文字
[16-Oct-2026 06:15:48 UTC] [寄信失敗] 無法具現化 mail 函式。|收件人:test@example.com|主旨:測試主旨

再加上 wp-config.php 的 SMTP 常數(用假的 Gmail 帳號測試)

  • 寄信方式從 mail 變成 smtp,主機 smtp.gmail.com、埠號 587、加密方式 TLS、有登入驗證。
  • 寄件人變成 SMTP 帳號 shop@example.com,名稱變成網站名稱。
  • 測試站的環境沒辦法和 Gmail 完成加密連線(SSL 憑證驗證失敗),寄信失敗;錯誤訊息「SMTP 錯誤: 無法連線至 SMTP 主機。」加上連線失敗的細節,一樣被記進 debug.log。

拿掉 wp-config.php 的常數,又回到原本的 mail() 寄信,程式碼不會出錯。

延伸閱讀

網站的信寄不出去,損失的常常是看不見的詢價。正威網路行銷是 25 年經驗的基隆網頁設計工作室,網站管家年費包含系統、外掛與安全性更新,以及每半年一次網站健檢報告,台北與全台客戶也歡迎來聊聊。

分享這篇文章

返回文章列表更多「Wordpress代碼教學」文章

發表留言

還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。

讓我們一起打造
您的專屬網站!