Release Stuck Messages in the Postal Mail Server Queue
Clear stale locks and retry delays on Postal's queued_messages table so stuck outbound mail is picked up and delivered again.
On this page
Postal workers lock each outbound message while they process it. If a worker crashes or the server restarts mid-delivery, messages can stay locked or keep waiting on a long retry delay, so the queue stops draining. Releasing the locks puts those messages back in front of the workers.
Warning
Postal treats a lock older than queued_message_lock_stale_days (one day by default) as stale and removes the message without retrying it. Release stuck messages promptly, within that window, or they'll be dropped.
1. Check the Queue
Connect to Postal's main MariaDB database (named postal by default; see main_db in postal.yml) and look at what's waiting:
SELECT COUNT(*) AS queued,
SUM(locked_by IS NOT NULL) AS locked,
SUM(retry_after > NOW()) AS waiting_to_retry
FROM queued_messages;To see the oldest locks:
SELECT id, domain, locked_by, locked_at, retry_after, attempts
FROM queued_messages
WHERE locked_by IS NOT NULL
ORDER BY locked_at
LIMIT 20;2. Stop the Workers
Stop Postal's worker processes so no message is being processed when you clear its lock. Otherwise a message could be delivered twice. With the standard Docker-based install:
postal stop3. Release the Locks
Clear the lock and retry fields on every queued message:
UPDATE queued_messages
SET locked_by = NULL,
locked_at = NULL,
retry_after = NULL;To release only some messages, add a WHERE clause, for example WHERE domain = 'example.com' or WHERE locked_at < NOW() - INTERVAL 1 HOUR.
4. Start Postal Again
postal start
postal logs workerWatch the worker logs to confirm the messages are being sent. If they lock up again straight away, the underlying cause (DNS, the remote server refusing connections, or an IP blocklisting) is still there, and the message's delivery log in the Postal web interface usually shows it.
From the Rails Console
The same release can be done through Postal's application console instead of raw SQL:
postal consoleQueuedMessage.update_all(locked_by: nil, locked_at: nil, retry_after: nil)Sources
This article is in the public domain (CC0 1.0), code samples included. Use it however helps you.