1 Control Issues of WordPress Email Notifications
Regarding the email notification feature of WordPress, friends who use WordPress to build websites should be no stranger to it, right? Whether it is the automatic upgrade of the core version, the automatic upgrade of plugins, or new comments and replies on the site, the administrator's email will almost always receive the corresponding email reminder at the first opportunity.
For friends who need to keep track of the site status in a timely manner, email notification is undoubtedly an important feature. It has indeed played the role of “the site's external voice” for a long time: if there is an anomaly, someone interacts, or the system changes, there will always be feedback in the mailbox.
However, as usage time increases, many people will gradually find these notifications a headache—especially system-level emails such as automatic plugin upgrades or WordPress core updates. These types of emails often do not directly affect the actual operation of the website and rarely require immediate intervention from the administrator, yet they frequently appear in the inbox, creating a continuous distraction of attention (especially for friends who are sensitive to new email alerts, this experience will be even more pronounced).
What is even more confusing is that WordPress does not provide a unified, intuitive switch that allows site administrators to clearly control “which system events are worth notifying externally via email.” Although there are indeed some scattered configuration items, constant definitions, or developer-oriented interfaces in the backend or at the code level that can affect email sending behavior to some extent, these methods are often fragmented and scattered, making it difficult to solve the problem of chaotic notification granularity as a whole.
After a period of actual use and observation, I gradually realized a phenomenon: most of the WordPress system emails I receive do not actually change anything I am going to do next. Whether a plugin has successfully completed an automatic upgrade or the core version update has finished, this information itself is more like an “external presentation” of backend logs, rather than an event that requires my immediate response or handling.
Especially when the blog gradually changes from an “online system” that needs passive response at any time to a personal space that I will regularly check and actively maintain, the value of these emails begins to decline. They are no longer necessary reminders, but rather like a continuous interruption, consuming attention unconsciously.
Thus, the question becomes clearer:Is there really still a need for this mechanism of WordPress sending emails on its own to continue to exist?
To judge this, we first need to go back to WordPress itself and see how its built-in email sending mechanism actually works.
2 Why WordPress “Should Not Send Emails Itself"
1 What is the Default Email Behavior of WordPress
Under the default configuration, WordPress itself has complete email sending capabilities and does not rely on any third-party plugins. As long as the server environment allows, WordPress can directly send email notifications to the configured administrator email or related users when various events occur.
These emails trigger a very wide range of scenarios, including automatic upgrades of the WordPress core, automatic update results of plugins or themes, reminders of new comments and comment replies, as well as account security-related operations such as user registration and password retrieval. From the user's perspective, they belong to different types of “notifications”; but inside WordPress, these events are not strictly distinguished as logs, reminders, or security processes, but instead uniformly go through the same email sending mechanism.
From the implementation level, all emails sent externally by WordPress will eventually converge into a core function — wp_mail(). Inside WordPress, there are no multiple parallel email systems: whether it is a prompt for a completed system update or a password retrieval email, it is essentially just a certain event triggering a call to wp_mail().
By default, wp_mail() is not responsible for the underlying actual delivery logic, but is merely a wrapper around PHP's mail() function, handing the email over to the mail transfer agent at the operating system level for further processing. Because of this, the scope that WordPress can control actually stops at the wp_mail() layer. Whether the subsequent sending process is successful or accepted by the recipient is not under its direct control:
WordPress → wp_mail() → PHP mail() → 系统 MTA → 外部世界
This also means that, without the intervention of additional plugins, the email sending path of WordPress is roughly fixed: after an event is triggered, the email will be synchronously generated and attempted to be sent in the current request flow. As for which specific MTA is used on the server, whether the email is actually delivered, or whether it is rejected or marked as spam by the recipient's server, WordPress itself will not perceive it, nor will it leave a complete sending record.
It should be noted that WordPress's focus on email sending is actually very limited: as long as wp_mail() does not explicitly return an error, it will consider this email sending to be “successful.” Under this design, critical password retrieval emails and non-urgent system update success reminders have no essential difference in their sending mechanism, nor is there any distinction in priority or level.
This also explains a common misconception: many users configure the email function for the first time by installing an SMTP plugin, so they easily think that “WordPress can only send emails if a plugin is installed.” In fact, SMTP plugins are mostly justreplacing or optimizing the way emails are sent, rather than giving WordPress the email capability itself. Even in the complete absence of plugins, as long as the server allows calling mail(), WordPress can still send emails externally on its own.
After understanding the default email behavior of WordPress, what needs to be discussed next is no longer “whether it can send emails,” but:what problems this design will bring in practical use when all types of events are uniformly treated as triggers for sending emails.
2 Hidden Problems Brought by This Email Mechanism
After understanding the default email sending method of WordPress, we no longer just focus on the surface question of “whether it can send emails,” but need to think deeply:what hidden impacts this design will bring in practical use when all types of events are uniformly treated as triggers for sending emails.
Fundamentally, WordPress does not design its email mechanism around a “notification system,” but merely treats email as a handy output method. Prompts for completed system updates, plugin upgrade notifications, and even password retrieval emails are essentially just a certain event triggering a call to wp_mail().
This design often does not immediately expose problems when the site scale is small and functions are simple, but as usage time goes on and site maintenance methods change, some hidden impacts will gradually manifest.
First, the most intuitive problem lies inthe tight coupling between events and notifications. In WordPress, as long as an event needs to “notify the administrator” or “remind the user”, the most direct and common practice is to trigger an email. This design does not distinguish the importance of the event itself, nor does it determine whether it is truly necessary to interrupt the user immediately. As a result, information that is more of a “background status change”, such as successful system-level updates and completed plugin upgrades, is pushed into the same inbox along with actions that require timely attention, such as comment replies and password resets.
Secondly, this mechanism has almostno clear control over notification granularity. WordPress does not provide a unified location for site administrators to clearly decide: which events should trigger emails, which only need to be logged, and which can be completely ignored. Some emails can be turned off through dashboard options, while others require code or filters to intervene, presenting an overall “scattered and distributed” state. This inconsistent control method often gives users the illusion that email notifications seem configurable, but in reality, they are very difficult to truly “tame”.
The third easily overlooked issue is thatemail sending itself is a synchronous side effect. In the default design, the generation and sending of emails occur during the execution of the current request, which means that every operation that triggers an email incurs the additional cost of a sending attempt. When the sending path is unstable, the server environment is restricted, or the email system responds slowly, this side effect directly affects the completion time of the request itself, and WordPress does not distinguish between “whether the business logic has been completed” and “whether the notification was successfully sent”.
In addition, due to the lack of comprehensive sending logs and status feedback, the email system in WordPress often presents a black-box state— It is difficult for site administrators to accurately determine whether an email was actually sent successfully, discarded midway, or rejected due to server policies. Over time, these emails become more of a “best effort” attempt rather than an auditable, traceable notification mechanism.
When these issues compound, they lead to a result that is not easily noticed immediately:Emails gradually degrade from “valuable reminders” to a persistent source of distractionWhen users find that most emails do not change their maintenance decisions or affect the actual operation of the website, their attention is repeatedly consumed with very little real benefit.
It is against this background that the problem begins to shift. People gradually realize that what really needs to be re-examined is not “whether these email notifications can be further optimized,” but rather:Whether it is necessary to continue letting WordPress handle the responsibility of sending emails itself.
3 Why This Mechanism is Unacceptable for Professional Sites
Although WordPress's default email mechanism mostly works fine in personal or low-complexity sites, this mechanism is often unacceptable in commercial, high-availability, or multi-person collaborative environments.
Professional sites usually have stricter requirements for emails: the sending path must be controllable, delivery status must be observable, logs must be auditable, and there must be clear policies to distinguish event levels. However, WordPress's default method of calling the system MTA via wp_mail() cannot meet these needs:
- Insufficient observability: The default mechanism cannot provide complete feedback on sending status, nor can it distinguish between “email successfully delivered” and “sending failed.” In professional sites, every email delivery can affect critical business, such as password resets, user registration confirmations, or financial notifications. If the delivery of emails cannot be accurately confirmed, it may cause business disruption or user complaints.
- Blurred control boundaries: The application layer directly triggers emails, making it impossible to centrally manage event types, sending timing, and sending channels. In high-availability architectures, this loose control method can easily lead to inconsistent behavior, or even trigger duplicate or missed notifications.
- Risk of synchronous side effects: Email sending is embedded in the request flow. If the email system responds slowly or the server environment is restricted, it may affect the overall response time of the site. For high-traffic commercial sites, this accumulated latency can directly impact user experience.
- Lack of policy grading: It is impossible to set different handling methods based on event types; system updates, plugin upgrades, and user notifications are all in one place, making them difficult to manage separately. In professional environments, different levels of events require different notification policies: core business events must be notified in real-time, while background status changes can be aggregated in batches. Mixing them together is not only inefficient but may also interfere with operational judgment.
Because, in many commercial or high-availability environments, WordPress sending emails itself is often prohibitedThe triggering, delivery, and notification methods of emails are usually split into clearer boundaries of responsibility: the application layer is only responsible for generating events or status changes, while whether to send emails, how to send them, and through which channels to notify are managed centrally by dedicated infrastructure or external systems. In this way, email becomes a controllable, replaceable, and auditable capability, rather than a byproduct of the application “doing it in passing.”
For example, in an enterprise-facing WordPress site, if password recovery emails or important update notifications are occasionally lost or delayed, it may prevent users from accessing the system or lead to service complaints. In such an environment, any behavior of “sending emails casually” is unacceptable.
After understanding this point, the next question to discuss is very clear:How to completely disable WordPress's self-sending email mechanism while retaining necessary notifications, and manage all email events in a controllable manner。
4 How Professional Sites Optimize Email Logic
Having understood the hidden problems of WordPress's default email mechanism and why it is unacceptable in professional sites, we cannot help but ask:In commercial or high-availability environments, how can we optimize email logic to make notifications controllable and reliable?
In reality, professional sites usually do not rely on WordPress itself to send emails. Emails are no longer a casual output of the application layer, but are integrated into the overall notification system, ensuring that every notification is controllable, auditable, and replaceable. There are three main implementation approaches.
Completely disable PHP's mail() calls at the system level
Disable sendmail in the server or container, or do not install a Mail Transfer Agent (MTA) at all, causing PHP's mail() calls to fail directly. The effect of doing this is very direct: WordPress is physically unable to send emails. Any system update notifications, plugin upgrade prompts, or even password recovery emails will no longer trigger on their own. The advantage is absolute reliability, while the disadvantage is that an alternative solution must be designed at the application layer or in an external system, otherwise functions like password recovery will fail.
Hijack or rewrite wp_mail() at the application layer
By intercepting WordPress's calls to wp_mail(), you can prevent it from actually delivering emails, and instead write the events to logs, push them to message queues, or hand them over to external notification systems for processing. The advantage of this is that it retains the event triggering logic while completely controlling email sending. It not only improves observability and auditability but also makes it easy to integrate notifications into different channels, such as email, SMS, or instant messaging systems.
Process uniformly through external notification services
In the most professional environments, all notifications—whether email, SMS, push, or instant messaging—will go through a unified message queue and then be sent out via a notification gateway or monitoring system. WordPress itself only exists as an event source and no longer sends emails directly. This design makes notifications controllable, replaceable, and scalable. Whether it is a system-level update or a user operation notification, there is a clear boundary of responsibility, and it can be monitored, recorded, and optimized.
Overall,in professional sites, WordPress no longer sends emails itself, but only serves as an event source for external systems to handle notificationsThis not only ensures the reliability of email sending but also makes notification granularity, sending policies, and failure handling controllable. Having understood these practices, next we will focus on discussing:How to completely disable the self-sending email mechanism within WordPress and let it be fully managed by external systems。
3 Why I Started Taking the WordPress Email Mechanism Seriously
What really got me to start seriously studying the WordPress email mechanism was not out of some “system design OCD,” but stemmed from the third optimization of the blog architecture (relevant background can be found in the previous article on the evolution of the blog architecture:Home Data Center Series: The Third Optimization of Blog Architecture: WordPress Active-Active Node Adjustment and Database Import Precautions)。
In the first two architectural adjustments of the blog, the overall structure was relatively simple: WordPress actually only ran on two nodes—macmini as the primary write node, and another node handling read traffic and backup roles. At that time, whenever a new comment was generated, both nodes would each send a comment notification email, and the administrator's mailbox would naturally receive two reminders with almost identical content.
To be honest, at that stage, this problem waspresent, but still tolerableComments themselves were not very frequent. Although two duplicate emails were slightly redundant, they were not enough to truly affect the user experience, so the issue was left aside.
It wasn't until the third architectural optimization was completed that things really changed—with the addition of the intermini node, the blog evolved from the original “two-node structure” to a “three-node structure”: macmini still served as the primary write node, while intermini and the Chicago node took on read services and redundancy roles. This adjustment was reasonable at the architectural level, but WordPress's email mechanism would not perceive this change in “node roles.”
The result was also very direct—every time a comment was generated, all three nodes would trigger their own email sending logic, and the administrator's mailbox would consequently receive three almost identical comment notification emails.
This time, the problem had turned from “slightly redundant” intoa clear distractionComments themselves are of course valuable, but three completely duplicate notifications do not bring any additional information; instead, they constantly consume attention. What's more embarrassing is that this duplication not only affects me, but visitors will also receive three almost identical notification emails after posting a comment. This is no longer just “redundant” but a clear user experience issue.
More importantly, this behavior itself does not align with the actual architectural design of the current blog. In my vision,only the macmini primary write node needs to bear the responsibility of external notifications, and the remaining nodes neither need to nor should send any emails on their own.
It was also at this moment that I realized a previously overlooked issue: WordPress has no concept of “node roles.” It simply calls wp_mail() as a matter of course when a local event occurs, attempting to send the email. As for whether this email is meaningful, duplicate, or fits the overall architectural design, WordPress does not and cannot make that judgment.
Therefore, for me, the goal of the problem is actually very clear and very restrained. I do not need to refactor a complete notification system, nor do I plan to introduce message queues or a unified notification gateway at this stage. What I truly need is simply to let non-primary nodes stop sending emails on their own。
This is not a decision to “make things big”; on the contrary, it is aprecise convergence targeting the current architecture. As for how to uniformly manage notifications through external systems in more professional or complex scenarios, these ideas have already been discussed in Section 2.4, and this article will not expand on their implementation.
Additionally, it should be noted that:if it is a single-node WordPress site, and you only want to turn off comment-related email notifications, you don't actually need to mess with any code. The WordPress admin dashboard itself provides corresponding toggles; checking or unchecking them will take effect:

