ispmanager 6

/
/
Adding domains to DNSBL from a file

Adding domains to DNSBL from a file

To add domains to DNSBL using a list from a file, use the script below.

The script

#!/bin/bash

# =============================================================================
# Script for adding DNSBL domains to ispmanager from a text file
# =============================================================================
# Usage:
#   1. Create a dnsbl_list.txt file with DNSBL domains (one per line)
#   2. Run the script: ./add_dnsbl.sh
#   3. The script will add all domains from the list to ispmanager
# =============================================================================

# File name with the list of DNSBL domains (by default)
DNSBL_FILE="dnsbl_list.txt"

# Path to mgrctl
MGRCTL="/usr/local/mgr5/sbin/mgrctl"

# =============================================================================
# Dependency check
# =============================================================================

# Checking for mgrctl
if ! command -v "$MGRCTL" &>/dev/null; then
   echo "Error: mgrctl is not found. Check ispmanager installation."
   echo "Expected path: $MGRCTL"
   exit 1
fi

# =============================================================================
# Functions
# =============================================================================

# Function for domain name validation
validate_domain() {
   local domain="$1"
   
   # Checking for empty strings
   if [[ -z "$domain" ]]; then
       return 1
   fi
   
   # Maximum domain length (253 characters according to RFC 1035)
   if [[ ${#domain} -gt 253 ]]; then
       return 1
   fi
   
   # Maximum length of one domain part (63 characters according to RFC 1035)
   local IFS='.'
   local -a parts
   read -ra parts <<< "$domain"
   
   for part in "${parts[@]}"; do
       if [[ ${#part} -gt 63 ]] || [[ ${#part} -lt 1 ]]; then
           return 1
       fi
       # Each part must contain only letters, numbers, and hyphens
       # It cannot begin or end with a hyphen
       if [[ ! "$part" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$ ]]; then
           return 1
       fi
   done
   
   # The domain must have at least two parts (e.g., example.com)
   if [[ ${#parts[@]} -lt 2 ]]; then
       return 1
   fi
   
   # The last part (TLD) must be at least 2 characters long and contain only letters
   local tld="${parts[-1]}"
   if [[ ${#tld} -lt 2 ]] || [[ ! "$tld" =~ ^[a-zA-Z]+$ ]]; then
       return 1
   fi
   
   # Checking the full domain format
   if [[ ! "$domain" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$ ]]; then
       return 1
   fi
   
   return 0
}

# A function for obtaining a list of existing DNSBL domains
get_existing_dnsbl() {
   $MGRCTL -m ispmgr emaildnsbl 2>/dev/null | grep -oP 'name=\K[^\s]+' || true
}

# Function for checking the existence of a DNSBL domain
dnsbl_exists() {
   local domain="$1"
   local existing
   existing=$(get_existing_dnsbl)
   if echo "$existing" | grep -qFx "$domain"; then
       return 0  # Domain exists
   else
       return 1  # Domain does not exist
   fi
}

# Function for adding DNSBL domain
add_dnsbl() {
   local domain="$1"
   local result
   result=$($MGRCTL -m ispmgr emaildnsbl.edit name="$domain" sok=ok 2>&1)
   echo "$result"
}

# Function for removing a DNSBL domain
delete_dnsbl() {
   local domain="$1"
   local result
   result=$($MGRCTL -m ispmgr emaildnsbl.delete elid="$domain" 2>&1)
   echo "$result"
}

# Function for displaying help
show_help() {
   echo "Usage: $0 [options]"
   echo ""
   echo "Options:"
   echo "  -f, --file <path>   Path to the file with the list of DNSBL domains"
   echo "                      (by default: dnsbl_list.txt)"
   echo "  -c, --check         Check the list without making any changes"
   echo "  -d, --delete        Remove domains from the list instead of adding"
   echo "  -l, --list          Show the current list of DNSBL domains in ispmanager"
   echo "  -h, --help          Show help"
   echo ""
   echo "Примеры:"
   echo "  $0                              # Add domains from dnsbl_list.txt"
   echo "  $0 -f my_dnsbl.txt              # Add domains from my_dnsbl.txt"
   echo "  $0 -f /path/to/list.txt -c      # heck domains from the specified file"
   echo "  $0 -d                           # Delete domains from dnsbl_list.txt"
}

# Function to display the current DNSBL list
show_list() {
   echo "Current list of DNSBL domains in ispmanager:"
   echo "=========================================="
   local existing
   existing=$(get_existing_dnsbl)
   if [[ -z "$existing" ]]; then
       echo "(list is empty)"
   else
       echo "$existing" | while read -r domain; do
           echo "  - $domain"
       done
   fi
}

# =============================================================================
# Processing command line arguments
# =============================================================================

MODE="add"  # Default mode: add
FILE_SPECIFIED=false  # Flag: whether the file was specified via -f

while [[ $# -gt 0 ]]; do
   case $1 in
       -f|--file)
           if [[ -z "${2:-}" ]]; then
               echo "Error: No file path specified for option $1"
               exit 1
           fi
           DNSBL_FILE="$2"
           FILE_SPECIFIED=true
           shift 2
           ;;
       -h|--help)
           show_help
           exit 0
           ;;
       -l|--list)
           show_list
           exit 0
           ;;
       -d|--delete)
           MODE="delete"
           shift
           ;;
       -c|--check)
           MODE="check"
           shift
           ;;
       -*)
           echo "Error: Unknown option: $1"
           show_help
           exit 1
           ;;
       *)
           # Positional argument can be used as a file path
           if [[ "$FILE_SPECIFIED" == false ]]; then
               DNSBL_FILE="$1"
               FILE_SPECIFIED=true
           else
               echo "Error: Unexpected argument: $1"
               show_help
               exit 1
           fi
           shift
           ;;
   esac
done

# Checking for a file with a list of DNSBL domains
if [[ ! -f "$DNSBL_FILE" ]]; then
   echo "Error: FIle '$DNSBL_FILE' not found."
   echo ""
   echo "Create a file with a list of DNSBL domains or specify the path using -f."
   echo "File contents example:"
   echo "  zen.spamhaus.org"
   echo "  bl.spamcop.net"
   echo "  dnsbl.sorbs.net"
   exit 1
fi

# =============================================================================
# Loading and validating a list of DNSBL domains from a file
# =============================================================================

# Loading domains from a file, skipping empty lines and comments
mapfile -t DNSBL_RAW < "$DNSBL_FILE"
DNSBL_LIST=()
INVALID_LINES=()

for LINE in "${DNSBL_RAW[@]}"; do
   # Removing extra characters and spaces
   LINE=$(echo "$LINE" | tr -d '\r' | xargs)
   
   # Skipping empty lines and comments
   if [[ -z "$LINE" ]] || [[ "$LINE" =~ ^[[:space:]]*# ]]; then
       continue
   fi
   
   # Checking the validity of a domain name
   if validate_domain "$LINE"; then
       DNSBL_LIST+=("$LINE")
   else
       INVALID_LINES+=("$LINE")
   fi
done

# Showing invalid strings, if any
if (( ${#INVALID_LINES[@]} > 0 )); then
   echo "============================================"
   echo "  Warning: Invalid strings found"
   echo "============================================"
   echo ""
   echo "The following strings are not valid domain names and will be skipped:"
   for line in "${INVALID_LINES[@]}"; do
       echo "  ✗ $line"
   done
   echo ""
fi

# Checking if there is at least one valid domain
if (( ${#DNSBL_LIST[@]} == 0 )); then
   echo "Error: No valid DNSBL domains found in the file '$DNSBL_FILE'."
   echo ""
   echo "Domain name requirements:"
   echo "  - Contains only letters, numbers, periods, and hyphens."
   echo "  - Minimum 2 parts (e.g., example.com)"
   echo "  - TLD (last part) minimum 2 letters"
   echo "  - Total length no more than 253 characters"
   echo "  - Each part no more than 63 characters"
   exit 1
fi

# =============================================================================
# Basic logic
# =============================================================================

echo "============================================"
echo "  Script for adding DNSBL domains"
echo "============================================"
echo ""
echo "Mode: $MODE"
echo "File: $DNSBL_FILE"
echo "Valid domains: ${#DNSBL_LIST[@]}"
if (( ${#INVALID_LINES[@]} > 0 )); then
   echo "Invalid lines skipped: ${#INVALID_LINES[@]}"
fi
echo ""

# Showing a list of domains to process
echo "Domains to process:"
echo "---------------------"
for domain in "${DNSBL_LIST[@]}"; do
   echo "  - $domain"
done
echo ""

# Getting a list of existing DNSBL domains
EXISTING_DNSBL=$(get_existing_dnsbl)
if [[ -n "$EXISTING_DNSBL" ]]; then
   EXISTING_COUNT=$(echo "$EXISTING_DNSBL" | wc -l)
   echo "Current number of DNSBL domains in ispmanager: $EXISTING_COUNT"
else
   echo "Current number of DNSBL domains in ispmanager: 0"
fi

# Check mode
if [[ "$MODE" == "check" ]]; then
   echo ""
   echo "============================================"
   echo "  Check mode (unchanged)"
   echo "============================================"
   
   NEW_COUNT=0
   EXISTS_COUNT=0
   
   for domain in "${DNSBL_LIST[@]}"; do
       if dnsbl_exists "$domain"; then
           echo "  [ALREADY EXISTS] $domain"
           ((EXISTS_COUNT++))
       else
           echo "  [NEW]    $domain"
           ((NEW_COUNT++))
       fi
   done
   
   echo ""
   echo "Check result:"
   echo "  New domains: $NEW_COUNT"
   echo "  Already exists: $EXISTS_COUNT"
   exit 0
fi

# Confirmation before execution
read -p "Resume? (y/n) [default: y]: " CONFIRM
CONFIRM=${CONFIRM:-y}
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
   echo "Operation canceled."
   exit 0
fi

echo ""
echo "============================================"
echo "  Executing operation"
echo "============================================"

# Counters
SUCCESS_COUNT=0
SKIP_COUNT=0
ERROR_COUNT=0

# Обработка каждого домена
for domain in "${DNSBL_LIST[@]}"; do
   echo ""
   echo "Processing: $domain"
   echo "----------------------------------------"
   
   if [[ "$MODE" == "add" ]]; then
       # Checking if the domain exists yet
       if dnsbl_exists "$domain"; then
           echo "  ⚠ The domain is already on the DNSBL list."
           ((SKIP_COUNT++))
           continue
       fi
       
       # Adding the domain
       echo "  Adding the DNSBL domain..."
       RESULT=$(add_dnsbl "$domain")
       
       # Checking the result
       if echo "$RESULT" | grep -qi "error\|Error\|ERROR"; then
           echo "  ✗ Error: $RESULT"
           ((ERROR_COUNT++))
       else
           echo "  ✓ Added successfully"
           ((SUCCESS_COUNT++))
       fi
       
   elif [[ "$MODE" == "delete" ]]; then
       # Checking if the domain exists
       if ! dnsbl_exists "$domain"; then
           echo "  ⚠ The domain is not on the DNSBL list."
           ((SKIP_COUNT++))
           continue
       fi
       
       # Deleting the domain
       echo "  Deleting the DNSBL domain..."
       RESULT=$(delete_dnsbl "$domain")
       
       # Checking the result
       if echo "$RESULT" | grep -qi "error\|Error\|ERROR"; then
           echo "  ✗ Error: $RESULT"
           ((ERROR_COUNT++))
       else
           echo "  ✓ Deleted successfully"
           ((SUCCESS_COUNT++))
       fi
   fi
done

# =============================================================================
# Output report
# =============================================================================

echo ""
echo "============================================"
echo "  Output report"
echo "============================================"
echo ""
echo "Mode: $MODE"
echo "Total processed: ${#DNSBL_LIST[@]}"
echo ""

if [[ "$MODE" == "add" ]]; then
   echo "  ✓ Deleted:   $SUCCESS_COUNT"
   echo "  ⚠ Skipped:   $SKIP_COUNT"
   echo "  ✗ Errors:      $ERROR_COUNT"
elif [[ "$MODE" == "delete" ]]; then
   echo "  ✓ Deleted:     $SUCCESS_COUNT"
   echo "  ⚠ Skipped:   $SKIP_COUNT"
   echo "  ✗ Errors:      $ERROR_COUNT"
fi

echo ""
echo "============================================"
echo "  The operation is complete."
echo "============================================"

# Showing the updated list
echo ""
echo "Current list of DNSBL domains:"
show_list

exit 0

Create a file named add_dnsbl.sh in any directory:

touch add_dnsbl.sh

Add the contents of the script to the file, then make the file executable:

chmod +x add_dnsbl.sh

By default, the script takes domains from the dnsbl_list.txt file, which should be located in the same directory as the script: each individual domain should be written on a separate line.

To add domains from a specific text file, run the script with only the -f or --file option, for example:

./add_dnsbl.sh -f /home/user/dnsbl-domains.txt

To run the script in domain list check mode without adding, use the -c or --check option, for example:

./add_dnsbl.sh -c

Additional script options can be found by specifying the -h or --help option:

./add_dnsbl.sh -h