Thoughts on blocking by recipient email address -

This is a placeholder for me thinking about how to discard emails based on who they are sent to.

The use case for this is very specific to me, I have a server with hundreds of unique email aliases on an old Postfix server. I want to move to Mail in a Box but I have to handle all the old email addresses, some of which I need to keep going and some I want to block.

This may be of zero interest to anybody else, but I’m interested in this, so I thought I’d log what I’m doing here so other people can use it if they see fit. I’m not expecting anybody to chip in and help, and I’m not expecting a mod to take my ideas and do anything with them :smile:

I want to block some email addresses and not others. AFAIK there is no mechanism in the web interface to MIAB to do this. This is not a criticism but an observation.

I’ve edited main.cf and changed

smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,reject_rbl_client zen.spamhaus.org,reject_unlisted_recipient,check_policy_service inet:127.0.0.1:10023

to

smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,reject_rbl_client zen.spamhaus.org,reject_unlisted_recipient,check_policy_service inet:127.0.0.1:10023, check_recipient_access sqlite:/etc/postfix/check_recipient_access.cf

I’ve created /etc/postfix/check_recipient_access.cf

dbpath=/home/user-data/mail/users.sqlite
query = SELECT case '%s' WHEN '<<PUT AN EMAIL ADDRESS HERE>>' THEN 'DISCARD' ELSE 'OK' END;

Put a dummy email address in <> and send an e-mail to it.

tail -f /var/log/mail.log

shows that the dummy email address is DISCARDed showing that this idea might work.

So If I have a table of addresses to be blocked, I can write a SQL statement that returns DISCARD or OK for them.

This mightg work, but needs thoughts on the web interface and how to use that. Failing that a simple shell program can be used to populate the table.

Scripts is your best bet, unless you want to modify MIAB every time you update / add an email / add a domain

@murgero

I’m working my way up the software stack (slowly must be said).

  1. I can write a SQL query that returns a value that is used by Postfix, at the moment the SQL query is rather trivial, but it demonstrates it can be done. The CASE element of the SQL shows that you only need to put in addresses to be discarded, it’s basically an if/then/else statement. I have seen this done where you had to put addresses to be accepted and addresses to be defined. My views is that all addresses are excepted except where the aren’t.

  2. This integrates to postfix into the main.cf and seems to work.

  3. I need to test it with different delimiters, specifically the ‘+’ default one. No idea how it will work.

  4. I need to test it with different e-mail domains.

  5. Need to check how it works in the rewriting stack of operations. Never fully understood Postfix rules, now could be the chance.

  6. I need to create an actual table to put this in, it needs to be be consistent with the other tables,. I did notice there are no indexes defined for the tables in SQLite. For the small number of users here, a table scan is fine, but if there would thousands of users across multiple domains an index will be a jolly good idea.

  7. A simple Perl or similar script could be used to update the table defined.

  8. Look at the web interface and see if its a nice modular interface with nice easy to use routines. I hate UI programming and CSS stuff :frowning: Not my thing at all.

  9. Try and wrap this up in a nice script to install and uninstall the hack (as thats what it is).

  10. Errr… Profit?

1 Like

Have tested using the ‘+’ delimiter with a Google mail account.

If I update /etc/postfix/check_recipient_access.cf to add in an e-mail address with a + in it. This should DISCARD the email as this check is done before the ‘+’ is processed. Use email ‘rwillett+drop AT example DOT com’.

Sent email ‘rwillett+drop AT example DOT com’ from Google mail and it is rejected - Pass
Sent email ‘willett+drop2 AT example DOT com’ from Google mail and it is correctly passed through the system - Pass

This appears to mean that the RECIPIENT_DELIMITER ‘+’ is honoured and still works with this proposed blocking system.

So far, so good. Item 3 on list appears to be OK.

Now created and added a SQLIte table and updated the query.

CREATE TABLE blocked (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE , action TEXT NOT NULL DEFAULT 'DISCARD');

The SQL query now to check if an address is blocked is:

cat check_recipient_access.cf
dbpath=/home/user-data/mail/users.sqlite
query = select CASE WHEN EXISTS (select 1 from blocked where email = '%s') THEN (select action from blocked where email = '%s') ELSE 'OK' END;

This seems to work according to the mail logs. I’m sending email, no back scatter. The ‘+’ delimiter is also working, I can block these emails as well as ordinary emails.

So I’ll write a couple of Perl scripts to populate this table, but the changes are simple and can easily be applied to a new build.

Rob

Have now got this running.

I have set a catchall email address and send that to a single mail address. This means that ALL my old emails will go to a single e-mail address.

So far, the Postgrey and SpamAssassin and whatever else is in MIAB seem to be doing an excellent job of keeping bad e-mails away.

I have only had to add one email address to the blocking table to date, which is a little surprising. It may well be that the blocking table isn’t making a massive difference.

Its adding zero load though, so I’ll keep it going for the moment.

Will look at using the admin interface to add and delete users,

e.g.

Gives a JSON-encoded list of all blocked mail users
curl -X GET https://box.jambuster.london/admin/mail/blocked?format=json

Adds a new blocked email user
curl -X POST -d "blocked_email=user@mydomail.com" -d “password=s3curE_pa5Sw0rD” https://box.jambuster.london/admin/mail/users/block

Removes a blocked email user
curl -X POST -d "blocked_email=new_user@mydomail.com" https://box.jambuster.london/admin/mail/users/block_remove

Something to do whilst the wedding is on…

Hey @rwillett, did you ever follow through on the API to block a recipient? Or is there some other way since to block a recipient?

One method I’ve seen elsewhere is to simply create an alias that has no parent account. Would that work?

I did a test by simply forwarding the undesirable email recipient to a non-existent email address, and it is effective.

Here is the response the sender receives.

<[blackhole@nowhere.com](mailto:blackhole@nowhere.com)>
 (expanded from <[abcde@mydomain.co.za](mailto:abcde@mydomain.co.za)>): 
host [mx1.email-hosting.net.au]
(http://mx1.email-hosting.net.au/)[103.252.153.11] 
said: 550 Relay denied for <[nowhere.com](http://nowhere.com/)> 
(in reply to RCPT TO command)