Current File : //usr/local/sbin/autoresponse |
#!/bin/bash
#+--------------------------------------------------------+
#|autoresponse 1.6.3 - an autoresponder script for postfix|
#| Charles Hamilton - musashi@nefaria.com |
#| This program is GNU/GPL software |
#+--------------------------------------------------------+
shopt -s -o nounset
shopt -s extglob
if [ "${#}" -eq "0" ]; then
printf "%s\n" "Autoresponse v. 1.6.3"
printf "%s\n" "Type -h for help"
exit 0
fi
declare RECIPIENT="unset"
declare SENDER="unset"
declare SASL_USERNAME="unset"
declare CLIENT_IP="unset"
declare AUTHENTICATED="unset"
declare AUTORESPONSE_MESSAGE="unset"
declare DISABLE_AUTORESPONSE="unset"
declare ENABLE_AUTORESPONSE="unset"
declare DELETE_AUTORESPONSE="unset"
declare SEND_RESPONSE="unset"
declare RESPONSES_DIR="/var/spool/autoresponse/responses"
declare SENDMAIL="/usr/sbin/sendmail"
declare RATE_LOG_DIR="/var/spool/autoresponse/log"
declare LOGGER="/usr/bin/logger"
#There are two different modes of operation:
# MODE="0" represents the actions that can not be executed from the command line
# MODE="1" represents the actions that can be executed from the command line
declare MODE="0"
#Time limit, in seconds that determines how often an
#autoresponse will be sent, per e-mail address (3600 = 1 hour, 86400 = 1 day)
declare RESPONSE_RATE="10"
while getopts "r:s:S:C:e:d:E:D:h" SWITCH; do
case "${SWITCH}" in
r) #Set the recipient's address
RECIPIENT="`echo ${OPTARG} | tr '[:upper:]' '[:lower:]'`"
SEND_RESPONSE="1"
;;
s) #Set the sender's address
SENDER="`echo ${OPTARG} | tr '[:upper:]' '[:lower:]'`"
SEND_RESPONSE="1"
;;
S) #If SASL_USERNAME exists then the user was authenticated
SASL_USERNAME="${OPTARG}"
if [ -z "${SASL_USERNAME}" ]; then
AUTHENTICATED="0"
else
AUTHENTICATED="1"
fi
;;
C) #IP address of client (sender)
CLIENT_IP="${OPTARG}"
;;
e) #Set the filename of the user's autoresponse message
#This is used for creating/editing new autoresponse messages
AUTORESPONSE_MESSAGE="${OPTARG}"
MODE="1"
;;
d) #Disable an existing autoresponse message
DISABLE_AUTORESPONSE="${OPTARG}"
MODE="1"
;;
E) #Enable an existing autoresponse message
ENABLE_AUTORESPONSE="${OPTARG}"
MODE="1"
;;
D) #Delete an existing autoresponse message
DELETE_AUTORESPONSE="${OPTARG}"
MODE="1"
;;
h|*) #Print the help dialog and exit
echo -e "\n${0} [-r {recipient email} -s {sender email} -S {sasl username} -C {client ip}] [-e {email address}] [-d {email address}] [-E {email address}] [-D {email address}] [-h]\n"
echo -e " -r, -s, -S, and optionally -C must be used together to specify a recipient, sender, sasl username, and client IP of an autoresponse message."
echo -e " Normally you configure these in postfix's \"master.cf\" but they can be used from the terminal as well (only for testing purposes!)."
echo -e " If this is executed from a terminal, you'll need to hit CTRL-D when you are finished typing your autoresponse message.\n"
echo " -e is used to create a new autoresponse or edit an existing one for the specified user."
echo -e " If a disabled autoresponse message exists, it will be ignored and a new message will be created.\n"
echo -e " -d is used to disable an existing active autoresponse message.\n"
echo " -E is used to enable an existing autoresponse message. If both a disabled AND and an active autoresponse message exist,"
echo -e " the active message will be overwritten by the disabled one.\n"
echo -e " -D is used to delete an existing autoresponse message, it will not delete disabled autoresponse messages.\n"
echo -e " -h prints this help menu\n"
exit 0
;;
esac
done
#If a SASL authenticated user wants to set their autoresponse message via e-mail...
if [ "${AUTHENTICATED}" = "1" ] && [ "${RECIPIENT/@*/}" = "${SENDER/@*/+autoresponse}" ] && [ "${MODE}" = "0" ]; then
if [ -f "${RESPONSES_DIR}/${SENDER}" ]; then
#Delete a user's existing autoresponse message.
(${0} -D "${SENDER}")
if [ ! -f "${RESPONSES_DIR}/${SENDER}" ]; then
${LOGGER} -i -t autoresponse -p mail.notice "Autoresponse disabled for address: ${SENDER} by SASL authenticated user: ${SASL_USERNAME} from: ${CLIENT_IP}"
(echo -e "From: ${RECIPIENT}\nTo: ${SENDER}\nSubject: Out of Office\n\n"
echo "Autoresponse disabled for ${SENDER} by SASL authenticated user: ${SASL_USERNAME} from: ${CLIENT_IP}") | ${SENDMAIL} -i -f "${RECIPIENT}" "${SENDER}"
else
${LOGGER} -i -t autoresponse -p mail.notice "Autoresponse could not be disabled for address: ${SENDER}"
fi
elif [ ! -f "${RESPONSES_DIR}/${SENDER}" ]; then
#Read from STDIN and save this as the user's autoresponse message.
#This will overwrite any pre-existing autoresponse messages!
cat > "${RESPONSES_DIR}/${SENDER}"
if [ -f "${RESPONSES_DIR}/${SENDER}" ]; then
${LOGGER} -i -t autoresponse -p mail.notice "Autoresponse enabled for address: ${SENDER} by SASL authenticated user: ${SASL_USERNAME} from: ${CLIENT_IP}"
(echo -e "From: ${RECIPIENT}\nTo: ${SENDER}\nSubject: Out of Office\n\n"
echo "Autoresponse enabled for ${SENDER} by SASL authenticated user: ${SASL_USERNAME} from: ${CLIENT_IP}") | ${SENDMAIL} -i -f "${RECIPIENT}" "${SENDER}"
else
${LOGGER} -i -t autoresponse -p mail.notice "Autoresponse could not be enabled for address: ${SENDER}"
fi
fi
#Log any unauthenticated shenanigans. We're attempting to prevent two scenarios here:
#
#(1) A user sends an e-mail to user+autoresponse@domain.tld from user@domain.tld through an open relay
# in an unauthorized attempt to set an autoresponse for the real user@domain.tld. The open relay
# will relay the message but because it will not authenticate with the mail server for domain.tld
# AUTHENTICATED will equal 0 and the user portion of the recipient address will equal user+autoresponse.
# Since we do not allow unauthenticated users to set autoresponse messages, we log this attempt as
# suspicious and exit cleanly so that postfix doesn't generate a bounce message.
#
#(2) A user sends e-mail to user+autoresponse@domain.tld from user@domain.tld through a mail server
# that requires authentication, (but allows relaying) and has autoresponse configured. This will result in
# an autoresponse toggle message being sent to the real user@domain.tld, notifying them that their
# autoresponse message has been enabled or disabled when in fact it has not. This scenario is rarer
# than the first and it is mainly meant to protect against compromised accounts and/or potential abuse
# by legitimate users of the rogue mail server.
#
elif [ "${AUTHENTICATED}" = "0" ] && [ "${RECIPIENT/@*/}" = "${SENDER/@*/+autoresponse}" ] || [ "${SENDER/@*/+autoresponse}" = "${RECIPIENT/@*/+autoresponse+autoresponse}" ] && [ "${MODE}" = "0" ]; then
${LOGGER} -i -t autoresponse -p mail.warning "Unauthenticated attempt to set autoresponse message for ${SENDER/+autoresponse/} from ${CLIENT_IP}!"
exit 0
#Finally, if the user recipient address does not equal user+autoresponse then we assume that it's
#just a normal message. We check to see if the recipient has an autoresponse message set; if one
#has not already been sent to the sender within our timeframe, we send it and then we deliver the
#original message to the original recipient.
#elif [ "${RECIPIENT/@*/}" != "${SENDER/@*/+autoresponse}" ] && [ "${MODE}" = "0" ]; then
elif [ "${MODE}" = "0" ]; then
rate_log_check() {
#Only send one autoresponse per e-mail address per the time limit (in seconds) designated by the RESPONSE_RATE variable
if [ -f "${RATE_LOG_DIR}/${RECIPIENT}/${SENDER}" ]; then
declare ELAPSED_TIME=`echo $[\`date +%s\` - \`stat -c %X "${RATE_LOG_DIR}/${RECIPIENT}/${SENDER}"\`]`
if [ "${ELAPSED_TIME}" -lt "${RESPONSE_RATE}" ]; then
${LOGGER} -i -t autoresponse -p mail.notice "An autoresponse has already been sent from ${RECIPIENT} to ${SENDER} within the last ${RESPONSE_RATE} seconds"
SEND_RESPONSE=0
fi
fi
}
if [ -f "${RESPONSES_DIR}/${RECIPIENT}" ]; then
rate_log_check
#If SEND_RESPONSE still equals "1" after the rate_log_check function, send an autoresponse.
# if [ "${SEND_RESPONSE}" = "1" ] && [ "${RECIPIENT}" != "${SENDER}" ]; then
if [ "${SEND_RESPONSE}" = "1" ]; then
(cat "${RESPONSES_DIR}/${RECIPIENT}") | sed -e "0,/^$/ { s/^To:.*/To: <${SENDER}>/ }" -e '0,/^$/ { /^Date:/ d }' | ${SENDMAIL} -i -f "${RECIPIENT}" "${SENDER}"
mkdir -p "${RATE_LOG_DIR}/${RECIPIENT}"
touch "${RATE_LOG_DIR}/${RECIPIENT}/${SENDER}"
${LOGGER} -i -t autoresponse -p mail.notice "Autoresponse sent from ${RECIPIENT} to ${SENDER}"
fi
fi
exec ${SENDMAIL} -i -f "${SENDER}" "${RECIPIENT}"
fi
#Check to see if we are editing or creating a new autoresponse for a user.
#This should only be used from the command line unlike -D, -d, and -E which
#could be used via postfix pipe or in other areas where no user interaction
#is required.
if [ "${AUTORESPONSE_MESSAGE}" != "unset" ] && [ "${MODE}" = "1" ]; then
#Check to see if an autoresponse message exists for the email address specified by the "AUTORESPONSE_MESSAGE" parameter, if one exists
#then edit the existing one, if one does not exist, create a new one. This action will ignore any disabled autoresponse messages.
if [ -f "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}" ]; then
vi "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}"
elif ! [ -f "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}" ]; then
vi "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}"
if [ -f "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}" ]; then
#Insert our mail headers; people who will be setting autoresponses from the command line
#hopefully will know better than to screw with these when editing an existing autoresponse.
sed -i "1i\From: ${AUTORESPONSE_MESSAGE}\nTo: THIS GETS REPLACED\nSubject: Out Of Office\n\n" "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}"
fi
fi
if [ -f "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}" ]; then
chown autoresponse.autoresponse "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}"
chmod 600 "${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE}"
else
echo "Editing ${RESPONSES_DIR}/${AUTORESPONSE_MESSAGE} aborted!"
exit 1
fi
#Are we disabling an existing autoresponse message?
elif [ "${DISABLE_AUTORESPONSE}" != "unset" ] && [ "${MODE}" = "1" ]; then
if [ -f "${RESPONSES_DIR}/${DISABLE_AUTORESPONSE}" ]; then
mv -i "${RESPONSES_DIR}/${DISABLE_AUTORESPONSE}" "${RESPONSES_DIR}/${DISABLE_AUTORESPONSE}_DISABLED"
elif ! [ -f "${RESPONSES_DIR}/${DISABLE_AUTORESPONSE}" ]; then
echo "${RESPONSES_DIR}/${DISABLE_AUTORESPONSE} does not exist thus, it cannot be disabled!"
exit 1
fi
#Are we enabling an existing autoresponse message?
elif [ "${ENABLE_AUTORESPONSE}" != "unset" ] && [ "${MODE}" = "1" ]; then
if [ -f "${RESPONSES_DIR}/${ENABLE_AUTORESPONSE}_DISABLED" ]; then
mv -i "${RESPONSES_DIR}/${ENABLE_AUTORESPONSE}_DISABLED" "${RESPONSES_DIR}/${ENABLE_AUTORESPONSE}"
elif ! [ -f "${RESPONSES_DIR}/${ENABLE_AUTORESPONSE}_DISABLED" ]; then
echo "There is no disabled autoresponse for ${ENABLE_AUTORESPONSE}"
exit 1
fi
#Are we deleting an existing autoresponse message (this does not delete disabled autoresponse messages)?
elif [ "${DELETE_AUTORESPONSE}" != "unset" ] && [ "${MODE}" = "1" ]; then
if [ -f "${RESPONSES_DIR}/${DELETE_AUTORESPONSE}" ]; then
rm "${RESPONSES_DIR}/${DELETE_AUTORESPONSE}"
elif ! [ -f "${RESPONSES_DIR}/${DELETE_AUTORESPONSE}" ]; then
echo "${RESPONSES_DIR}/${DELETE_AUTORESPONSE} does not exist thus, it cannot be deleted!"
exit 1
fi
fi