#!/usr/bin/bash ############################################################################################################# # check-postfix.sh # ############################################################################################################# # # # This script is just something I cooked up for work. I setup a server with posftix configured as an` # # email/smtp relay so that some of our old equipment can still function without having to try and # # configure our commercial Email Server to accept unauthed requests to send email. # # # # This requres a few packages to be installed: # # - postfix (of course) # # - telnet # # - sendmail # # # # The issue is if the postfix service dies and fails to come back up after a restart via this script, # # you will be unable to send any emails via a smtp client (as they will try to contact the service # # on the server itself). So the only workaround I was able to find is to manually send the email via # # telnet using a coproc. You could use a smtp library with python or perl, but I like to keep these # # scripts using a single language wherever possible. # # # # Since telnet is just a basic tcp client we are able to interact with the smpt port on a mailserver # # (port 25). So setting it up as coproc allows us to run a concurrent process and pipe commands into # # the file-descriptor to send the commands to the mailserver. Which allows us to manually send an email # # to an authoritative email server (provided they don't have your IP blocklisted or are filtering # # traffic on port 25). # # # ############################################################################################################# # BEGIN: Variables ## Duration to wait to see if service has come back up DURATION=10 ## Wait duration to send next part of message WAIT=1 ## Test flag TEST=0 ## Email addresses NOTIFY_EMAIL=recipient@domain.com MAIL_FROM=username@domain.net FROM_DOMAIN=` echo $FROM_EMAIL | cut -d @ -f 2 ` DAMAIN=` echo $NOTIFY_EMAIL | cut -d @ -f 2 ` # END: Variables # BEGIN: Helper Functions send_email () { local MESSAGE="${1:?"send_email: No message was passed through"}" sendmail $NOTIFY_EMAIL <<< "$MESSAGE" } : " The only option is to manually telnet to the smtp port on the authoritative mailserver for the target domain. As otherwise unless a mail-host is configured as an email relay, you will be unable to send an email to a user outside of the mailservers domain (without authentication). " do_emergency_email () { local MESSAGE="${1:-"The Postfix service has failed to come up on `hostname` (`hostname -i`) after a service restart. Please ssh into server to troubleshoot the issues."}" ## Getting a mailserver IP for manual message MAILSERVER=`dig $DOMAIN mx | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1` ## Setting up coprocess to send commands to telnet session coproc TELNET { telnet $MAILSERVER 25; } ## Commands to send email manually local -a commands=( "ehlo $FROM_DOMAIN\n" "mail from: <$MAIL_FROM>\n" "rcpt to: <$NOTIFY_EMAIL>\n" "data\n" "Subject: Postfix Service Failure\nFrom: $MAIL_FROM\nTo: $NOTIFY_EMAIL\n" "$MESSAGE\n\n.\n" "quit\n" ) ## Iterate through commands and send them to coprocesses ### We need to wait before each command as the remote mailserver will not catch everything otherwise. for i in ${!commands[@]}; do COMMAND="${commands[$i]}" echo -e "$COMMAND" >&${TELNET[1]} sleep $WAIT done } # END: Helper Functions # BEGIN: Test Check if [[ $TEST -eq 1 ]]; then MESSAGE_1=" This is a test message to verify that postfix can send an email " send_email "$MESSAGE_1" MESSAGE_2="This is a test email to make sure the postfix crash workaround email works" do_emergency_email "$MESSAGE_2" exit fi # END: Test Check # BEGIN: Work if [[ `systemctl is-active postfix` != 'active' ]]; then systemctl restart postfix sleep $DURATION SERVICE_STATUS=` systemctl is-active postfix ` if [[ "$SERVICE_STATUS" == 'active' ]]; then MESSAGE=" SUBJECT: Postfix Service Failure FROM: root TO: $NOTIFY_EMAIL The postfix service on `hostname` (`hostname -i`) was found to be not running. The service has been restarted, and after waiting $DURATION seconds it was found to be $SERVICE_STATUS. " send_email "$MESSAGE" else do_emergency_email fi fi # END: Work