The document describes how to make Exim (exim4) check in real time presence of Cyrus mailbox using exim's callouts. It was speciffically designed to support cyrus virtual domains.
As of version 4.34 exim does not implement callouts over unix socket so the solution uses LMTP over TCP.
It is one of those "simple when you know it" recipies :-)
This page is listed at Cyrus > External Links page of Cyrus Wiki.
Below please find list of changes required cyrus configuration:
Make cyrus wait for unauthenticated lmtp connections over TCP on local interface
In cyrus.conf add
SERVICES { ... lmtp cmd="lmtpd -a" listen="127.0.0.1:lmtp" prefork=0 }
Without "-a" lmtp requires authentication for LMTP over TCP.
If your /etc/services files does not define lmtp service (2003/tcp) then use 'listen="127.0.0.1:2003"'.
Below please find list of changes required in exim's configuration file:
Define cyrus_domains domainlist to list all virtual domains handled by your cyrus.
domainlist cyrus_domains = example.net : example.com : example.org
The best place is just before (or just after) "domainlist local_domains =" line.
Define cyrus_ltcp (cyrus local tcp) transport in transports section.
cyrus_ltcp: driver = smtp protocol = lmtp hosts = localhost allow_localhost
It will deliver messages to lmtp port at localhost using lmtp protocol
If your /etc/services files does not define lmtp service (2003/tcp) then add
port = 2003
Insert cyrus_vdom router as first routers section
cyrus_vdom: driver = accept domains = +cyrus_domains transport = cyrus_ltcp no_more
It will select cyrus_lmtp transport for all addresses in cyrus_domains domains.
Add checking validity of addresses in cyrus virtual domain in acl_check_rcpt section. I have added the lines just after "accept hosts = :" line [skipping tests for SMTP not over TCP/IP (local)].
# Reject "faked" sender addresses in cyrus domains deny sender_domains = +cyrus_domains message = Sender unknown/invalid !verify = sender/callout=defer_ok,5s
defer_ok makes exim accpet messages when cyrus in unavailable. 5s defines timeout for callout connection attempts.
# Accept valid (and reject invalid) recipient adresses in cyrus domains accept domains = +cyrus_domains endpass message = ${if match{$acl_verify_message}\ {\N(?m)^\d{3} (\d\.\d\.\d .{0,120})\Z\N} \ {IMAP said: $1}{Recipient unknown/invalid}} verify = recipient/callout=random,5s
Whenever Cyrus Imap "reject reply" matches the regular expression, it is passed in "RCPT TO:" by exim. You can customize format of the passed message to fit your tastes.
Use smtp over stdin/stdout for tests. Specify connecting host address (-oMa).
exim -oMa 127.0.0.1 -bs<<END HELO xxx MAIL FROM: no-such-mailbox@example.com RCPT TO: no-such-mailbox@example.com RCPT TO: existing-mailbox@example.com RSET MAIL FROM: existing-mailbox@example.com RCPT TO: no-such-mailbox@example.com RCPT TO: existing-mailbox@example.com QUIT