Mail Rate Limiting "refresh" command?

Is there a command line equivalent to clicking “Save” on:

Virtualmin -> Email Settings -> Mail Rate Limiting

This is a tiny little nit to pick but when I set rate limiting for a domain it adds lines in the GUI and lines to the /etc/milter-greylist/greylist.conf file.

When I later delete a domain, the lines remain in the /etc/milter-greylist/greylist.conf and appear as a blank entry in the GUI but with the limits intact (no doubt because the corresponding domain ID no longer exists). If I click “Save” in the GUI, that goes away. Is there a way to do that programmatically? (ie, without restarting the milter-greylist service, which I believe starts all of the counts over again, which I think “Save” does not).





Unchanged:

After I click “Save”:


I can force the issue by adding something like:

[ "$VIRTUALSERVER_ACTION" = "DELETE_DOMAIN" ] && /usr/local/sbin/remove-milter-greylist-settings.py $VIRTUALSERVER_DOM $VIRTUALSERVER_ID

And make (and then chmod +x) a little /usr/local/sbin/remove-milter-greylist-settings.py script like this:

#!/usr/bin/env python3

import sys
import re

def remove_lines(domain, id_number, file_path):
    try:
        # Read the existing lines from the file
        with open(file_path, 'r') as file:
            lines = file.readlines()

        # Prepare regex patterns
        id_pattern = re.compile(rf'domain_{id_number}')
        domain_pattern = re.compile(rf'@{re.escape(domain)}/')

        # Filter out lines based on the specified patterns
        filtered_lines = [
            line for line in lines
            if not id_pattern.search(line) and not domain_pattern.search(line)
        ]

        # Write the filtered lines back to the file
        with open(file_path, 'w') as file:
            file.writelines(filtered_lines)

        print(f"Removed lines containing '{domain}' in the format '@{domain}/' and '{id_number}' in the format 'domain_{id_number}' from {file_path}.")

    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: script.py <domain> <id_number>")
        sys.exit(1)

    domain = sys.argv[1]
    id_number = sys.argv[2]
    file_path = '/etc/milter-greylist/greylist.conf'

    remove_lines(domain, id_number, file_path)

And this does work, removing file lines (which reflects in the GUI of course). However it occurs to me that something else might actually be “refreshing” the config files but not actually the “running config” (there’s a lot of that in Linux) so I might be making things worse in a way because now if something is wrong in the running config, I can’t look at the greylist.conf file and be certain that that is what is currently loaded.

Does the “Save” button have this issue too? Or does the “Save” button do something more than resave the greylist.conf file with new settings to match the current GUI? (And is that something that I can do? …like some kind of “milter-greylist.service --refresh config” that I don’t know about?)

According to https://linux.die.net/man/5/greylist.conf:

image

And if that works like as advertised, that would mean that “Save” (effectively) does exactly what my script does and the config file is reloaded every single time there’s new mail if it’s been modified since the last mail… still I’m not sure that my using “sed” to yank out lines properly flags the file for “I’ve been modified, reload me” to milter-greylist.

And is mine a bad idea for some reason I haven’t thought of? (It really only solves a minor problem of "No-one will likely look at the ‘Mail Rate Limiting’ menu for years and then will wonder whether the blank lines reflect some problem and then will ask me, who will have long forgotten this, and will then spend two hours figuring out whether it’s an issue or not.)

Thanks.

Ron

SYSTEM INFORMATION
OS type and version Ubuntu 24.04.2
Virtualmin version 7.30.8