Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
view sbin/bsmtp2dma @ 145:c4e9099a3d3e
FIX: Really use "printf" instead of "echo" when printing the version
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Wed, 30 Oct 2019 21:13:00 +0100 |
| parents | 6be3742d21f7 |
| children | dc3ac7fc06ea |
line wrap: on
line source
#!/bin/sh # -*- indent-tabs-mode: nil; -*- : 'A simple replacement for Bacula `bsmtp` when the underlying mailer does not listen on TCP ports (e.g. `dma`, `ssmtp` et al.). :Author: Franz Glasner :Copyright: (c) 2019 Franz Glasner. All rights reserved. :License: BSD 3-Clause "New" or "Revised" License. See LICENSE for details. If you cannot find LICENSE see <https://opensource.org/licenses/BSD-3-Clause> :ID: @(#)@@PKGORIGIN@@ $HGid$ ' VERSION="@@VERSION@@" USAGE=' USAGE: bsmtp2dma [OPTIONS] RECIPIENT ... Options: -V Show the program version and usage and exit. -8 Does nothing. Just a compatibility option for `bsmtp`. -c ADDRESS Set then "CC:" header. -d n Does nothing. Just a compatibility option for `bsmtp`. -f ADDRESS Set the "From:" header. -h MAILHOST:PORT Does nothing. Just a compatibility option for `bsmtp`. -l NUMBER Does nothing. Just a compatibility option for `bsmtp`. -r ADDRESS Set the "Reply-To:" header -s SUBJECT Set the "Subject:" header Usage: The body of the email message is read from standard input. Message is ended by sending the `EOF` character (`Ctrl-D` on many systems) on the start of a new line, much like many `mail` commands. Files: The shell style configuration file in @@ETCDIR@@/bsmtp2dma.conf is sourced in at script start. ' # # Configuration directory # : ${CONFIGDIR:=@@ETCDIR@@} test -r "${CONFIGDIR}/bsmtp2dma.conf" && . "${CONFIGDIR}/bsmtp2dma.conf" # # Default configuration values # # `sendmail` is also valid for `dma` because of the mapping within # `/etc/mail/mailer.conf` # : ${MAILER:=/usr/sbin/sendmail} parse_addr() { : 'Parse an possibly complex email address. Addresses can be of the form - Name Parts <user@domain.tld> - user@domain.tld `Name Parts` may not contain ``<`` or ``>`` characters. Args: _addr: the complex email address Returns: 0 on success, 1 on errors Output (Globals): email_name: the name part (or empty) email_addr: the technical address part (or empty) ' local _addr _addr="$1" test -n "${_addr}" || return 1 if printf "%s" "${_addr}" | grep -q -E -e '^[^<>]+<[^<>]+@[^<>]+>$'; then email_name=$(printf '%s' "${_addr}" | sed -E -e 's/[[:space:]]*<.+$//') email_addr=$(printf '%s' "${_addr}" | sed -E -e 's/^[^<>]+<//' | sed -E -e 's/>$//') return 0 fi if printf "%s" "${_addr}" | grep -q -E -e '^[^<>]+@[^<>]+$'; then email_name="" email_addr="${_addr}" return 0 fi return 1 } send_mail() { : 'Send the mail via the underlying configured mailer (dma, sendmail et al.). Args: _recipient: The recipient name. Will be written into the "To:" header also. Input (Globals): MAILER MAILCONTENT MAILFIFO_STDIN MAILFIFO_STDOUT CC FROM REPLYTO SUBJECT Returns: 0 on success, other values on errors or the error exit code from the underlying mailer This procedure starts the configured mailer as coproc and sends email headers and contents to the started mailer. ' local _recipient _rc _oifs _text _pid_mailer _recipient_addr local _from_from _from_addr _sender_addr _dummy _recipient="$1" _rc=0 if parse_addr "${_recipient}"; then _recipient_addr="${email_addr}" else echo "ERROR: unknown recipient address format in \`${_recipient}'" >&2 return 1 fi _sender_addr="$(whoami)@$(hostname -f)" if [ -z "${FROM}" ]; then _from_addr="${_sender_addr}" _from_from="${_from_addr}" else if parse_addr "${FROM}"; then _from_from="${FROM}" _from_addr="${email_addr}" else echo "ERROR: unknown sender name in \`${FROM}'" >&2 return 1 fi fi mkfifo -m 0600 "${MAILFIFO_STDIN}" _rc=$? if [ ${_rc} -ne 0 ]; then return ${_rc} fi mkfifo -m 0600 "${MAILFIFO_STDOUT}" _rc=$? if [ ${_rc} -ne 0 ]; then rm -f "${MAILFIFO_STDIN}" return ${_rc} fi # # Start the mailer **before** opening the pipe; otherwise a # deadlock occurs # "$MAILER" -f "${_sender_addr}" "${_recipient_addr}" <${MAILFIFO_STDIN} >${MAILFIFO_STDOUT} & _pid_mailer=$! exec 3>"${MAILFIFO_STDIN}" exec 4<"${MAILFIFO_STDOUT}" printf "To: %s\n" "${_recipient}" >&3 printf "From: %s\n" "${_from_from}" >&3 if [ "${_sender_addr}" != "${_from_addr}" ]; then printf "Sender: %s\n" "${_sender_addr}" >&3 fi if [ -n "${SUBJECT}" ]; then printf "Subject: %s\n" "${SUBJECT}" >&3 fi if [ -n "${REPLYTO}" ]; then # # XXX TBD proper Reply-To header value checks: # a comma separated list of full mail addresses # printf "Reply-To: %s\n" "${REPLYTO}" >&3 fi if [ -n "${CC}" ]; then # # XXX TBD proper CC header value checks: # a comma separated list of full mail addresses # printf "Cc: %s\n" "${CC}" >&3 fi printf "\n" >&3 # preserve leading white space when reading with `read` _oifs="$IFS" IFS=" " cat "${MAILCONTENT}" | while read _text; do printf "%s\n" "$_text" >&3 done # not all mailer recognize this # printf ".\n" >&3 IFS="$_oifs" # close the fd to the pipe: coproc should get EOF and terminate exec 3>&- # read eventually remaining stuff from the mailer until EOF IFS='' read _dummy <&4 exec 4<&- wait $_pid_mailer _rc=$? # we are done with the named pipes rm -f "${MAILFIFO_STDIN}" rm -f "${MAILFIFO_STDOUT}" return ${_rc} } while getopts "V8c:d:f:h:l:nr:s:" _opt; do case ${_opt} in V) printf 'bsmtp2dma v%s (rv:%s)\n' "${VERSION}" '@@HGREVISION@@' echo "$USAGE" exit 0; ;; 8) : # VOID ;; c) CC="$OPTARG" ;; d) : # VOID ;; f) FROM="$OPTARG" ;; h) : # VOID ;; l) : # VOID ;; r) REPLYTO="$OPTARG" ;; s) SUBJECT="$OPTARG" ;; \?) exit 2; ;; *) echo "ERROR: inconsistent option handling" >&2 exit 2; ;; esac done # return code _rc=0 MAILTMPDIR="$(mktemp -d)" MAILFIFO_STDIN="${MAILTMPDIR}/mail-stdin" MAILFIFO_STDOUT="${MAILTMPDIR}/mail-stdout" MAILCONTENT="${MAILTMPDIR}/mail-text" # # Clean up existing temporary stuff on all sorts of exit # (including the "exit" call (signal 0)) # trap 'if [ -d "${MAILTMPDIR}" ]; then rm -rf "${MAILTMPDIR}"; fi; exit;' 0 1 2 15 test -d "${MAILTMPDIR}" || { echo "ERROR: no existing private tmp dir" >&2; exit 1; } # # Reset the Shell's option handling system to prepare for handling # other arguments and probably command-local options # shift $((OPTIND-1)) OPTIND=1 # early check whether some recipients are given if [ $# -eq 0 ]; then echo "ERROR: no recipient given" >&2 exit 2; fi # # Collect the mail text from stdin into a temporary file # exec 3>"${MAILCONTENT}" # preserve leading white space when reading with `read` _oifs="$IFS" IFS=" " while read _text; do if [ "${_text}" = "." ]; then break else printf "%s\n" "${_text}" >&3 fi done exec 3>&- IFS="$_oifs" # # Now send the content of the collected mail content to all recipients # until [ $# -eq 0 ]; do send_mail "$1" _rcsm=$? if [ \( ${_rcsm} -ne 0 \) -a \( ${_rc} -eq 0 \) ]; then _rc=${_rcsm} fi shift done exit ${_rc}
