Skillett.com

A couple of days ago I had reason to get really hands on, down and dirty with Exim my MTA.

The basic problem being that for some absolutely unknown reason a couple of clients messages were stuck on the queue and not able to be delivered to me. They were failing with some reason about broken pipes:

2005-12-14 10:18:17 <MSG ID> <someone@email.com>: virtual_sa_userdelivery transport output: An error was detected while processing a file of BSMTP input.
2005-12-14 10:18:17 <MSG ID> == <someone@email.com> R=virtual_sa_user T=virtual_sa_userdelivery defer (0): transport filter timeout while writing to pipe

Try as I might I couldn’t get them off the queue – later whilst trying to uninstall clamav/Mailscanner (which seemed to be the problem) a reboot of the server was done and they all popped through!!!

However, all of this did cause me to start messing with Exim and find all of the following useful commands and info(courtesy of BradTheMad.org and Ben Duncan’s Article):

The Exim SMTP Mail Server Exim: The Mail Transfer Agent
The Exim SMTP Mail Server: Official Guide for Release 4 Exim: The Mail Transfer Agent: The Mail Transport Agent

Notes

msg id’s and spool
The message-IDs are of the form: XXXXXX-YYYYYY-ZZ. Commands use these message-ids.

There are three files for each message in the spool directory (make sure you get all of the little sods if you’re messing with these files by hand).

logging information for each message is stored here:
/var/spool/exim/msglog

Files in /var/spool/exim/input are named after the message-id, plus a suffix denoting whether it is the envelope header (-H) or message data (-D).

Don’t expect everything to always appear directly in the top /var/spool/exim/input or /var/spool/exim/msglog directories; any searches or greps will need to be recursive.

WARNING:See if there is a proper way to do what you’re doing before working directly on the spool files.

Queue information

Number of messages in the queue:
root@localhost# exim -bpc

Print a listing of the messages in the queue (time queued, size, message-id, sender, recipient):
root@localhost# exim -bp

Print a summary of messages in the queue (count, volume, oldest, newest, domain, and totals):
root@localhost# exim -bp | exiqsumm

Generate and display Exim stats from a logfile:
root@localhost# eximstats /path/to/exim_mainlog

Same as above, with less verbose output:
root@localhost# eximstats -ne -nr -nt /path/to/exim_mainlog

Same as above, for one particular day:
root@localhost# fgrep YYYY-MM-DD /path/to/exim_mainlog | eximstats

Print what Exim is doing right now:
root@localhost# exiwhat

Search the queue for messages from a specific sender:
root@localhost# exiqgrep -f [luser]@domain

Search the queue for messages for a specific recipient/domain:
root@localhost# exiqgrep -r [luser]@domain

Print just the message-id as a result of one of the above two searches:
root@localhost# exiqgrep -i [ -r | -f ] ...

Print just the message-id of the entire queue:
root@localhost# exiqgrep -i

Managing the queue

Start a queue run:
root@localhost# exim -q -v

Start a queue run for just local deliveries:
root@localhost# exim -ql -v

Remove a message from the queue:
root@localhost# exim -Mrm [ ... ]

Freeze a message:
root@localhost# exim -Mf [ ... ]

Thaw a message:
root@localhost# exim -Mt [ ... ]

Deliver a specific message:
root@localhost# exim -M [ ... ]

Force a message to fail and bounce:
root@localhost# exim -Mg [ ... ]

View a message’s headers:
root@localhost# exim -Mvh

View a message’s body:
root@localhost# exim -Mvb

View a message’s logs:
root@localhost# exim -Mvl

Adding a recipient to a message:
root@localhost# exim -Mar message_id email@domain.dom
will add email@domain.dom as a recipient of the message and send a copy to that address.

There is no way to actually delete a recipient, but Exim can be told to pretend that delivery for a recipient has been completed. To mark one of the intended recipients as delivered:
root@localhost# exim -Mmd message_id email@domain.dom
Will mark the address email@domain.dom as delivered and stop delivery attempts to that address, whereas:
root@localhost# exim -Mmad message_id
Will mark all recipients as delivered.

You can also edit the body of the message:
exim -Meb message_id
This runs vi on a copy of the spool file with a lock. No delivery attempts are made while the file is locked. There a few caveats on this and you should look up more info on it before you attempt it.

My Problem

In my case I needed to do something quite drastic using the last few notes above from Ben
Because the messages wouldn’t deliver locally I needed to get them to deliver off somewhere else (in my case – my gmail account):


root@localhost# exim -Mf message_id
(Freeze the message)
root@localhost# exim -Mar message_id mygmailaccount@gmail.com
(Add my gmail account as a recipient)
root@localhost# exim -Mmd message_id email@localdomain.com
(Mark the local domain as delivered - because we can't actually delete it)
root@localhost# exim -Mt message_id
(Thaw the message to run it on the next queue run)
or,

root@localhost# exim -M message_id
(Deliver message immediately)

Fix SMTP-Auth for Pine

If pine can’t use SMTP authentication on an Exim host and just returns an “unable to authenticate” message without even asking for a password, add the following line to exim.conf:

begin authenticators

fixed_plain:
driver = plaintext
public_name = PLAIN
server_condition = “${perl{checkuserpass}{$1}{$2}{$3}}”
server_set_id = $2
> server_prompts = :

Disable Attachment Blocking

To disable the executable-attachment blocking that many Cpanel servers do by default but don’t provide any controls for on a per-domain basis, add the following block to the beginning of the /etc/antivirus.exim file:

if $header_to: matches “example\.com|example2\.com”
then
finish
endif

Bonus!

To delete all queued messages containing a certain string in the body:
root@localhost# exim -Mrm `grep -lr 'a certain string' /var/spool/exim/input/ | \
sed -e 's/^.*\/\([a-zA-Z0-9-]*\)-[DH]$/\1/g'`

If you have to feed many, many message-ids (like more than a thousand) to an exim command, you may exhaust the limit of your shell’s command line arguments. In that case, use head or tail on a listing of message-ids to run only a limited number of them at once.

For example, if joe@example.com bombed you with 8,000 messages and you want to get rid of them all, remove 1,000 at a time:
root@localhost# exim -Mrm `exiqgrep -i -f '' | head -1000`
root@localhost# !!

[…etc., 8 times total…]

Thanks to Brad and Ben who saved my bacon the other day!

If you found this post useful, why not buy me a coffee or a beer (depending on the time of day obviously!):
[donate]