Ein Kumpel schickt ab und an mal einen Newsletter an recht viele Mailadressen von Kunden. Als er das letztens mal wieder machte, stolperte ich in den Logdateien über sehr viele Bounces. Ein weiteres Suchen ergab, das sich im Laufe der Zeit sehr viele ungültige Mailadressen in der Datenbank für diesen Newsletter befunden hatten.
Hier nun ein kleines Skript für die Bourne Again Shell, welches alle Mailadressen aus einer Datenbank (in dem Fall MySQL) ausliest, den MX Rekord heraus sucht und abschließend ein Test-Connect durchführt... und die fehlerhaften Mails danach aus der Datenbank entfernt.
#!/bin/sh
####################################################################
# /TR 2014-01-05 GPLv2
####################################################################
db_name="database_name"
db_user="db_user"
db_pass="db_password"
db_table="newsletter_table"
# alle mails aus der datenbank raus holen...
function getmails() {
echo "use $db_name; select email from $db_table;" \
| mysql --skip-column-names -u$db_user -p$db_pass
}
# alle mx server für eine bestimmte domain abfragen...
function dnsmx() {
domain="$1"
# via dig von bind
dig mx $domain|grep "^$domain."|tr -s '\t' ' ' \
| cut -d' ' -f6|sed -e 's/.$//g'
# via dnsmx von djb, oder dig von bind
# dnsmx $domain
}
# eine bestimmte mail aus der tabelle entfernen
function delete_email() {
email="$1"
echo $email >> deleted.txt
# dieses return auskommentieren, wenn die emails wirklich aus
# der datenbank entfernt werden sollen
return
# achtung, hier wird nun wirklich gelöscht!
echo "use $db_name;
delete from $db_table where email='$email';" \
| mysql -u$db_user -p$db_pass
}
# versuche den mx zu connecten
# -> wenn das nicht klappt:
# -> lösche die email aus der datenbank
# -> setze den mx auf eine blacklist
# -> wenn connect in ordnung war, ab auf die whitelist
function checkmail() {
mx=$1
email=$2
echo -e "\ncheckmail mx=$mx mail=$email"
# prüfe, ob mx der email in whitelist steht
while read wl; do
if [ "$mx" = "$wl" ]; then
echo "mail $email (mx $mx) is on white list, skipping..."
echo $email >> goodmail.txt
return
fi
done < white.txt
# prüfe, ob mx der email in blacklist steht
while read bl; do
if [ "$mx" = "$bl" ]; then
echo "mail $email (mx $mx) is on black list, deleting..."
delete_email "$email"
return
fi
done < black.txt
# wenn ein connect zum mx in 6 sekunden erfolgreich ist,
# nehmen wir an, das der server in ordnung ist
timeout 6 bash -c "cat < /dev/null > /dev/tcp/$mx/25"
if [ $? != 0 ]; then
# can not connect, so the email seems wrong!!
echo "can not connect to mx $mx of email $email, deleting..."
echo $mx >> black.txt
delete_email "$email"
return
fi
echo $email >> goodmail.txt
echo $mx >> white.txt
}
# 1) alle zu prüfenden mails aus der datenbank exportieren...
getmails > mails.txt
# resette black und white list
echo -n > white.txt
echo -n > black.txt
# 2) checke für alle mails den mx
while read email; do
domain=`echo $email|cut -d'@' -f2`
mx=`dnsmx $domain|head -n 1`
if [ -z "$mx" ]; then
# lösche mails mit invalid mx
echo "no mx for email $email, deleting..."
delete_email "$email"
continue
fi
# connect prüfen...
checkmail "$mx" "$email"
done < mails.txt
# 3) delete temp files
# rm mails.txt black.txt white.txt
# 4) delete debug files
# rm godmail.txt deleted.txt