There are situations in which you may wish to run Postfix as a front end MTA, and place your Citadel server behind it as the final MDA for your domains. For example, you might run Postfix on a dedicated relay hub outside your firewall, and Citadel inside your firewall, and only allow SMTP between those two machines through the firewall. Or you might have some great new mail filtering plugin that only runs on Postfix.
So far you would have run into a major drawback: how would Postfix know, whether it should deliver a mail, or reject it due to being sent to a non existant user? These days, spammers tend to perform dictionary attacks, and use spoofed sender addresses. If Postfix accepts the mail, and then Citadel rejects it, Postfix will try to notify the sender that the message could not be delivered. In most cases, the sender is spoofed or nonexistent, which results in an Aide folder full of “double bounce” messages.
The combination of Postfix and Citadel offers an elegant solution to this problem. Postfix supports non local (unix users) delivery tables. You can do user lookup for example in a MySQL table, or Postgres, dbm, ldap and, since later versions of postfix (2.2 and later, earlier in patches, for example Debian sarge; search for dict_tcp.so) via a new type of TCP lookup. If you don't know how to find out the version of your postfix with your package management, try
postconf -v 2>/dev/null|grep '^mail_version'
postconf -m | grep tcp
should output tcp if your system has support for dict_tcp.
Citadel now offers support for the TCP lookup service. To configure it, follow these steps:
- Upgrade to latest Citadel and WebCit (6.84 and later).
- Configure Administration → Edit site-wide configuration → Network → Postfix TCP Dictionary Port to a port of your choice; for example lets say 777.
- Restart the Citadel system to make it open the port using “/etc/init.d/restart” as root on your shell.
- To check back if it worked out, do “netstat -lnp” if citserver provides your port.
Now for Postfix. Check if /etc/postfix/dynamicmaps.cf contains something like:
tcp /usr/lib/postfix/dict_tcp.so dict_tcp_open
As we're trying to use LMTP transport, postfix mustn't do that in a chroot (it won't find citadels lmtp socket there), so your /etc/postfix/master.cf should contain a line like that:
lmtp unix - - n - - lmtp
note that the 'n' in the 5th column is essential!
Take the main.cf from the last box(or add the matching lines to your config), replace 777 with your port and sample.yourcitadel.org with your hostname. Make Postfix reload its config using “postfix reload” as root on your shell. Use “tail -f /var/log/mail” or “tail -f /var/log/mail/current” depending on your syslog facility to check the effort:
Aug 27 23:29:00 [postfix/postfix-script] refreshing the Postfix mail system Aug 27 23:29:00 [postfix/master] reload configuration
or if you do “postfix stop; postfix start” :
Aug 28 22:32:30 [postfix/postfix-script] stopping the Postfix mail system Aug 28 22:32:30 [postfix/master] terminating on signal 15 Aug 28 22:32:33 [postfix/postfix-script] starting the Postfix mail system Aug 28 22:32:33 [postfix/master] daemon started -- version 2.1.5
Aug 29 00:34:41 [postfix/smtpd] connect from yourtestmta.org[testmta ip] Aug 29 00:34:41 [postfix/smtpd] E69F29ED1: client=yourtestmta.org[testmta ip] Aug 29 00:34:41 [postfix/cleanup] E69F29ED1: message-id=
Aug 29 00:34:32 [citadel] : get email@example.com Aug 29 00:34:32 [citadel] sending 200 OK firstname.lastname@example.org
and the usual delivery and sorting afterwards.
(lines wrapped are indended)
Aug 29 00:33:40 [postfix/smtpd] connect from unknown[testmta ip] Aug 29 00:33:41 [postfix/smtpd] NOQUEUE: reject: RCPT from unknown[testmta ip]: 550 <NonexistantUser@sample.citadel.org>: Recipient address rejected: User unknown in local recipient table; from=<email@example.com> to=<NonexistantUser@sample.citadel.org> proto=SMTP helo=<yourtestmta.org> Aug 29 00:33:41 [postfix/smtpd] disconnect from unknown[testmta ip]
- Citadel: If you're suspecting citadel not to do the right thing, you can try to talk to it's dict_tcp port by hand, it's quiet simple. Lets go with the names from above:
# telnet 127.0.0.1 777 Trying 127.0.0.1... Connected to 127.0.0.1 Escape character is '^]'. get firstname.lastname@example.org Answer: 200 OK email@example.com get NonexistantUser@sample.citadel.org Answer: 500 REJECT noone here by that name.
- Citadel: force Citserver to rebuild his userdatabase (in case you suspect that Aliases you added aren't working; this may happen if you add new domains)
Here's the sample
to follow. Remember to substitute “777” with whatever port number you are using.
# See /usr/share/postfix/main.cf.dist # for a commented, more complete version # you should use a greeting apropriate to your distro: smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) biff = no # appending .domain is the MUA's job. append_dot_mydomain = no # Uncomment the next line to generate "delayed mail" warnings #delay_warning_time = 4h myhostname = sample.citadel.org myorigin = sample.citadel.org # Debian puts this by default to: # myorigin = /etc/mailname mydestination = mail.sample.citadel.org, sample.citadel.org #relayhost = mynetworks = 127.0.0.0/8 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all # ------------------------------------------------ # checking rules. # get rid of anything useless as early as possible. # * stage one: check if the user is there. # * stage two: check the source. is its helo valid? else buye. # * stage three: check the sender etc. # * stage four: check the open relay Database. # hosts registered here won't be accepted. # * stage five: check the content by regex. # won't accept Windows executables of any kind. # * stage six: Do virus checking. # reject some more extensions. # * stage seven: deliver it to citadel via local transport # make it bite harder if wanted. #unknown_local_recipient_reject_code = 550 #unknown_address_reject_code = 550 #unknown_client_reject_code = 550 #unknown_relay_recipient_reject_code = 550 #unknown_virtual_alias_reject_code = 550 #unknown_virtual_mailbox_reject_code = 550 #unknown_address_reject_code = 550 #unknown_client_reject_code = 550 #unknown_hostname_reject_code = 550 #unverified_recipient_reject_code = 550 #unverified_sender_reject_code = 550 #unverified_recipient_reject_code = 550 # # nope. don't wanna know. bounce_notice_recipient = # replace 127.0.0.1 with the ip of your citadel server, # and 777 with the port you made it open its dict-tcp server # in doubt check with netstat -lnp # telnet ip port # smtpd_recipient_restrictions = reject_unauth_destination, reject_unauth_pipelining, reject_non_fqdn_sender, reject_non_fqdn_hostname, reject_invalid_hostname, reject_unknown_recipient_domain, reject_unknown_sender_domain, reject_unknown_hostname, reject_rbl_client sbl-xbl.spamhaus.org, reject_rbl_client bl.spamcop.net, reject_rbl_client dnsbl.njabl.org, reject_rbl_client dnsbl.sorbs.net, reject_rbl_client l2.spews.dnsbl.sorbs.net, reject_rhsbl_client rhsbl.sorbs.net, reject_rhsbl_client bogusmx.rfc-ignorant.org, reject_rhsbl_sender rhsbl.sorbs.net, reject_rhsbl_sender bogusmx.rfc-ignorant.org, reject_rhsbl_sender dsn.rfc-ignorant.org, tcp:127.0.0.1:777, reject local_recipient_maps = tcp:127.0.0.1:777 # if we deliver to citadel via lmtp, # do it for example like that: # Postfix version 2.1 and older: #local_transport = lmtp:unix:/var/run/citadel/lmtp.socket mailbox_transport = lmtp:unix:/var/run/citadel/lmtp.socket # check the output of # netstat -lnp # for your lmtp.sock location.
You can find more articles about configuring postfix at many places on the web.