
經營開放註冊的會員網站,很多人會希望:網站一發表新文章,就自動寄 Email 通知會員回來看。
這個功能用程式碼做得到,但「寄信」這件事比想像中麻煩:寄太多會被主機擋、會進垃圾信匣,寫法不對還會在每次修改文章時重複寄給所有人。這篇先講清楚該用什麼方式,再提供正確的程式碼。
先說結論:會員多,就用電子報服務
- 會員不多(例如幾十人),想自己做:可以用下面的程式碼,搭配 SMTP 外掛寄信。
- 會員上百人以上,或想看開信率、做排版漂亮的信:直接用電子報服務或外掛,例如 MailPoet、Mailchimp、Brevo,或 Jetpack 的訂閱功能。它們大多有「發佈新文章時自動寄送」的功能,退訂、退信、寄送速度都幫你處理好。
為什麼不要在發文時一次寄給所有會員?
- 發佈會卡住:如果在按下「發佈」的當下一封一封寄,要等所有信寄完頁面才會回應。會員一多就可能逾時,編輯器甚至顯示發佈失敗。
- 主機有寄信上限:大部分主機都有每小時可以寄出的信件數限制,一次寄太多會被擋,嚴重的話整個網站都寄不出信(包含會員註冊、忘記密碼的信)。
- 容易進垃圾信匣:WordPress 預設用主機的 PHP 寄信,沒有經過正式的寄信驗證,很容易被當成垃圾信。
所以不管用哪種方式,都建議先裝 SMTP 外掛(例如 WP Mail SMTP、FluentSMTP),透過正式的郵件服務寄信。這類外掛大多有「寄送測試信」的功能,設定完先測試一次。SMTP 的設定概念可以參考用 Gmail 收發公司企業信箱的寄件(SMTP)設定。
舊版程式碼的問題
這篇文章舊版的程式碼,現在使用會有幾個問題:
- 用
publish_post觸發:這個 hook 不只在第一次發佈時執行,已發佈的文章每次更新也會執行。改一個錯字,全部會員就再收到一封信。 - 用
$_POST['original_post_status']判斷:區塊編輯器不會送出這個欄位,判斷會失效,PHP 8 還會出現警告。 - 寄給資料庫裡所有帳號:包含管理員、沒打算收信的會員,也沒有提供退訂的方法。
- 在發佈當下同步寄出:就是上一節說的問題。
正確寫法:只寄給願意收信的會員,分批在背景寄送
下面的程式碼分成三個部分:
- 會員在個人資料頁自己勾選「有新文章時寄信通知我」。
- 文章第一次發佈時,不馬上寄信,而是排一個背景工作。
- 背景工作每次寄 20 封,寄完再排下一批,直到寄完。
程式碼加在子主題的 functions.php,或用 Code Snippets 外掛新增(說明請看 WordPress functions.php 實用程式碼整理)。
第一部分:會員自己選擇要不要收信
PHP
// 個人資料頁加上「新文章通知」勾選
add_action( 'show_user_profile', 'ahwei_notify_field' );
add_action( 'edit_user_profile', 'ahwei_notify_field' );
function ahwei_notify_field( $user ) {
?>
<h2>新文章通知</h2>
<table class="form-table" role="presentation">
<tr>
<th scope="row">Email 通知</th>
<td>
<label>
<input type="checkbox" name="ahwei_notify" value="1" <?php checked( get_user_meta( $user->ID, 'ahwei_notify', true ), '1' ); ?>>
網站有新文章時寄信通知我
</label>
</td>
</tr>
</table>
<?php
}
// 儲存勾選結果
add_action( 'personal_options_update', 'ahwei_save_notify_field' );
add_action( 'edit_user_profile_update', 'ahwei_save_notify_field' );
function ahwei_save_notify_field( $user_id ) {
if ( current_user_can( 'edit_user', $user_id ) ) {
update_user_meta( $user_id, 'ahwei_notify', isset( $_POST['ahwei_notify'] ) ? '1' : '0' );
}
}WordPress 在儲存個人資料之前,已經做過表單的安全檢查,這裡再確認目前的使用者有權限修改這個帳號。
第二、三部分:第一次發佈時排入背景,分批寄送
PHP
// 文章「第一次」發佈時,排入背景工作(不在發佈當下寄信)
add_action( 'transition_post_status', function ( $new_status, $old_status, $post ) {
if ( 'publish' !== $new_status || 'publish' === $old_status || 'post' !== $post->post_type ) {
return;
}
if ( get_post_meta( $post->ID, '_ahwei_notified', true ) ) {
return; // 通知過了(例如先取消發佈、又重新發佈)
}
update_post_meta( $post->ID, '_ahwei_notified', 1 );
wp_schedule_single_event( time() + MINUTE_IN_SECONDS, 'ahwei_send_post_notice', array( $post->ID, 0 ) );
}, 10, 3 );
// 背景工作:每批寄 20 封,寄完再排下一批
add_action( 'ahwei_send_post_notice', function ( $post_id, $offset ) {
$post = get_post( $post_id );
if ( ! $post || 'publish' !== $post->post_status ) {
return;
}
$batch = 20;
$users = get_users( array(
'meta_key' => 'ahwei_notify',
'meta_value' => '1',
'fields' => array( 'ID', 'user_email' ),
'orderby' => 'ID',
'order' => 'ASC',
'number' => $batch,
'offset' => $offset,
) );
$site = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
$title = wp_strip_all_tags( $post->post_title );
$subject = sprintf( '【%s】新文章:%s', $site, $title );
$message = sprintf(
"%s 發表了新文章:\n\n%s\n%s\n\n不想再收到通知,請到個人資料頁取消勾選:\n%s",
$site,
$title,
get_permalink( $post ),
admin_url( 'profile.php' )
);
foreach ( $users as $user ) {
wp_mail( $user->user_email, $subject, $message );
}
// 這批寄滿了,代表可能還有下一批
if ( count( $users ) === $batch ) {
wp_schedule_single_event(
time() + 5 * MINUTE_IN_SECONDS,
'ahwei_send_post_notice',
array( $post_id, $offset + $batch )
);
}
}, 10, 2 );這樣寫的好處:
- 只在第一次發佈時寄:用
transition_post_status判斷「從不是發佈變成發佈」,之後更新文章不會再寄;排程發佈的文章,到時間發佈時也會正常通知。 - 不會重複寄:寄過的文章會記一個
_ahwei_notified標記,就算先取消發佈再重新發佈,也不會再寄一次。 - 發佈不會卡住:寄信交給背景工作,按下發佈馬上完成。
- 分批寄送:每 5 分鐘寄 20 封,一小時大約 240 封。請依照主機或 SMTP 服務的寄送上限,調整
$batch和間隔時間。 - 信裡附上退訂方式:會員隨時可以到個人資料頁取消勾選。
使用前要知道的事
- 背景工作靠 WP-Cron 執行:WordPress 的排程是在有人瀏覽網站時才觸發,流量很少的網站,信可能會晚一點寄出。可以請主機商設定系統排程,定時執行網站的
wp-cron.php,時間會比較準。 - 會員要進得了個人資料頁:如果你用了禁止非管理者進入後台的做法,會員就打不開個人資料頁,勾選功能要改放在前台的會員頁面,或直接改用電子報外掛。
- 先測試再上線:先用自己的測試帳號勾選通知,發一篇測試文章,確認信件內容、寄件者名稱都正確,也沒有進垃圾信匣。
延伸閱讀
- 用 Gmail 收發公司企業信箱:寄件(SMTP)設定與 Gmail 停用 POP 後的收信方式
- WordPress 會員註冊後自動登入、跳轉到指定頁面(PHP 8 安全寫法)
- WordPress 禁止非管理員進入後台:訂閱者、會員登入後自動導回首頁
會員經營要長久,信要寄得到、也不能打擾人。正威網路行銷是 25 年經驗的基隆網頁設計工作室,提供客製化網頁設計與網站維護託管,服務台北與全台客戶,歡迎來聊聊。







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