如何通过Bash脚本自动用Telnet测试SMTP?脚本优化与最佳实践
SMTP Test Script Fixes & Automation Best Practices
Error Analysis
The "improper command pipelining after DATA" error occurs because the original script sends all SMTP commands in one batch (pipelining) without waiting for the server's response after issuing the DATA command. SMTP servers require you to wait for a 354 response before transmitting the message body—skipping this step triggers the error.
Revised Script Fix
Here’s a fixed version of the script that handles command flow properly, validates server responses, and includes queue assertion:
#!/usr/bin/env bash set -euo pipefail # Configuration variables SMTP_SERVER="mailserver" SMTP_PORT=25 SENDER="sender@test.local" RECIPIENT="recipient@test.local" TEST_SUBJECT="Test $(date +%Y-%m-%d_%H_%M_%S)" TEST_BODY="A nice test" QUEUE_DIR="/var/spool/postfix/maildrop" # Adjust to your server's queue path # Open connection to SMTP server exec 3<>/dev/tcp/$SMTP_SERVER/$SMTP_PORT # Wait for server banner read -r -t 10 -u 3 line || { echo "Timeout waiting for banner"; exit 1; } if [[ ! "$line" =~ ^220 ]]; then echo "Failed to connect: $line" exit 1 fi # Send HELO echo "HELO test.local" >&3 read -r -t 10 -u 3 line || { echo "Timeout waiting for HELO response"; exit 1; } if [[ ! "$line" =~ ^250 ]]; then echo "HELO failed: $line" exit 1 fi # Send MAIL FROM echo "MAIL FROM:<$SENDER>" >&3 read -r -t 10 -u 3 line || { echo "Timeout waiting for MAIL FROM response"; exit 1; } if [[ ! "$line" =~ ^250 ]]; then echo "MAIL FROM failed: $line" exit 1 fi # Send RCPT TO echo "RCPT TO:<$RECIPIENT>" >&3 read -r -t 10 -u 3 line || { echo "Timeout waiting for RCPT TO response"; exit 1; } if [[ ! "$line" =~ ^250 ]]; then echo "RCPT TO failed: $line" exit 1 fi # Send DATA command echo "DATA" >&3 read -r -t 10 -u 3 line || { echo "Timeout waiting for DATA response"; exit 1; } if [[ ! "$line" =~ ^354 ]]; then echo "DATA failed: $line" exit 1 fi # Transmit message body echo "Subject: $TEST_SUBJECT" >&3 echo "" >&3 echo "$TEST_BODY" >&3 echo "." >&3 # Wait for message acceptance read -r -t 10 -u 3 line || { echo "Timeout waiting for DATA completion"; exit 1; } if [[ ! "$line" =~ ^250 ]]; then echo "Message rejected: $line" exit 1 fi # Send QUIT echo "QUIT" >&3 read -r -t 10 -u 3 line || { echo "Timeout waiting for QUIT response"; exit 1; } # Clean up connection exec 3>&- exec 3<&- echo "Test email sent successfully" # Assert email is in queue if ls "$QUEUE_DIR"/* 2>/dev/null | grep -q .; then echo "Email confirmed in queue" else echo "Email not found in queue" exit 1 fi
Key Improvements
- Uses bash’s built-in
/dev/tcpfor granular control over command flow instead ofnc - Adds 10-second timeouts to all read operations to prevent hanging
- Validates every server response against expected SMTP status codes
- Properly waits for the
354response before sending the message body - Includes explicit queue assertion (adjust
QUEUE_DIRto match your mail server’s queue path) - Enables strict error checking with
set -euo pipefail
Optimization Suggestions
- Make Configs Flexible: Allow overriding variables via command-line arguments or environment variables (e.g.,
SMTP_SERVER=$1orexport SMTP_SERVER=prod-mailserver) - Add TLS Support: For servers requiring STARTTLS, replace
/dev/tcpwithopenssl s_client -connect $SMTP_SERVER:$SMTP_PORT -starttls smtp - Logging: Redirect output to a log file (e.g.,
./smtp-test.sh >> test.log 2>&1) for debugging - Test Inbox Validation: Extend the script to check if the test email arrives in a dedicated test inbox (use
curlwith IMAP/POP3 APIs or tools likefetchmail)
Repeatable Automation Workflow for Config Changes
- Version Control Configs: Store all mail server config files (Postfix, Dovecot, etc.) in Git. Track every change to enable rollbacks.
- Idempotent Deployment: Use tools like Ansible or Docker Compose to apply config changes—ensure running the deployment multiple times doesn’t cause unintended side effects.
- Staging Environment Testing: Run the SMTP test script in a staging environment that mirrors production before applying changes to live systems.
- Post-Deployment Validation: Automatically run the SMTP script after config changes to confirm mail flow works. Integrate this into your CI/CD pipeline if available.
- Monitoring & Alerts: Set up monitoring for queue sizes, delivery rates, and error codes (e.g., Prometheus + Grafana). Trigger alerts if the test script fails.
Best Practices
- Isolate Tests: Run tests in a dedicated container or VM to avoid impacting production mail flow.
- Clean Up Test Data: Configure test emails to be delivered to a disposable inbox or automatically deleted from the queue after testing.
- Document Everything: Write clear docs for the test script, deployment workflow, and config change process so the entire team can follow it.
- Schedule Regular Tests: Set up cron jobs or CI/CD pipelines to run the SMTP script daily to catch issues early.
- Handle Credentials Securely: If your server requires authentication, store credentials in environment variables or a secrets manager instead of hardcoding them.
内容的提问来源于stack exchange,提问作者Kristi Jorgji
相关产品推荐
相关产品推荐

