#!/bin/bash # Use ssmtp to send an email message if [ $# -eq 0 ]; then echo "sendmsg: Usage sendmsg [ options [ optArg ] | recipientAddress ] ..." >&2 exit 1 fi # Tabs here: # sendmsg: Usage sendmsg [ options [ optArg ] | recipientAddress ] ... # Options: # -s subjectString # Establish the message's subject header # -t recipientAddrress # Add a primary recipient # -c ccAddress # Add a carbon-copy recipient # -b blindCCAddress # -bc blindCCAddress # -bcc blindCCAddress # Add a blind carbon-copy recipient # -m messageBodyFile # Specify a file containing message content # # May be repeated. A single hyphen causes # # the standard input to be be read # -f senderAddress # Establish the sender's (from) address # -fn senderFullName # -F senderFullName # Establish the sender's full name # -r replyToAddress # -rt replyToAddress # Establish a "Reply-To:" header # -nd # -nt # Do not add a \"Date:\" header field # -d dateString # Specify the contents of the \"Date:\" header # # Note: Do not include the \"Date: portion\" # -ppp # Re-create /etc/ssmtp/ssmtp.conf # -q queueFile # Enqueue message in specified queue file # -pq queueFile # Print headers of mail queued in specified queue file # -sq queueFile # Send mail queued in specified queue file # # based on current PPP connection # -h | -help | --help # Show this usage summary # Spaces here: usageSummary="# sendmsg: Usage sendmsg [ options [ optArg ] | recipientAddress ] ... # Options: # -s subjectString # Establish the message's subject header # -t recipientAddrress # Add a primary recipient # -c ccAddress # Add a carbon-copy recipient # -b blindCCAddress # -bc blindCCAddress # -bcc blindCCAddress # Add a blind carbon-copy recipient # -m messageBodyFile # Specify a file containing message content # # May be repeated. A single hyphen causes # # the standard input to be be read # -fn senderFullName # -F senderFullName # Establish the sender's full name # -r replyToAddress # -rt replyToAddress # Establish a "Reply-To:" header # -nd # -nt # Do not add a \"Date:\" header field # -d dateString # Specify the contents of the \"Date:\" header # # Note: Do not include the \"Date: portion\" # -ppp # Re-create /etc/ssmtp/ssmtp.conf # -q queueFile # Enqueue message in specified queue file # -pq queueFile # Print headers of mail queued in specified queue file # -sq queueFile # Send mail queued in specified queue file # # based on current PPP connection # -h | -help | --help # Show this usage summary " showUsage() { echo "$usageSummary" } # Extract an option argument from the script's positional parameters # Note: unfinished and wrong... optArg() { if [ $# -lt 1 ]; then echo "sendmsg: \"$1\" option requires an argument" 2>&1 quitEarly=1 else eval "$2=$1" shift fi } # Perl-like join operator join() { out= sep="$1" shift for elt; do [ -z "$out" ] && out="$elt" || out="$out$sep$elt" done echo -n "$out" } quoteAll() { quoteChar=$1 shift for elt do echo -n "$quoteChar${elt//$quoteChar/\\$quoteChar/}$quoteChar " done } declare -a recipients declare -a carbons declare -a blindCarbons declare -a bodyFiles declare -a fromArgs noTimeStamp= timeStamp="$(date +'%a, %d %b %Y %T %z')" fromAddr= fromName= replyToAddr= doPPPConfig= messageQueueFile= sendQueueFile= printQueueFile= quitEarly= # Append entries to the array whose name is the first argument appenda() { aName="$1" shift for aSlot; do appendCmd="$aName[\${#$aName[@]}]=\"$aSlot\"" eval "$appendCmd" done } while [ $# -gt 0 ]; do arg="$1" nextArg="$2" shift case "$arg" in -s) # Subject subject="$nextArg" shift ;; -t) # Primary recipient appenda recipients "$nextArg" shift ;; -c | -cc) # Carbon copy recipient appenda carbons "$nextArg" shift ;; -b | -bc | -bcc) # Blind carbon copy recipient appenda blindCarbons "$nextArg" shift ;; -m) # Message body file appenda bodyFiles "$nextArg" shift ;; -f) # Sender (From:) address fromAddr="$nextArg" shift ;; -F | -fn) # Sender (From:) name fromName="$nextArg" shift ;; -r | -rt) # Reply-To address replyToAddr="$nextArg" shift ;; -nt | -nd) # Inhibit "Date:" header noTimestamp=1 ;; -d) # Specify time-stamp value timeStamp="$nextArg" shift ;; -q) # Enqueue the message for later sending messageQueueFile="$nextArg" shift ;; -sq) # Send queued messages sendQueueFile="$nextArg" shift ;; -pq) # List queued messages printQueueFile="$nextArg" shift ;; -ppp) # Run smtp-ppp-config before sending doPPPConfig=1 ;; -h | -help | --help) # Provide usage summary showUsage quitEarly=0 ;; -*) echo "sendmsg: Unrecognized option \"$arg\" (\"sendmsg --help\" for usage summary)" >&2 quitEarly=1 ;; *) # Other arguments are assumed to be primary recipient addresses appenda recipients "$arg" ;; esac done # Stop now? if [ "$quitEarly" ]; then exit $quitEarly fi # Configure for PPP link? if [ "$doPPPConfig" -a -n "$messageQueueFile" ]; then if ssmtp-ppp-config; then : else echo "sendmsg: Unable to configure email for PPP" fi fi # Quit now if there is nothing left to do if [ ${#recipients[@]} -eq 0 -a ${#carbons[@]} -eq 0 -a ${#blindCarbons[@]} -eq 0 \ -a -z "$printQueueFile" -a -z "$sendQueueFile" ]; then echo "sendmsg: No-op" exit 0 fi # Prepare "From:" options for ssmtp if [ -n "$fromAddr" -o -n "$fromName" ]; then if [ -n "$messageQueueFile" ]; then fromArgs=("\"-f$fromAddr\"" "\"-F$fromName\"") else fromArgs=("-f$fromAddr" "-F$fromName") fi fi # Synthesize the message if [ ${#recipients[@]} -gt 0 -o ${#carbons[@]} -gt 0 -o ${#blindCarbons[@]} -gt 0 ]; then ( # Synthesize header fields if [ ! "$noTimeStamp" ]; then echo "Date: $timeStamp" fi # if [ -n "$fromAddr" ]; then # if [ -n "$fromName" ]; then # echo "From: ${echo "$fromName" |tr -d "!@#$%^&*()+={}[]:;\"'<>,.?/"} <$fromAddr>" # else # echo "From: $fromAddr" # fi # fi if [ -n "$replyToAddr" ]; then echo "Reply-To: $replyToAddr" fi if [ -n "$subject" ]; then echo "Subject: $subject" fi if [ ${#recipients[@]} -gt 0 ]; then echo "To: $(join ", " "${recipients[@]}")" fi if [ ${#carbons[@]} -gt 0 ]; then echo "CC: $(join ", " "${carbons[@]}")" fi if [ ${#blindCarbons[@]} -gt 0 ]; then for bccRecipient in "${blindCarbons[@]}"; do echo "BCC: $bccRecipient" done fi echo # Generate and / or collect (from standard input) the body of the message cat "${bodyFiles[@]}" ) | ( # Queue for later or send now? if [ -n "$messageQueueFile" ]; then # Queue the message for later eomTag="EOM_$(date +'%Y%m%d%H%M%S')" ( echo "ssmtp $(quoteAll \" "${fromArgs[@]}" "${recipients[@]}" "${carbons[@]}" "${blindCarbons[@]}") <<$eomTag" cat echo "$eomTag"$'\n\n' )>>"$messageQueueFile" else # Send the message on its way: ssmtp "${fromArgs[@]}" "${recipients[@]}" "${carbons[@]}" "${blindCarbons[@]}" fi ) fi # List queued messages if [ -n "$printQueueFile" ]; then if [ -s "$printQueueFile" ]; then sed -n -e '/^ssmtp/,/^$/p' "$printQueueFile" |egrep -v '^ssmtp' else echo "sendmsg: No messages are currently queued in \"$printQueueFile\"" fi fi # Send queued messages if [ -n "$sendQueueFile" -a -s "$sendQueueFile" ]; then # Configure for PPP link? if [ "$doPPPConfig" -a -n "$messageQueueFile" ]; then if ssmtp-ppp-config; then : else echo "sendmsg: Unable to configure ssmtp for PPP" fi fi source "$sendQueueFile" # Rename the file with a timestamp of the time it was sent mv "$sendQueueFile" "$sendQueueFile-$(date +'%Y-%m-%d@%H-%M-%S')" fi