But this approach, under my current architecture, isineffective。
The reason is not complicated: these settings in the WordPress admin dashboard are essentially stored in the database as configuration options, specifically in the wp_options table.
In my multi-node architecture, however,the database is synchronized using the macmini primary write node as the source—this means that even if I manually turn off these 3 comment email options on the intermini and Chicago nodes, after the next database synchronization from macmini to these two nodes, the settings on these nodes will still be overwritten by the primary node's configuration.
In other words,Toggles at the admin option level do not have the capability for “node-differentiated configuration”. Under this architecture, WordPress only recognizes “this is the same site” and does not understand “these are nodes with different roles.”
Therefore, to truly solve this problem, the only reasonable way is to:directly disable WordPress's email sending capability itself on the intermini and Chicago nodes, rather than relying on admin configurations.
4 Disabling WordPress from Directly Sending Emails
1 Implementation Idea: Controlling WordPress Email Sending in a Multi-Node Environment
In Chapter 3, we clarified the core of the problem: in a multi-node environment, only the primary node needs to bear the responsibility of sending emails, while emails from other nodes are redundant and disruptive side effects. This means our goal is not to optimize email content, nor to reconstruct the entire notification system, but to completely disable WordPress from sending emails on its own on non-primary nodes.
Regarding the specific implementation methods, there are the following 4 conventional options:
- Disable email-related options in the admin dashboard
For single-node sites, this is usually the most direct approach: WordPress provides toggles for emails like comment notifications and update notifications, which take effect when checked or unchecked. However, in a multi-node synchronization environment, these configurations are stored in the wp_options table of the database and will overwrite the settings of non-primary nodes during data synchronization from the primary node. Therefore, relying solely on admin options cannot achieve node-differentiated control.
- Use a regular plugin to intercept wp_mail()
In theory, this can work, but regular plugins load later than WordPress core functions, sometimes loading the interception only after the email logic has already been triggered. At the same time, if the plugin logic depends on database configurations, it might also be overwritten during the synchronization process. Under a multi-node architecture, stability and controllability are limited.
- Modify global configuration or wp-config.php
can disable the email capability of the entire site, but lacks flexibility: it cannot be controlled solely for non-primary nodes, which may affect other functions or future expansions.
- Use mu-plugin (Must-Use Plugin)
A mu-plugin is a special type of plugin that automatically loads as long as it is placed in the wp-content/mu-plugins directory, without requiring manual activation. It loads early in the execution order, allowing it to intercept before core logic triggers emails, and it does not rely on database configurations. Therefore, it is highly suitable for implementing email constraints on non-primary nodes in a multi-node environment.
Among the many methods, I ultimately chose mu-plugin as the means of email control for non-primary nodes, because it can precisely and thoroughly achieve the goal: completely disabling the intermini and Chicago nodes from sending emails while keeping the primary node sending normally. The core advantages of mu-plugins include:
- No manual activation required: Simply placing it in the wp-content/mu-plugins directory of non-primary nodes will automatically load it, without requiring admin operations or relying on database settings.
- Early loading order: mu-plugins run before regular plugins, allowing them to intercept wp_mail() calls before any email operations occur, fundamentally preventing non-primary nodes from sending emails.
- Independent of database configuration: It will not be overwritten by the primary node's database synchronization, ensuring it takes effect locally on non-primary nodes.
- Simple operation: The file is very short, usually just a few dozen lines, without needing to modify core code or admin settings.
In addition, mu-plugins also have good scalability: if there is a need to add other notification channels (such as SMS, instant messaging, or a unified notification gateway) in a multi-node environment in the future, the mu-plugin can serve as an event interception entry point to push events to external systems, without breaking the independence of existing nodes.
In short, choosing mu-plugin as the implementation method is based on a comprehensive consideration of factors such as multi-node architectural constraints, email behavior side effects, and database synchronization characteristics . It is precise and restrained; as described in Chapter 3, this is not a decision to “start a big project,” but a targeted convergence of the current architecture.
2 Practical Operation: Completely Disabling WordPress from Sending Emails on Non-Primary Nodes
After clarifying the implementation approach, the actual operation is instead very restrained.
The entire process does not require modifying WordPress core code, does not rely on backend configurations, and does not introduce additional systems; it only requires doing non-primary nodes two things:
- Clearly identify "this is a node that should not send emails"
-
Intercept all email requests before the emails are actually sent
Step 1: Mark “disable email sending” on non-primary nodes”
In order to make the same code behave differently on different nodes, we need aclear, stable, and readable judgment condition。
Here, we adopt the most intuitive method that also best fits WordPress usage habits:Add a custom constant to the wp-config.php of non-primary nodes.
在 intermini / Chicago node 's wp-config.php:
define('WP_DISABLE_MAIL', true);
而 macmini primary node does not add this configuration line.
The meaning of doing this is very clear: WP_DISABLE_MAIL = true → this is a non-primary node, email sending is disabled; if this constant is undefined → this is the primary node, email behavior remains default.
This judgment does not rely on the database, does not participate in SQL synchronization, and will not be overwritten by backend configurations, making it highly suitable as a node-level behavior switch.
From the perspective of engineering implementation, a more ideal approach is actually throughenvironment variablesto identify node roles, such as injecting node identifiers in Docker, systemd, control panel environment variables, or startup scripts. This avoids maintaining multiple copies of wp-config.php and is more elegant in large-scale deployment or automation scenarios.
However, in this article, choosing to distinguish between primary and non-primary nodes by modifying wp-config.php is adeliberate trade-off. Its path is clear enough, the modification method is intuitive enough, and the behavior is highly deterministic, with almost no uncertainty about “whether it has actually taken effect.” At the same time, this approach is more in line with the usage habits of most WordPress users, with very low reading and replication costs.
If you are very familiar with your operating environment, you can completely replace the judgment condition here with environment variables to make the implementation more engineered; but if not, the version of the solution provided in this article is already stable, clear, and “convergent” enough, without the need to introduce additional complexity for this.
Step 2: Create a mu-plugin as the email interception entry point
Next, in non-primary nodes create the mu-plugin. Confirm that the directory exists:
wp-content/mu-plugins/
If it does not exist, simply create it:
mkdir -p wp-content/mu-plugins
Then create a new file:
wp-content/mu-plugins/disable-mail.php
Step 3: Write the interception code (subject to the actual effective version)
Write the following content into disable-mail.php:
<?php
/**
* Plugin Name: Disable Mail on Non-Primary Node
* Description: Disable all outgoing emails on non-primary WordPress nodes.
* Author: tangwudi
* Version: 1.0
*/
/**
* 判断当前节点是否为非主节点
* WP_DISABLE_MAIL = true 表示需要禁用邮件
*/
is_non_primary_node = defined('WP_DISABLE_MAIL') && WP_DISABLE_MAIL === true;
if (is_non_primary_node) {
/**
* 使用 pre_wp_mail 直接在最前置阶段拦截邮件
* 返回 true 表示邮件已被“处理”,WordPress 不会继续发送
*/
add_filter('pre_wp_mail', function (null,atts) {
// 可选:调试日志,用于确认 mu-plugin 是否正常加载
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log(sprintf(
'[Disable Mail mu-plugin] 邮件已拦截:to=%s, subject=%s',
is_array(atts['to']) ? implode(',',atts['to']) : atts['to'],atts['subject']
));
}
return true;
}, 10, 2);
}
What this code does is very single-minded and very clear: only on non-primary nodes take effect; it does not modify any business logic; it does not affect processes like comments, logins, or updates; it just, before WordPress is ready to actually send the mail, “eats” the email request—from the perspective of WordPress, the email has been processed normally; from the system level, nothing was actually sent.
Why is this combination stable in a multi-node environment? The key here is not “intercepting emails”, but inthe location where the interception occurs and the basis for judgment:
- The mu-plugin loading order is early enough: the email logic is terminated before it even reaches SMTP or PHP Mailer.
- The judgment condition comes from the local configuration file: it does not rely on the database and does not participate in data synchronization from the primary node.
- Complete separation of responsibilities between the primary node and non-primary nodes: the primary node is only responsible for “actual external notifications”, while other nodes are only responsible for “business execution”.
This is precisely the point repeatedly emphasized earlier:Email is not the business itself, but a side effect generated by the business.
3 Implementation Effect Verification and Behavioral Boundaries
After completing the mu-plugin deployment, two things need to be confirmed: first, whether the email sending behavior of non-primary nodes has been successfully blocked; second, whether this blocking will have side effects on the normal operation of WordPress.
The verification method is not complicated; you can directly use common email trigger scenarios within WordPress itself to observe the results. For example, perform a plugin or theme update in the backend of a non-primary node, or trigger a comment submission on the frontend. By default, these actions will call wp_mail() to send notification emails, making them a very intuitive entry point for verification.
During the actual verification process, a clear result can be observed: the email behavior on the primary node (macmini) is completely normal, with update notifications and comment notifications sending successfully; while on the intermini and Chicago nodes, the corresponding operations no longer trigger any email sending behavior. At the same time, no errors appeared on either the WordPress backend or frontend pages, and neither the update process nor the comment process was affected.
This indicates that the mu-plugin's interception only acts on the single behavior of email sending and does not disrupt WordPress's event handling logic. In other words, the events themselves are still triggered and processed normally, except that on non-primary nodes, the side effect of emails is safely removed.
From the perspective of implementation boundaries, this solution possesses several technical characteristics: it does not modify core code, nor does it rely on database configurations; all logic exists solely in the local mu-plugins directory of non-primary nodes, so it is unaffected by database synchronization behavior. Meanwhile, the interception point is concentrated at the wp_mail() level, keeping the scope of impact controllable without affecting the normal execution of other plugins or themes.
At this point, the technical goal has been achieved: email sending behavior on non-primary nodes is completely disabled, without introducing additional system complexity or altering the existing multi-node synchronization process. Continuing to expand at the implementation level is no longer a necessary condition for “solving the problem” but rather falls under the scope of functional extension, which can be left for discussion in subsequent scenarios.
5 Some Boundaries and Trade-offs
At this point, the matter is actually concluded—non-primary nodes no longer send any emails, while the behavior of the primary write node remains unchanged; WordPress itself shows no anomalies, and page access, comment workflows, or backend operations have not been affected by the email interception. From an engineering perspective, this is already a complete, closed-loop problem-solving process, rather than an intermediate state that “still needs further optimization.”
But precisely because the issue was resolved so cleanly, it is instead necessary to pause and clarify some boundaries and background. First, it must be emphasized that this article is not attempting to “fix” or “reconstruct” the WordPress email system. In fact, in a single-node scenario, WordPress's current email mechanism itself has no obvious issues: events occur, trigger locally, and notify instantly—this is a very direct and highly intuitive design. What actually causes the problem is not the email mechanism itself, but ratherthe mismatch between multi-node architecture and differences in node roles。
In other words, the question from the very beginning was not “should emails be sent,” but rather “which nodes are authorized to send them.” Once this was clarified, all subsequent decisions revolved around “how to make WordPress shut up on non-primary nodes,” rather than designing a more complex notification system. This is also why, although more professional and systematic solutions were mentioned earlier—such as unified notification centers, message queues, and external notification gateways—we ultimately did not proceed in that direction.
The reason is simple: under the current blog architecture, these solutions are not better solutions, but simply heavier ones. Introducing extra components, services, and maintenance costs just to eliminate a few duplicate emails is inherently an imbalance. Especially in an architecture that can already clearly distinguish between “primary write nodes” and “read nodes,” using the minimal approach to keep system behavior aligned with architectural intent is instead a more stable choice.
This is also why an approach like mu-plugin, which seems “very simple,” ended up being the final solution. It is neither clever nor flexible, and could even be described as somewhat “brute-force”: once enabled, all wp_mail() calls on the node are intercepted, regardless of email type or trigger source. But it is precisely this uncompromising behavior that makes it highly suitable for the current problem scenario—on non-primary nodes, emails shouldn't exist in the first place。
Of course, this also means that this solution has clear boundaries—if your requirement is to “only disable certain types of emails,” or if you wish to dynamically allow notifications under different conditions, then what you need is no longer a simple interception point, but a more refined rule system. That is already another problem domain, and is no longer suitable to be solved in the restrained manner of this article.
Similarly, this article also deliberately avoids the seemingly elegant direction of “making the behavior configurable.” The reason is not complicated: once configuration is introduced, it means introducing state synchronization, and state synchronization is precisely one of the most error-prone parts in a multi-node environment. Contrastingly, a judgment based entirely on the presence or absence of a local file on the node is instead clearer, more controllable, and better aligned with the reality of the current architecture—from this perspective, mu-plugin is more like adeployment-level decision, rather than a runtime decision: put it in place, and it takes effect; take it away, and it reverts. There is no intermediate state, and it will not be affected by database synchronization.
It should be noted that the verification in this article is mainly based on a non-primary node environment running on a VPS. In this environment, node roles are clear and the email path is relatively pure, making it easier to confirm “whether the email was successfully intercepted.” In more complex local virtualization or home networks, the email sending path may be affected by additional factors, such as container networking, forwarding policies, and differences in SMTP plugin behavior. These factors do not invalidate the solution itself, but they might make the “phenomenon presentation” less intuitive, requiring judgment based on the specific environment. This also illustrates from another angle that this article is not concerned with “presenting a completely consistent appearance in all environments,” but ratherkeeping system behavior aligned with design intent under the premise of clear architecture and node responsibilities。
Therefore, stopping here is not because “I could write more but don't want to,” but rather a conscious choice. This article does not attempt to make things “bigger,” but rather precisely solves a problem that has been clearly perceived and has begun to affect the user experience. If the blog architecture evolves again in the future and requires a unified notification system, then today's mu-plugin can naturally be removed or transformed into part of an event interception entry point. But that should be driven by demand, rather than a pre-assumed direction.
At least for now, this problem has been solved, and solved cleanly enough—at this point, we can safely bring this to a close.
Additionally, if your goal is simply to prevent nodes from sending emails as much as possible, without pursuing strict control and cross-node consistency, you do not necessarily have to use mu-plugin. A lighter compromise is to directly disable or uninstall SMTP plugins on WordPress, such as WP Mail SMTP. This will typically block the vast majority of email sending in most VPS or mainstream hosting environments. However, it is important to note that this approach has some potential impacts: 1. In a multi-node environment, the plugin lists between nodes will be inconsistent, which may lead to differences in processing logic across different nodes; 2. If a default mail service or system-level mail configuration exists in the node environment, emails may still be triggered. Therefore, this can only be considered an empirical, low-cost compromise solution, suitable for scenarios that pursue “good enough” rather than strict isolation, and do not care about plugin uniformity across multiple nodes.
Okok