Corndog for Craft CMS

Troubleshooting

Nothing is being logged

In order of likelihood:

  1. Logging is switched off. The log screen says so at the top when it is.
  2. The email does not go through Craft's mailer. Corndog hooks Craft::$app->getMailer(). Something calling PHP's mail(), or an SMTP library of its own, or an API client for a delivery service, never reaches that mailer — and never reaches Craft either. Nothing inside Craft can see those; they are not a gap Corndog can close.
  3. The send is inside a database transaction that rolled back. The log row is written in the same transaction as the work that triggered the email, so if that work is rolled back the row goes with it. The email may still have been sent.
  4. The plugin is installed but the send happened in another process that has not finished. Rows are written at the start of the send and updated at the end; a worker killed mid-send leaves a row marked Unfinished, not a missing one.

A message says Failed but gives no reason

Corndog reads the reason by sitting between Craft's mailer and its transport. If it could not install itself there — an unusual mailer, a transport swapped by another plugin — the row still reports the failure, but the text comes from Craft rather than from the mail server. The real error is in Craft's own logs (storage/logs/), which is where Craft puts it.

A message is stuck on Unfinished

That row is a send that started and never came back: a fatal error, a timeout, a killed queue worker. Corndog marks any row still open when the process ends as failed, so a permanent Unfinished means the process did not end normally either. Look for the crash, not for the email.

The log is full of one plugin's emails

That is the log doing its job — but if a plugin is sending far more than you expected, the Sender filter narrows the list to it and the message screen tells you which class and which queue job is responsible.

The table is getting big

Bodies are the biggest thing in it by an order of magnitude. In order:

  1. Lower Most rows to keep. This is the setting that actually bounds the table.
  2. Lower Longest body to store.
  3. Turn off Store the HTML body.

Then php craft corndog/email/prune to apply it now rather than waiting for garbage collection. Pruning deletes rows, and deleting a row deletes its tracking events too.

Tracking counts nothing

  • Open tracking needs an HTML body. A plain-text message cannot carry a pixel, and Corndog will not add an HTML part to a message to measure it. Those messages get no tracking key at all.
  • Mail clients block images. Apple Mail's privacy protection loads them from a proxy, Gmail caches them, others never load them. Zero opens is not evidence that nobody read it.
  • The pixel URL has to be reachable. It is a front-end URL on the site the message belongs to. If your site is behind HTTP auth, or the message was sent from a console command on a host whose site URL is localhost, the recipient's mail client cannot load it.

Links are not being rewritten

Check, in this order: trackClicks is on; the link is http or https; it does not match ignoredLinkPatterns (*unsubscribe* and */actions/* are excluded by default); it does not carry data-corndog-ignore; and it does not still contain an unrendered {{ … }}, which Corndog leaves alone rather than signing a URL that was never finished.

A tracked link goes to the home page

That is the signature check refusing a target it cannot verify. It happens when the query string has been mangled in transit — some scanners rewrite links — or when the site's security key has changed since the message was sent. Old tracked links stop working when the key rotates, by design.

A resend is refused

Two reasons, both deliberate: the message has no stored body, because body logging was off when it was sent; or there is nobody to send it to after your edits. Corndog would rather refuse than send a blank email to a customer.

Emails send fine but the origin says Unknown

Corndog reads the call stack at the moment of the send. A send from a plain PHP script, from eval'd code, or from a closure with nothing above it that belongs to a plugin, has no frame worth naming — so it says so rather than guessing. The transport, the headers and the body are all still there.

Alerts are not arriving

The alert is sent through the same mailer that just failed. If the transport itself is down, the alert cannot get out either — check the log: the alert attempt is in there, failed, like everything else. Also check the threshold (three failures inside sixty minutes by default) and the cooldown, which suppresses a second alert for an hour.

Removing it

Uninstalling drops both tables and takes the whole log with it. Nothing else in the site changes — Corndog never modifies how mail is composed or where it goes, beyond the delivery overrides you switched on yourself, and those stop the moment the plugin does.