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
#!/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
#!/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
#!/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
#!/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.