Why a WordPress site starts sending spam
Every WordPress install has a working mail-sending function — wp_mail(), which under the hood typically calls PHP's built-in mail() unless an SMTP plugin overrides it. That function exists to send password resets, order confirmations, and contact-form notifications. It's also a genuinely popular thing for an attacker to hijack once they've gotten any level of code execution on your server, because it turns a compromised site into a disposable spam-sending machine: no need to set up their own mail infrastructure, and your domain's existing reputation (however small) does some of the work of getting past spam filters, at least until it gets burned.
This is a distinct monetization path from the redirect and phishing patterns covered elsewhere on this site — the goal here usually isn't to trick your own visitors, it's to use your server as free, disposable sending capacity for spam aimed at other people entirely. You may never see the actual emails; the first sign is often your host's abuse team emailing you, or a sudden delivery failure on your own legitimate site mail.
First: confirm it's actually your server, not spoofing
This is the single most common point of confusion, and it's worth getting right before you do anything else. Two very different things can produce "someone got an email that looks like it's from my domain":
- Spoofing — someone else, using their own mail infrastructure entirely, fakes your domain in the visible "From" header. Your server was never involved. This is extremely common and doesn't mean you've been compromised.
- An actually compromised server — mail is genuinely originating from your hosting account, using your site's real sending mechanism.
SPF and DKIM are the two DNS-based checks that tell these apart. SPF publishes which mail servers are authorized to send for your domain; DKIM attaches a cryptographic signature that proves a message's headers and body weren't altered in transit. A spoofed message sent from unrelated infrastructure will typically fail SPF and DKIM checks at the receiving end, because the sender never had access to your actual authorized servers or signing key. Mail sent from your own genuinely compromised hosting account, by contrast, usually passes both — because it's going out through infrastructure that's legitimately authorized to send for your domain, which is exactly why blacklisting and reputation damage can follow.
In short: if you're getting bounce-backs or complaints about mail you never sent, don't assume the worst immediately — check whether your server is actually the origin before you start pulling apart your WordPress install.
Checking what's actually being sent
The fastest way to confirm real outbound mail from your own site is to look at what WordPress itself is sending, rather than guessing. The WP Mail Logging plugin — free, and the most widely used tool for this specifically — hooks into wp_mail() and records every message your site sends: recipient, subject, headers, and body, with no configuration required after activation. If your site is genuinely compromised, this log usually makes it obvious fast: a flood of messages to addresses you don't recognize, sent through wp_mail() at times and volumes nothing on your real site would produce.
Alongside the plugin, check your host's own mail logs if they expose them (most shared and managed hosts do, at least a summary) — hosts often catch abusive volume before you do, since it's their outbound reputation on the line too.
Where the injection usually lives
If the logs confirm real spam is going out through your own site, the actual injected code is typically in one of a few places:
- A vulnerable contact-form or mail-sending plugin — an unpatched plugin that accepts and relays arbitrary mail content is a common entry point, especially on sites running outdated versions.
- An injected mailer script dropped directly into the theme or uploads directory, calling
mail()orwp_mail()independently of any legitimate plugin. - A rogue cron job scheduled to fire the spam-sending routine on a recurring basis — which is also why disabling mail temporarily doesn't fix anything; the scheduled task just waits and fires again.
The WP Mail Logging entries themselves are a real clue here: unusual message content, subjects, or a code path you don't recognize sending them, point at which of these it actually is.
Fixing it — not just disabling mail
Turning off outgoing mail entirely, or blocking port 25 at the server level, stops the immediate symptom but leaves the actual injected code sitting on your site, waiting to resume (or move on to something worse) the moment mail is re-enabled. The real fix is:
- Find and remove the injected code itself — not just the symptom. This is the same process as any other WordPress malware cleanup: compare core and plugin files against known-good copies, and treat any unrecognized script in
wp-contentor elsewhere as suspect. - Update or remove the vulnerable plugin that gave the attacker the entry point in the first place, if the logs point at one.
- Check for a persistence mechanism like a scheduled task, and remove it — not just the mailer script itself.
- Rotate credentials — WordPress admin, hosting/FTP, and database — since the same compromise that planted a mailer script may have exposed more than just mail-sending.
If you're not confident you've found every injected file, treat it as a full compromise rather than a one-off mail issue — see our full malware removal guide for the complete process, in the right order.
After the cleanup: checking your sender reputation
Once the injected code is actually gone, check whether your domain or server IP ended up on a blacklist as a result — this is a separate step from the cleanup itself, and it's the part that actually affects whether your legitimate email starts arriving again. MXToolbox's blacklist check is a free, widely used tool that queries dozens of DNS-based blacklists (DNSBLs) against your domain or IP in a single lookup, and shows exactly which ones have listed you. Most blacklist operators publish their own delisting process once the underlying issue is fixed — patience matters here, since delisting isn't instant even after you've genuinely cleaned up.
Catch the injected mailer script or rogue cron job behind this before your domain gets blacklisted.
Install free →