hostdoc — offline cPanel/WHM/WHMCS support brain

← all runbooks

---
title: Website is not sending email
panel: cPanel / WHM
symptoms:
  - mail is not arriving
  - mail stuck in the queue
  - no bounce message
  - website forms do not send
  - contact form does not send email
  - the site is not sending mail
  - no emails are sent from the website
  - smtp mail is not going out
  - mail is stuck in the queue
---

# Website is not sending email

## 1. Split "not sending" into two different faults

**Why:** the customer uses one phrase for two faults that need opposite
fixes. If the mail never left the server, the problem is the site or the
account. If it left and was refused, the problem is the records or the
receiving side. Every later step depends on which one this is, so split
them before you change anything.

**In cPanel:** Email > Mail Troubleshooter. Enter the address and submit.
It traces the route from your server to the destination and shows the
point where it stopped.

**In the terminal:** `exim -bpc` gives the number of messages sitting in
the queue. A number that keeps climbing means the server is not
delivering, not that the site is broken.

**Care:** this only reads. Nothing changes.

- https://docs.cpanel.net/whm/email/mail-troubleshooter/

## 2. Read the queue, then read the delivery report

**Why:** the delivery report carries the reason code, and it is the most
useful thing to read before changing anything. It says whether the
receiving server refused the message, deferred it, or never saw it. Each
of those has a different fix and the report tells you which one you have.

**In WHM:** Email > Mail Queue Manager for what is waiting, then Email >
Mail Delivery Reports for what happened to what already went out.

**In the terminal:** `grep -i <domain> /var/log/exim_mainlog`

**Care:** this only reads.

- https://docs.cpanel.net/whm/email/mail-queue-manager/
- https://docs.cpanel.net/whm/email/mail-delivery-reports/

## 3. Check the domain's mail routing

**Why:** a domain with a routing rule set to discard, or a forwarder
pointing at an address that bounces, swallows mail with no error shown to
the site owner. The form says "sent" and nothing arrives. This one is
worth checking early because the customer can see no trace of it.

**In cPanel:** Email > Email Routing for the domain's rules.

**In WHM:** DNS Functions > Email Routing Configuration.

**In the terminal:** `cat /var/cpanel/userdata/<user>/main` and look for
the routing and forwarder blocks for the domain.

**Care:** this only reads. A routing rule you change sends mail somewhere
else, so write down what it was before you touch it.

## 4. Check the SPF and DKIM records

**Why:** if another server sends on the domain's behalf and SPF does not
list it, that mail gets rejected or pushed to spam. Missing or broken DKIM
is the usual reason a legitimate message lands in spam rather than being
refused outright.

**In cPanel:** Email > Email Deliverability. Manage the Domain shows the
current SPF and DKIM records next to what the system recommends.

**In WHM:** Email > Email Deliverability > Deliverability by Domain.

**In the terminal:** `dig +short TXT <domain>` for the SPF record, and
`dig +short TXT <selector>._domainkey.<domain>` for DKIM.

**Care:** SPF is easy to break. A record with too many DNS lookups fails
silently and the whole record gets ignored, which is worse than having no
record at all. Change one thing, then re-check it.

- https://docs.cpanel.net/whm/dns-functions/enable-dkim-spf-globally/
- https://docs.cpanel.net/whm/scripts/the-spf_installer-script/

## 5. Check whether the sender's reputation is the problem

**Why:** a server or an account that has been sending spam gets its IP
listed, and then legitimate mail from every other customer on that server
starts landing in spam as well. If the problem started suddenly and the
records look right, the reputation is the thing to check.

**In WHM:** Email > Mail Delivery Reports, read the deferral reasons
across the account rather than for one message.

**In the terminal:** `grep -i rejected /var/log/exim_rejectlog`

**Care:** this only reads.