Contact Form

The contact form on the public site (www.nortonshop.net) submits to admin.nortonshop.net/send-mail.php, which authenticates to Migadu’s SMTP server using PHPMailer and sends the message to the shop’s mailbox. PHP’s built-in mail() is not used — the PHP container has no local MTA, so outbound mail is relayed entirely through Migadu.

Mail flow

  1. Customer fills the contact form on the public site.
  2. Browser POSTs to https://admin.nortonshop.net/send-mail.php over HTTPS (CORS allows www.nortonshop.net as an origin).
  3. PHP validates input (captcha, honeypot, rate limit, file type) then hands the message to PHPMailer.
  4. PHPMailer opens an authenticated TLS connection to smtp.migadu.com:465, logs in as info@nortonshop.net, and submits the message.
  5. Migadu delivers the email to the info@nortonshop.net mailbox (same address on both ends — the customer’s email is set as Reply-To, so hitting reply in Mail.app goes to the customer).

PHPMailer location

Three source files are vendored at admin/lib/PHPMailer/, committed to the repo so they deploy via git pull:

Pinned to a release tag (currently v6.9.3). To upgrade, download fresh copies from https://github.com/PHPMailer/PHPMailer/raw/<tag>/src/ and commit.

Environment variables (docker-compose.yml)

The php service in /opt/server-stack/docker-compose.yml passes SMTP credentials to send-mail.php:

environment:
  CONTACT_TO:   info@nortonshop.net
  CONTACT_FROM: info@nortonshop.net
  SMTP_HOST:    smtp.migadu.com
  SMTP_PORT:    "465"
  SMTP_SECURE:  ssl
  SMTP_USER:    info@nortonshop.net
  SMTP_PASS:    "${SMTP_PASS}"

${SMTP_PASS} is substituted at container start from /opt/server-stack/.env:

SMTP_PASS=the-migadu-mailbox-password
If the password contains a $ character, escape it as $$ in .env — Docker Compose treats $ as variable substitution, and each $$ collapses to a single $ when passed into the container. After editing .env, run docker compose up -d php and verify with docker compose exec php env | grep SMTP_PASS.
/opt/server-stack/ is not a git repository, so .env is safe there. Do not commit .env to the site repo.

Built-in protections

Changing SMTP provider

To switch from Migadu to any other SMTP provider (Mailjet, Fastmail, Brevo, etc.): update the five SMTP_* vars in docker-compose.yml, change the password in .env, and run docker compose up -d php. No code changes required. For providers that use STARTTLS on port 587, set SMTP_PORT: "587" and SMTP_SECURE: tls.

Diagnosing delivery failures

docker compose logs php --since=5m | grep -i 'contact\|smtp\|error'

PHPMailer errors are written to PHP's error log prefixed with Contact form SMTP error:. The most common causes are wrong password (Migadu returns 535 Authentication failed), missing $$ escaping in .env (blank password), or Migadu rate limits (10 outbound/day on the Micro tier).

Back to top