X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;ds=sidebyside;f=mailtest-check;h=7adec9281f094932ae30efee2651bbf3f65ac8cd;hb=HEAD;hp=036aeff1a2faf981367d7ff69f9ebb98cff26a58;hpb=d6def754cd241538c61456536b52ee51cbd85b42;p=distro-setup diff --git a/mailtest-check b/mailtest-check index 036aeff..9f37cb9 100755 --- a/mailtest-check +++ b/mailtest-check @@ -1,17 +1,40 @@ #!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to switch +# its license to GPL. -# Usage: mail-test-check [slow] [anything] +# Copyright 2024 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# Usage: mailtest-check [slow] [int|nonint] # # slow: do slow checks, like spamassassin # -# anything: consider non-interactive, dont print unless something went +# for non-interactive, dont print unless something went # wrong +#set -x -source /b/errhandle/err [[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@" +source /b/bash-bear-trap/bash-bear + shopt -s nullglob e() { $int || return 0; printf "mailtest-check: %s\n" "$*"; } @@ -19,8 +42,8 @@ e() { $int || return 0; printf "mailtest-check: %s\n" "$*"; } getspamdpid() { if [[ ! $spamdpid || ! -d /proc/$spamdpid ]]; then # try twice in case we are restarting, it happens. - for i in 1 2; do - spamdpid=$(systemctl show --property MainPID --value spamassassin | sed 's/^[10]$//' ||:) + for (( i=0; i<2; i++ )); do + spamdpid=$(systemctl show --property MainPID --value $spamd_ser | sed 's/^[10]$//' ||:) if [[ $spamdpid ]]; then break fi @@ -28,11 +51,6 @@ getspamdpid() { done fi } -pr() { - if $doprom && [[ -e /var/lib/prometheus/node-exporter ]]; then - cat >>/var/lib/prometheus/node-exporter/mailtest-check.prom.$$ - fi -} #### begin arg processing #### @@ -67,6 +85,13 @@ fi # TODO, get je to deliver the local mailbox: /m/md/INBOX # dovecot appears to setup, i can t be sure. +maini=0 + +spamd_ser=spamd +if systemctl cat spamassassin &>/dev/null; then + spamd_ser=spamassassin +fi + source /a/bin/bash_unpublished/source-state doprom=false @@ -81,6 +106,7 @@ esac main() { + local -a p_unexpected_spamd_results p_missing_dnswl p_last_usec case $HOSTNAME in bk) folders=(/m/md/{expertpathologyreview.com,amnimal.ninja}/testignore) @@ -92,7 +118,11 @@ main() { ;; *) folders=(/m/md/l/testignore) - froms=(testignore@je.b8.nz testignore@expertpathologyreview.com testignore@amnimal.ninja ian@iankelling.org z@zroe.org iank@gnu.org) + # save some cpu cycles + froms=(testignore@je.b8.nz ian@iankelling.org) + if (( maini % 10 == 0 )); then + froms=(testignore@je.b8.nz testignore@expertpathologyreview.com testignore@amnimal.ninja ian@iankelling.org z@zroe.org) + fi if ! $int; then ### begin rsyncing fencepost email ### # We dont want to exit if rsync fails, that will get caught by @@ -141,15 +171,15 @@ EOF fi e spamdpid: $spamdpid if [[ ! $spamdpid ]]; then - echo mailtest spamd pid not found. systemctl status spamassassin: - systemctl status spamassassin + echo mailtest spamd pid not found. systemctl status $spamd_ser: + systemctl status $spamd_ser fi tmpfile=$(mktemp) declare -i unexpected=0 for folder in ${folders[@]}; do for from in ${froms[@]}; do declare -i missing_dnswl=0 - declare -i dnsfail=0 + #declare -i dnsfail=0 declare -i unexpected=0 latest= last_sec=0 @@ -186,19 +216,27 @@ EOF # example line that sed is parsing: # (-0.1 / 5.0 requ) DKIM_SIGNED=0.1,DKIM_VALID=-0.1,DKIM_VALID_AU=-0.1,SPF_HELO_PASS=-0.001,SPF_PASS=-0.001,TVD_SPACE_RATIO=0.001 autolearn=_AUTOLEARN resultfile=$(mktemp) - $spamcpre sudo -u Debian-exim spamassassin -D -t --cf='score PYZOR_CHECK 0' <"$latest" &>$resultfile + # add -D for debug info. usually it + $spamcpre sudo -u Debian-exim spamassassin -t --cf='score PYZOR_CHECK 0' <"$latest" &>$resultfile # note: on some mail, its 1 line after the send-test-forward, on others its 2 with a blank inbetween. # I use the sed -n to filter this. raw_results="$(tail $resultfile | grep -A2 -Fx /usr/local/bin/send-test-forward | tail -n+2 | sed -nr 's/^\([^)]*\) *//;s/=[^, ]*([, ]|$)/ /gp')" for r in $raw_results; do case $r in + # This came in t12, but its just dkim + spf, and my + # systems aren't all t12, so ignore it for now. + DMARC_PASS) : ;; # got this in an update 2022-01. dun care T_SCC_BODY_TEXT_LINE|SCC_BODY_SINGLE_WORD) : ;; # we have a new domain, ignore this. # it seems like some versions of spamassassin do BODY_SINGLE_WORD, others dont, we dun care. # bayes_00 is a new one indicating ham, we dont care if its missing. BAYES_00|BODY_SINGLE_WORD|FROM_FMBLA_NEWDOM*|autolearn) : ;; + + # These have somewhat randomly been added and removed, resulting in useless alerts, so ignore them. + RCVD_IN_DNSWL_MED|DKIMWL_WL_HIGH) : ;; + SPF_HELO_NEUTRAL) # some of my domains use neutral spf, treat them the same. results[SPF_HELO_PASS]=t @@ -215,12 +253,7 @@ EOF keys=(DKIM_SIGNED DKIM_VALID{,_AU,_EF} SPF_HELO_PASS SPF_PASS TVD_SPACE_RATIO) if [[ $to == *@gnu.org && $from == *@gnu.org ]]; then keys=(ALL_TRUSTED TVD_SPACE_RATIO) - elif [[ $to == *@gnu.org ]]; then - # eggs has RCVD_IN_DNSWL_MED - keys+=(RCVD_IN_DNSWL_MED) - elif [[ $from == *@gnu.org ]]; then - # eggs has this. it used to have DKIMWL_WL_HIGH sometime in 2022 - keys+=(RCVD_IN_DNSWL_MED) + # from eggs had DKIMWL_WL_HIGH sometime in 2022, then DKIMWL_WL_MED unti march 2023 fi for t in ${keys[@]}; do @@ -262,13 +295,13 @@ EOF # echo mailtest-check: cat $latest: # cat $latest # echo mailtest-check: end of cat - # echo "$(tput setaf 5 2>/dev/null ||:)█$(tput sgr0 2>/dev/null||:)%.0s" $(eval echo "{1..${COLUMNS:-60}}") #fi fi rm -f $resultfile for r in ${results[@]}; do case $r in - # iank: for when we want to handle dns errors differently + # iank: for when we want to handle dns errors differently. + # also uncomment declaration of dnsfail above. # DKIM_INVALID|T_SPF_TEMPERROR|T_SPF_HELO_TEMPERROR) # dnsfail+=1 # ;; @@ -278,21 +311,19 @@ EOF esac done for miss in ${missing[@]}; do - # We expect dns failures from time to time, so - # we count them separately and alert differently. + # At some point we had annoying dns failures that we couldn't solve so we + # we counted dns fail related results separately and alert differently. + # DKIM_VALID|DKIM_VALID_AU|DKIM_VALID_EF|SPF_HELO_PASS|SPF_PASS| case $miss in - # iank: dns fail - # DKIM_VALID|DKIM_VALID_AU|DKIM_VALID_EF|SPF_HELO_PASS|SPF_PASS| - RCVD_IN_DNSWL_MED|DKIMWL_WL_HIGH) - missing_dnswl+=1 - ;; *) unexpected+=1 ;; esac done - pr <>$path + done + for l in "${p_missing_dnswl[@]}"; do + printf "%s\n" "$l" >>$path + done + for l in "${p_last_usec[@]}"; do + printf "%s\n" "$l" >>$path + done + mv $path $dir/mailtest-check.prom # note: node_textfile_mtime_seconds will tell us when this last happened. useful for debugging. fi } @@ -323,12 +364,13 @@ loop-main() { while true; do premain_sec=$EPOCHSECONDS main + maini=$((maini + 1)) sleep $(( 300 - ( EPOCHSECONDS - premain_sec ) )) done } -if [[ $INVOCATION_ID ]]; then +if [[ $PPID == 1 ]]; then loop-main else main