Code Snippets and Patches of 2014

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

checkmails.sh

Last modified on 2014-01-05 at 15:52
netcup.de