TSF – Giải pháp IT toàn diện cho doanh nghiệp SMB | HCM

PRTG - Advanced Mail Server Monitoring with PRTG Network Monitor

In this tutorial, you’ll learn advanced mail server monitoring using PRTG Network Monitor.
This guide explains how to monitor SMTP, IMAP, and mail delivery performance in detail.
Advanced monitoring helps detect hidden email issues that basic checks often miss.
Mail server problems can occur silently before users report missing or delayed emails.
PRTG allows IT administrators to receive early warnings with real-time alerts.
In this video, we demonstrate advanced sensor configuration and alert thresholds.
You’ll also learn best practices for reliable email monitoring in production environments.
Follow this guide to keep your mail services stable, secure, and fully monitored.

MAILCOW & DOCKER

#1. SSH Script Advanced – Docker Containers


Functions
• Check if important mailcow containers are running
Check containers:
• postfix-mailcow
• dovecot-mailcow
• rspamd-mailcow
• clamav-mailcow
• nginx-mailcow
Output
• 1 = OK
• 0 = FAIL
Thresholds
• ❌ Lower DOWN: 1
📌 Only 1 container needs to fail → mail fails

Step 1: Grant Docker permissions to the SSH user

sudo usermod -aG docker bao
then reboot the mail server
Check again with the command `docker ps`, if it no longer requests permissions, it’s correct.

Step 2: Create check script

sudo mkdir -p /var/prtg/scriptsxml

Create file

sudo nano /var/prtg/scriptsxml/check_mailcow_containers.sh
Content

💻
filename.sh
#!/bin/bash

PATTERNS=(
  "postfix-mailcow"
  "dovecot-mailcow"
  "rspamd-mailcow"
  "clamd-mailcow"
  "nginx-mailcow"
)

FAILED=0
FAILED_LIST=""

for p in "${PATTERNS[@]}"; do
  running=$(docker ps \
    --filter "name=$p" \
    --filter "status=running" \
    --format '{{.Names}}')

  if [ -z "$running" ]; then
    FAILED=$((FAILED+1))
    FAILED_LIST="$FAILED_LIST $p"
  fi
done

# Message
if [ "$FAILED" -eq 0 ]; then
  MSG="All mailcow containers are running"
else
  MSG="Container down:$FAILED_LIST"
fi

cat <<EOF
<prtg>
  <result>
    <channel>Mailcow Containers</channel>
    <value>$FAILED</value>
    <unit>Count</unit>
    <limitmaxerror>0</limitmaxerror>
    <limitmode>1</limitmode>
  </result>
  <text>$MSG</text>
</prtg>
EOF

exit 0

Script permissions (required)
sudo chmod +x /var/prtg/scriptsxml/check_mailcow_containers.sh
________________________________________
Manually check on the server
sudo /var/prtg/scriptsxml/check_mailcow_containers.sh

Step 3: Restart probe services

Step 4: Add sensor Script ssh advanced

Result

0 That’s OK, 1 is the immediate warning.

Step 5: Demo the warning
🔥 REAL-WORLD TEST (recommended)
sudo docker stop mailcowdockerized-rspamd-mailcow-1
➡️ Script must return 0 → PRTG DOWN immediately

Restart
sudo docker start mailcowdockerized-rspamd-mailcow-1
➡️ Returns 1

________________________________________
#2. SSH Script Advanced – Mail Queue


Functions

• Monitors stuck mail queues

Channel
• Queue Count
📌 Queue increases = mail sent is blocked / blacklisted
🟢 Case 1 – Want to KNOW IMMEDIATELY when mail is blocked

Step 1: Create script
sudo nano /var/prtg/scriptsxml/check_mail_queue.sh

Content

💻
filename.sh
#!/bin/bash

# Get mail queue count (Postfix)
QUEUE_COUNT=$(postqueue -p 2>/dev/null | grep -c '^[A-F0-9]')

# Fallback if command is faulty
[ -z "$QUEUE_COUNT" ] && QUEUE_COUNT=0

# Message
if [ "$QUEUE_COUNT" -eq 0 ]; then
  MSG="Mail queue empty (outgoing OK)"
else
  MSG="Mail queue pending: $QUEUE_COUNT"
fi

cat <<EOF
<prtg>
  <result>
    <channel>Queue Count</channel>
    <value>$QUEUE_COUNT</value>
    <unit>Count</unit>
    <limitmaxwarning>100</limitmaxwarning>
    <limitmaxerror>500</limitmaxerror>
    <limitmode>1</limitmode>
  </result>
  <text>$MSG</text>
</prtg>
EOF

exit 0

Permissions and testing
sudo chmod +x /var/prtg/scriptsxml/check_mail_queue.sh
sudo /var/prtg/scriptsxml/check_mail_queue.sh

Step 2: Add sensor

