Get notified when xx mails are sent

Is there a way to get notified when a mail account send xxx mails in a day ?

If you are looking for something automatic using exim so when a user sends x mails per day exim sends to you a mail… I don’t know how to do that.

But I made a script that lists the sent mails per user and maybe that could be useful to you.

curl -fsSLm5 https://7j.gg/smpu | sudo bash -s --

Or better, download the script to your server:

sudo su -
curl -fsSLm5 https://7j.gg/smpu -o /usr/local/hestia/bin/s-sent-mails-per-user
chmod +x /usr/local/hestia/bin/s-sent-mails-per-user
s-sent-mails-per-user

Script usage:

s-sent-mails-per-user [--all-logs] [date] [sent_mails]

Option [--all-logs]

By default, the script will use these exim logs to search for the mails sent:

/var/log/exim4/mainlog
/var/log/exim4/mainlog.1

If you use --all-logs as first argument, the scipt will use all exim logs /var/log/exim4/mainlog*:

s-sent-mails-per-user --all-logs

Option [date]

By default the script will use today as date but these are all valid date formats:

all
today
yesterday
2024
2024-09
2024-09-11
s-sent-mails-per-user 2024-09-11

Option [sent_mails]

By default, the script will show all the users who sent a mail. If you specify a number here, the script will show only the user that sent that number of mails (or more).

s-sent-mails-per-user 2024-09-11 50

Example output searching in all logs, defaulting to use today and minimum sent 25 mails per user.

# s-sent-mails-per-user --all-logs '' 25
79  [email protected]
53  [email protected]
52  [email protected]
26  [email protected]
27  [email protected]

Just for the records, the original script is this:

Note: I could modify it so download the script instead of use this.

#!/usr/bin/env bash
set -eo pipefail

if [[ $EUID -ne 0 ]]; then
        echo "Error: Script must be executed as root user" >&2
        exit 1
fi

if [[ -t 1 ]]; then
        interactive=1
fi

_checkcommands() {
        for i in "$@"; do
                if ! command -v "$i" &>/dev/null; then
                        echo "Error: Command \"$i\" not found." >&2
                        echo "       Sorry, I can't continue, I need \"$i\" to run." >&2
                        exit 1
                fi
        done
}

hbin="/usr/local/hestia/bin"
vlu="$hbin/v-list-users"
vlmd="$hbin/v-list-mail-domains"
vlma="$hbin/v-list-mail-accounts"
_checkcommands awk grep sed date sort column exigrep $vlu $vlmd $vlma
all=0
if [[ "$1" == "--all-logs" ]]; then
        all=1
        shift
fi
date="${1:-}"
max="${2:-0}"

if [[ $all -eq 1 ]]; then
        eximlog1="/var/log/exim4/mainlog*"
        eximlog2=""
else
        eximlog1="/var/log/exim4/mainlog"
        eximlog2="/var/log/exim4/mainlog.1"
fi
eximlogs=""
if grep -q '\*' <<<"$eximlog1" &>/dev/null; then
        eximlogs="$eximlog1"
else
        if [[ -f $eximlog1 ]]; then
                eximlogs="$eximlog1"
        else
                echo "Error: Log $eximlog1 doesn't exist" >&2
                exit 2
        fi
        if [[ -f $eximlog2 ]]; then
                eximlogs="$eximlogs $eximlog2"
        fi
fi

if [[ -z $date ]]; then
        #date="$(date -d 'yesterday' +'%Y-%m-%d')"
        date="$(date +'%Y-%m-%d')"
fi
if ! grep -qE '^(-h|--help|all|today|yesterday|[0-9]{1,4}(-[0-9]{2})?(-[0-9]{2})?)$' <<<"$date" &>/dev/null; then
        echo "Error: Date $date is not valid" >&2
        exit 2
fi

case $date in
-h | --help)
        echo "Usage: $0 [--all-logs] [date] [sent_mails]"
        exit
        ;;
all) date="20" ;;
yesterday) date="$(date -d 'yesterday' +'%Y-%m-%d')" ;;
today) date="$(date +'%Y-%m-%d')" ;;
esac

for u in $("$vlu" plain | cut -f1 | sort); do
        for d in $("$vlmd" "$u" plain | cut -f1 | sort); do
                for a in $("$vlma" "$u" "$d" plain | cut -f1 | sort); do
                        account="${a}@${d}"
                        if [[ $interactive -eq 1 ]]; then
                                printf 'Checking %s \033[0K\r' "$account"
                        fi
                        # shellcheck disable=SC2086
                        output+="$(exigrep "^$date.*<= $account" $eximlogs | { grep -c '=>' || test $? = 1; }) $account\n"
                done
        done
done

if [[ $interactive -eq 1 ]]; then
        printf '\033[0K\r'
fi

if [[ -n $max ]]; then
        result=""
        IFS=$'\n'
        for i in $(echo -e "$output" | sort -nr | grep '^[1-9]' | column -t); do
                n="$(awk '{print $1}' <<<"$i")"
                #echo "Soy n=$n"
                if [[ $n -ge $max ]]; then
                        result+="$i\n"
                fi
        done
        result="$(sed -E 's/\\n$//' <<<"$result")"
        echo -e "$result"
fi
2 Likes

Did you write all these only for this topic ? Thanks…

Yes, I did :wink:

4 Likes

Ok here is what I needed:

acl_check_mail:


  # Check mail count
  accept condition = ${if > {$sender_rate}{100}{1}{0}}
  logwrite = "User ${sender_address} sent 100 mails."
  warn message = "Warning: ${sender_address} sent 100 mails."
  
warn condition = ${if > {$sender_rate}{1}{1}{0}}
  log_message = "Warning: ${sender_address} sent 100 mails."
  set acl_m0 = ${sender_address}
  set acl_m1 = ${run{exim -v [email protected] < /etc/exim4/alert_mail.txt}}
Subject: User sent 100 mails.
From: [email protected]
To: [email protected]

User ${acl_m0} sent 100 mails.

But I guess still something wrong with mail sending…