You fire off an email from a PHP script, a contact form, or an SMTP client, and instead of the mail going out, it bounces back immediately with something like 550 5.7.1 Relay access denied. No delay, no queueing — it just refuses the message on the spot. This is one of the more confusing cPanel mail errors because it looks like a bounce, but it's actually your own mail server (or someone else's) refusing to forward the message in the first place.

Symptom: What "Relay Access Denied" Actually Looks Like

You'll usually see one of these, depending on where the attempt happens:

  • A PHP script using mail() or PHPMailer fails with an SMTP error containing Relay access denied or relaying denied.
  • An email client (Outlook, Thunderbird) throws a send error with a 550 or 554 code and the word "relay" in the description.
  • A WordPress contact form plugin logs a failed send with the same phrase in its SMTP debug log.
  • cPanel's Email Deliverability or Track Delivery tool shows the message as rejected before it ever left the server queue.

The key giveaway: this isn't a bounce from the recipient's server. It's your own mail server (Exim, in cPanel's case) — or, less often, an upstream relay like your ISP or a third-party SMTP provider — refusing to accept the message for delivery at all.

Cause: Why Exim Is Blocking the Relay

Mail servers relay email on behalf of two kinds of senders: people it can positively identify as authorized (through authentication or a trusted IP), and nobody else. "Relay access denied" means Exim couldn't put your attempt into either bucket. In practice, that comes down to one of these:

CauseHow It Happens
No SMTP authenticationA script or client connects to port 25/587 and tries to send without logging in with a valid mailbox username and password.
Wrong "From" domainYou're authenticated as one mailbox but the message's From address uses a domain the server doesn't host or isn't authorized for.
Connecting from the wrong IPA PHP app on a different server (or a local dev machine) tries to relay through your cPanel server's IP, which only trusts local connections or authenticated ones.
PHP mail() with no envelope sender matchPHP's built-in mail() function submits locally as the web server user, and Exim's ACLs reject it if the domain in the header doesn't match a hosted domain.
Restrict Outgoing Email is activeWHM's "Restrict Outgoing Email" feature forces all mail to go through cPanel's mail service under the account's own domains — anything else gets relay-denied.
Recipient's server rejects your relayLess common: you're sending correctly, but the destination mail server itself won't relay/accept from your IP (this shows up as a bounce from their side, not yours).

The most frequent one by far, especially after a migration or a new WordPress install, is the first: something is trying to send mail without authenticating, and Exim (correctly) refuses to be an open relay for it.

Fix: Step by Step

1. Check the exact error in the mail log

SSH in and tail the Exim main log — it tells you exactly which rule fired and why:

tail -f /var/log/exim_mainlog

Look for a line near your failed send with T=remote_smtp or an ACL rejection referencing relay_from_hosts or authenticated_id. That confirms whether the block happened at your server or the recipient's.

2. Fix WordPress and PHP contact forms first

If the failure is coming from a WordPress site or PHP script, the fix almost always isn't a server change — it's switching from PHP's mail() to authenticated SMTP:

  • Install a plugin like WP Mail SMTP or Fluent SMTP.
  • Configure it with an actual cPanel mailbox: SMTP host mail.yourdomain.com, port 587 (STARTTLS) or 465 (SSL), and the mailbox's real username and password.
  • Send a test email from the plugin's built-in test tool and confirm it authenticates instead of relaying anonymously.

This alone resolves the vast majority of "relay access denied" tickets, because it stops the script from trying to relay unauthenticated in the first place.

3. Fix a script or app that must use SMTP directly

If you're calling an SMTP library (PHPMailer, Nodemailer, Python's smtplib) directly, make sure you're actually authenticating rather than just connecting:

$mail->isSMTP();
$mail->Host = 'mail.yourdomain.com';
$mail->SMTPAuth = true;
$mail->Username = 'sender@yourdomain.com';
$mail->Password = 'the-mailbox-password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

A common mistake is leaving SMTPAuth false or pointing Host at localhost without credentials — that's an unauthenticated relay attempt from Exim's point of view every time.

4. Check whether the From domain matches an authenticated mailbox

If you authenticate as noreply@siteA.com but send with a From header of info@siteB.com, and siteB.com isn't hosted on the same cPanel account, Exim can deny the relay depending on your server's ACL configuration. Either send from a mailbox on the same domain, or set up the sending domain properly on the account with its own DNS and mailbox.

5. Check WHM's Restrict Outgoing Email setting

If you have WHM/root access, go to WHM > Email > Manage Mail Server Domain Forwarding > Restrict Outgoing Email (or search "Outgoing" in WHM). If it's enabled, any script that tries to send using a domain not on the account, or that bypasses cPanel's own mail delivery path, gets blocked. This is a security feature, not a bug — the fix is to make the sending domain and mailbox line up correctly, not to disable the restriction.

6. Confirm your app server's IP is allowed to relay

If a separate application server (not the cPanel box itself) needs to relay through your mail server, it must authenticate — cPanel's Exim doesn't grant relay by IP alone for anything outside localhost and hosted domains. Set up SMTP authentication on that app server the same way as step 3, rather than trying to add it as a trusted relay host.

Prevention

  • Standardize every app, script, and plugin on authenticated SMTP over port 587 or 465 instead of PHP's bare mail() function.
  • Keep the From address on any transactional email matching a real mailbox on a domain hosted in the same cPanel account.
  • After a migration, re-check every WordPress site's SMTP plugin settings — credentials and hostnames from the old server don't carry over automatically.
  • Watch /var/log/exim_mainlog after any change to mail-sending code; a quiet relay-deny in the log now saves a "why didn't my form email arrive" ticket later.
  • If you use a third-party transactional service (SendGrid, Mailgun, Amazon SES), route through their SMTP relay with API-key authentication instead of your cPanel server — it sidesteps this whole class of error for high-volume sending.

Frequently Asked Questions

Is "Relay Access Denied" the same as being blacklisted?

No. A blacklist rejection happens on the recipient's server, usually with wording about reputation or spam. "Relay access denied" is your own mail server (or an intermediate one) refusing to even attempt delivery because the sender wasn't authenticated or authorized — it happens before the message ever reaches the recipient's server.

Why does this only happen for some emails and not others?

It usually depends on which script or mailbox sent the message. A properly configured SMTP plugin with valid credentials will go through fine, while a different plugin or a custom PHP script using bare mail() on the same site can get denied, because Exim evaluates each connection and its authentication state independently.

Can I just add my server's IP as a trusted relay to make this go away?

You technically can via Exim's ACL configuration, but it's not recommended — it turns your mail server into an open (or semi-open) relay, which spammers actively scan for and abuse, and can get your server's IP blacklisted within hours. Fixing authentication on the sending side is safer and just as fast.

I fixed the SMTP settings but I'm still getting the error. What now?

Clear any cached mail settings in the plugin or app, confirm the mailbox password hasn't changed, and double check you're pointing at mail.yourdomain.com rather than a stale IP or an old server's hostname from before a migration. Then re-check /var/log/exim_mainlog for the exact rejection reason on the retry — it will confirm whether authentication succeeded this time.

Does this affect webmail or only scripts and apps?

Webmail (Roundcube/Horde) and normal mail clients configured with the mailbox's real password rarely hit this, because they authenticate properly by design. It's almost always automated senders — PHP scripts, contact forms, cron jobs, or misconfigured app servers — that attempt to relay without valid credentials.