Step 3: Set threshold
📌 Recommended configuration for sysadmin
Threshold Price Value
⚠️ Upper WARNING 1
❌ Upper ERROR 50
👉 Only 1 email in the queue → WARNING
________________________________________
🟡 Case 2 – Environment with many emails (avoid false alerts)
Threshold Value
⚠️ Warning 20
❌ Error 100
________________________________________
🔴 Case 3 – Only notify when an email is “truly corrupted”
Threshold Value
⚠️ Warning 100
❌ Error 500
👉 This is suitable for reporting, NOT suitable for real-time monitoring

#3. DNS Sensor (MX Record)


Advanced HTTP Sensor
Functions
• Checks for the existence of MX records

URL:

https://dns.google/resolve?name=tsf.id.vn&type=MX
Required keyword:

mail.tsf.id.vn
🚨 REASONABLE WARNING THRESHOLDS (DNS CHECK)
🔴 Loading Time
Status Value
⚠️ Warning > 1,500 ms
❌ Down > 5,000 ms
📌 DNS API typically <300ms
________________________________________
🟡 Time to First Byte
Status Value
⚠️ Warning > 800 ms
❌ Down > 3,000 ms

________________________________________
#4. Blacklist Check


Function
• Check if your mail IP is blacklisted

Step 1: Bash Script (run directly on the Mailcow VM or proxy)

sudo nano /var/prtg/scriptsxml/check_mail_blacklist.sh
Content

💻
filename.sh
#!/bin/bash

IP=$(curl -s https://api.ipify.org)
[ -z "$IP" ] && IP="UNKNOWN"

REVERSED_IP=$(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}')

RBL_LIST=(
  "zen.spamhaus.org"
  "bl.spamcop.net"
  "b.barracudacentral.org"
  "dnsbl.sorbs.net"
  "psbl.surriel.com"
)

COUNT=0
LISTED=""

for RBL in "${RBL_LIST[@]}"; do
  if dig +short ${REVERSED_IP}.${RBL} | grep -qE '^[0-9]'; then
    COUNT=$((COUNT+1))
    LISTED="$LISTED $RBL"
  fi
done

MSG="IP $IP clean"
[ "$COUNT" -gt 0 ] && MSG="IP $IP listed on:$LISTED"

cat <<EOF
<prtg>
  <result>
    <channel>Blacklist Count</channel>
    <value>$COUNT</value>
    <unit>Count</unit>
    <limitmaxwarning>0</limitmaxwarning>
    <limitmaxerror>1</limitmaxerror>
    <limitmode>1</limitmode>
  </result>
  <text>$MSG</text>
</prtg>
EOF

exit 0

Decentralize & test
sudo chmod +x /var/prtg/scriptsxml/check_mail_blacklist.sh

sudo /var/prtg/scriptsxml/check_mail_blacklist.sh
Example output:
0:OK – IP 27.xxx.xxx.xxx is clean
or
1:WARNING – Listed on dnsbl.sorbs.net
________________________________________

Step 2: Configure in PRTG

⛔ DO NOT scan too quickly, it is easy to be blocked by RBL

Step 3: Remove spam mail warnings (if any)
https://www.barracudacentral.org/rbl/removal-request

#5. Sensor – Rejected Incoming Mail (Spam Check)

🎯 Function
• Monitors rejected mail sent to the Mailcow server
• Detects:
o Domain/IP sending spam
o Mail blocked due to spam score
o Virus / policy reject

📌 Rejected Incoming Mail ≠ Mail Queue

Step 1: Create a script

sudo nano /var/prtg/scriptsxml/check_mail_incoming_reject.sh
Content

💻
filename.sh
#!/bin/bash

# Check time
MINUTES=5

# Container rspamd
RSPAMD_CONTAINER="mailcowdockerized-rspamd-mailcow-1"

# Timestamp từ MINUTES phút trước
SINCE_TS=$(date -d "$MINUTES minutes ago" +"%Y-%m-%d %H:%M")

# Count mail incoming reject
REJECT_COUNT=$(docker logs --since "$SINCE_TS" "$RSPAMD_CONTAINER" 2>/dev/null \
  | grep -i "action=reject" \
  | wc -l)

[ -z "$REJECT_COUNT" ] && REJECT_COUNT=0

# Message
if [ "$REJECT_COUNT" -eq 0 ]; then
  MSG="No incoming mail rejected in last ${MINUTES} minutes"
else
  MSG="Incoming rejected: $REJECT_COUNT mails in last ${MINUTES} minutes"
fi

cat <<EOF
<prtg>
  <result>
    <channel>Incoming Reject Count</channel>
    <value>$REJECT_COUNT</value>
    <unit>Count</unit>
    <limitmaxwarning>1</limitmaxwarning>
    <limitmaxerror>10</limitmaxerror>
    <limitmode>1</limitmode>
  </result>
  <text>$MSG</text>
</prtg>
EOF

exit 0

Decentralize and test run
sudo chmod +x /var/prtg/scriptsxml/check_mail_incoming_reject.sh
sudo /var/prtg/scriptsxml/check_mail_incoming_reject.sh

Step 2: Add sensor


Step 3: Set Threshold
🚨 Recommended Threshold
Value Level
⚠️ Warning 1
❌ Error 10
📌 Just one rejected incoming email → you’ll know immediately there’s a spam attack.