OpenCart admins discover the deliverability problem the same way everyone else does — a customer messages asking for their order details, and you realise the confirmation never arrived. Except OpenCart has one extra quirk: the default configuration in System → Settings → Mail is set to "Mail" (PHP mail()) rather than SMTP. Most admins never change it.
The fix is configurable inside OpenCart itself — no plugins required for basic SMTP — but the UI is unhelpful, and the DNS side of the equation is ignored by every OpenCart tutorial that shows only the admin panel.
Change Mail Engine to SMTP in OpenCart admin. Point at an authenticated relay. Then publish SPF, DKIM, DMARC, and a return-path CNAME for the relay. That is the whole fix.
Why PHP mail() fails on OpenCart hosting
- Shared IP reputation: OpenCart runs on LAMP. LAMP runs on shared hosts. Shared hosts share IPs. Your order confirmation competes with every other tenant's newsletter.
- No DKIM: PHP mail() does not sign. The few hosts with cPanel DKIM at the MTA layer sign with the wrong selector and wrong domain, which is worse than not signing.
- Envelope mismatch: the store's
emailsetting in admin controls the header From only. The envelope MAIL FROM is whatever the local sendmail decides, usually the cPanel username. - No visibility: PHP mail() returns true or false. If false, OpenCart logs a generic error. If true, the message could still be dropped silently downstream.
Switch OpenCart to SMTP
System → Settings → Store → Mail tab. Change Mail Engine from "Mail" to "SMTP". Then fill in the relay details.
SMTP settings for common relays
# Brevo (ex-Sendinblue) — free 300/day
SMTP Hostname: smtp-relay.brevo.com
SMTP Username: your_brevo_login@yourstore.com
SMTP Password: SMTP key from Brevo dashboard (not your password)
SMTP Port: 587
SMTP Security: TLS
# SendGrid
SMTP Hostname: smtp.sendgrid.net
SMTP Username: apikey
SMTP Password: full SG API key
SMTP Port: 587
SMTP Security: TLS
# Amazon SES (eu-west-1 example)
SMTP Hostname: email-smtp.eu-west-1.amazonaws.com
SMTP Username: SES SMTP credentials username
SMTP Password: SES SMTP credentials password
SMTP Port: 587
SMTP Security: TLSOpenCart sets SMTP Timeout to 5 seconds by default. On transactional paths that is fine. If the relay occasionally takes longer to handshake, bump to 15. Longer than that and you are papering over a relay problem.
DNS: SPF, DKIM, DMARC, return-path
OpenCart's admin panel does not show you what DNS records to add. The relay dashboard does. Take those records and publish them at your domain registrar.
; example for Brevo, apex = yourstore.com
yourstore.com. TXT "v=spf1 include:spf.brevo.com ~all"
mail._domainkey.yourstore.com TXT "k=rsa; p=<brevo_provided_key>"
_dmarc.yourstore.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourstore.com"
; return-path alignment (Brevo custom envelope)
bounce.yourstore.com CNAME ob.sendibm3.com.Test every order status
OpenCart fires a different template for each order status. Testing only "order placed" misses that "complete" might have broken HTML or a stale attachment path.
- Run a real test order with a seed mailbox as customer email.
- Move the order through Pending → Processing → Complete, checking each status email.
- Trigger a password reset from the customer account page.
- Trigger a return request.
Template hygiene
- OpenCart templates live at
catalog/view/theme/<theme>/template/mail/. Most themes ship a heavy HTML layout — strip promotional blocks. - Ensure a
text/plainalternative exists. OpenCart generates one automatically if you provide plain-text template siblings, not otherwise. - Logo image under 10 KB, no banners, no product-recommendation grids in confirmation emails.
- Reply-to set to a monitored mailbox, not a no-reply address.
After every template change or plugin install, run a seed test across 20+ providers. Catch Promotions-tab drift and DMARC alignment breaks before customers do.