2

we have a larger community portal which became bigger and bigger over the years but also has some dead accounts. Recently the ip of the server was blacklisted because many mail adresses of the users are no longer available (550) and the server was sending newsletters to them.

To avoid this i am filtering out known unavailable mailboxes in the sending php script, but i want exim to take over this job because it is more universal.

My plan is to use a mysql database to list the unavailable mailboxes. I want to use a simple script that walks through the logfiles and saves the unavailable mailbox email adresses to the database.

I am not sure if it is common practive that some providers only pretend that mailboxes are unavailable because the server was on the blacklist. But once 40% of the mails were rejected with this response and i can't imagine that so many users deleted their mail accounts. Furthermore i have to take into consideration that deleted accounts could be (re-)created at some time. So along with the address i would store a timestamp that is, lets say 4 weeks in the future. Within this time all mails to the adress have to be dropped. If the first mail after this 4 weeks can be delivered, everything is fine. Otherwise the period should be extended (exponential backoff or so).

I can cover all this with the script and i even know already how a sql query that gives a list of blocked addresses would look like:

SELECT blocked FROM maildrop WHERE name=${localpart}@${domain} and timestamp<UNIX_TIMESTAMP()

But the question is, how do i integrate this into the exim configuration correctly? At first i thought i could use virtual aliases and redirect the mails to devnull@localhost user whose mails are piped to /dev/null.

I tested it using the following configuration

mysql_sys_aliases:
  debug_print = "R: mysql_sys_aliases for $local_part@$domain"
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup mysql{SELECT login FROM aliases WHERE alias='${local_part}@${domain}'}}

BTW: I also tested mysql_aliases instead of mysql_sys_aliases

and the following database entry: alias: mail@externaldomain.com | login: devnull@localhost

But without success. I still received the mails at externaldomain.com

Then i also found this post where acls are used but i couldn't get it working either. Also i am not sure if this works for mail that is sent by the system directly (not via external SMTP) https://serverfault.com/a/577007/239968

How would you solve that?

Florian
  • 21

1 Answers1

0

after a long day of try and error, i just found out how it works. Amazingly easy in restrospect.

On Debian make sure you have installed the exim4-daemon-heavy packages to have mysql support. I also assume that a split config is used (all paths are relative to /etc/exim4/conf.d/).

Then create the database with at least one column containing the blacklisted mail addresses. This cokumn should be indexed.

Create the file main/50_exim4-config_failmail and put the mysql credentials in it:

hide mysql_servers = MYSQL_HOST/MYSQL_DB/MYSQL_USER/MYSQL_PASS

Furthermore create router/050_exim4-config_failmail_router and add:

failmail:
  driver = redirect
  data = ${lookup mysql { SELECT '/dev/null' FROM dropmail WHERE email='${local_part}@${domain}'} {$value} }
  file_transport = address_file

It is very important that the file name begins with this 050 because it has to be loaded before the other routers. Otherwise the rules are ignored. It costed me a few hours to find out that it makes a big difference if you name the file "50_exim4-config...". In this case its rules are processed after the 400-ruleset and all outgoing mail is already sent.

This is not the full solution of the original problem because i simplified a bit to find out what happens. But based on this it should be easy to extend the database sheme and query to match the functionality outlined above.

Florian
  • 21