|
| 1 | +#!/usr/bin/env bash |
| 2 | +# add_whitelists.sh - Add domains/IPs to Postfix and Postgrey whitelists |
| 3 | +# Author: Anton Babaskin |
| 4 | + |
| 5 | +set -Eeuo pipefail |
| 6 | + |
| 7 | +POSTFIX_FILE="/etc/postfix/client_whitelist" |
| 8 | +POSTGREY_FILE="/etc/postgrey/whitelist_clients.local" |
| 9 | +BACKUP_DATE="$(date +%F_%H%M%S)" |
| 10 | + |
| 11 | +usage() { |
| 12 | + cat <<EOF |
| 13 | +Usage: |
| 14 | + $0 [-n] <domain-or-ip> |
| 15 | + $0 [-n] -f <file_with_entries> |
| 16 | +
|
| 17 | +Options: |
| 18 | + -f FILE File with entries (one per line, empty lines and #comments ignored) |
| 19 | + -n Dry-run mode (no changes applied) |
| 20 | + -h Show this help message |
| 21 | +
|
| 22 | +Examples: |
| 23 | + $0 example.com |
| 24 | + $0 203.0.113.7 |
| 25 | + $0 -f whitelist.txt |
| 26 | + $0 -n -f whitelist.txt |
| 27 | +EOF |
| 28 | + exit 1 |
| 29 | +} |
| 30 | + |
| 31 | +DRY=0 |
| 32 | +LIST_FILE="" |
| 33 | +while getopts ":f:nh" opt; do |
| 34 | + case "$opt" in |
| 35 | + f) LIST_FILE="$OPTARG" ;; |
| 36 | + n) DRY=1 ;; |
| 37 | + h) usage ;; |
| 38 | + *) usage ;; |
| 39 | + esac |
| 40 | +done |
| 41 | +shift $((OPTIND -1)) |
| 42 | + |
| 43 | +SINGLE_TARGET="${1:-}" |
| 44 | + |
| 45 | +if [[ -z "$SINGLE_TARGET" && -z "$LIST_FILE" ]]; then |
| 46 | + usage |
| 47 | +fi |
| 48 | + |
| 49 | +msg() { printf '%b\n' "$*"; } |
| 50 | +die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } |
| 51 | + |
| 52 | +require_root() { |
| 53 | + if [[ $EUID -ne 0 ]]; then |
| 54 | + die "Run as root or with sudo." |
| 55 | + fi |
| 56 | +} |
| 57 | + |
| 58 | +ensure_file() { |
| 59 | + local path="$1" |
| 60 | + local dir |
| 61 | + dir="$(dirname "$path")" |
| 62 | + if [[ ! -d "$dir" ]]; then |
| 63 | + msg "📁 Creating directory: $dir" |
| 64 | + [[ $DRY -eq 0 ]] && mkdir -p "$dir" |
| 65 | + fi |
| 66 | + if [[ ! -f "$path" ]]; then |
| 67 | + msg "📝 Creating file: $path" |
| 68 | + [[ $DRY -eq 0 ]] && touch "$path" |
| 69 | + [[ $DRY -eq 0 ]] && chmod 644 "$path" |
| 70 | + fi |
| 71 | +} |
| 72 | + |
| 73 | +backup_if_exists() { |
| 74 | + local path="$1" |
| 75 | + if [[ -f "$path" ]]; then |
| 76 | + msg "🗂 Backup: ${path}.bak_${BACKUP_DATE}" |
| 77 | + [[ $DRY -eq 0 ]] && cp -a "$path" "${path}.bak_${BACKUP_DATE}" |
| 78 | + fi |
| 79 | +} |
| 80 | + |
| 81 | +is_domain() { |
| 82 | + local s="$1" |
| 83 | + [[ "$s" =~ ^([A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$ ]] |
| 84 | +} |
| 85 | + |
| 86 | +is_ipv4() { |
| 87 | + local s="$1" |
| 88 | + [[ "$s" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] |
| 89 | +} |
| 90 | + |
| 91 | +is_cidr() { |
| 92 | + local s="$1" |
| 93 | + [[ "$s" =~ ^([0-9]{1,3}]()]() |
0 commit comments