Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison bin/bsmtp2dma @ 110:af4eeb94144a
Begin bsmtp2dma tool
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 14 Oct 2019 09:47:34 +0200 |
| parents | |
| children | fa73423234bf |
comparison
equal
deleted
inserted
replaced
| 109:0bd594fb56f8 | 110:af4eeb94144a |
|---|---|
| 1 #!/bin/sh | |
| 2 # -*- indent-tabs-mode: nil; -*- | |
| 3 : 'A simple replacement for Bacula `bsmtp` when the underlying mailer does | |
| 4 not listen on TCP ports (e.g. `dma`, `ssmtp` et al.). | |
| 5 | |
| 6 :Author: Franz Glasner | |
| 7 :Copyright: (c) 2019 Franz Glasner. | |
| 8 All rights reserved. | |
| 9 :License: BSD 3-Clause "New" or "Revised" License. | |
| 10 See LICENSE for details. | |
| 11 If you cannot find LICENSE see | |
| 12 <https://opensource.org/licenses/BSD-3-Clause> | |
| 13 :ID: @(#)@@PKGORIGIN@@ $HGid$ | |
| 14 | |
| 15 ' | |
| 16 | |
| 17 VERSION="@@VERSION@@" | |
| 18 | |
| 19 USAGE=' | |
| 20 USAGE: bsmtp2dma [OPTIONS] RECIPIENT ... | |
| 21 | |
| 22 Options: | |
| 23 | |
| 24 -8 Does nothing. Just a compatibility option for `bsmtp`. | |
| 25 | |
| 26 -d n Does nothing. Just a compatibility option for `bsmtp`. | |
| 27 | |
| 28 -f ADDRESS Set the "From:" header. | |
| 29 | |
| 30 -h MAILHOST:PORT Does nothing. Just a compatibility option for `bsmtp`. | |
| 31 | |
| 32 -n Do a dry-run: just print out what would be done | |
| 33 | |
| 34 -s SUBJECT Set the "Subject:" header | |
| 35 | |
| 36 -r ADDRESS Set the "Reply-To:" header | |
| 37 | |
| 38 -l NUMBER Does nothing. Just a compatibility option for `bsmtp`. | |
| 39 | |
| 40 -V Show the program version and usage and exit. | |
| 41 | |
| 42 | |
| 43 Usage: | |
| 44 | |
| 45 The body of the email message is read from standard input. Message is | |
| 46 ended by sending the `EOF` character (`Ctrl-D` on many systems) on the | |
| 47 start of a new line, much like many `mail` commands. | |
| 48 | |
| 49 ' | |
| 50 | |
| 51 # | |
| 52 # Configuration directory | |
| 53 # | |
| 54 : ${CONFIGDIR:=@@ETCDIR@@} | |
| 55 | |
| 56 test -r "${CONFIGDIR}/bsmtp2dma.conf" && . "${CONFIGDIR}/bsmtp2dma.conf" | |
| 57 | |
| 58 | |
| 59 # Default configuration values | |
| 60 : ${MAILER:=/usr/sbin/sendmail} | |
| 61 | |
| 62 | |
| 63 parse_addr() { | |
| 64 : 'Parse an possibly complex email address. | |
| 65 | |
| 66 Addresses can be of the form | |
| 67 | |
| 68 - Name Parts <user@domain.tld> | |
| 69 - user@domain.tld | |
| 70 | |
| 71 `Name Parts` may not contain ``<`` or ``>`` characters. | |
| 72 | |
| 73 Args: | |
| 74 _addr: the complex email address | |
| 75 | |
| 76 Returns: | |
| 77 0 on success, 1 on errors | |
| 78 | |
| 79 Output (Globals): | |
| 80 email_name: the name part (or empty) | |
| 81 email_addr: the technical address part (or empty) | |
| 82 | |
| 83 ' | |
| 84 local _addr | |
| 85 | |
| 86 _addr="$1" | |
| 87 | |
| 88 if printf "%s" "${_addr}" | grep -q -E -e '^[^<>]+<[^<>]+@[^<>]+>$'; then | |
| 89 email_name=$(printf '%s' "${_addr}" | sed -E -e 's/[[:space:]]*<.+$//') | |
| 90 email_addr=$(printf '%s' "${_addr}" | sed -E -e 's/^[^<>]+<//' | sed -E -e 's/>$//') | |
| 91 return 0 | |
| 92 fi | |
| 93 if printf "%s" "${_addr}" | grep -q -E -e '^[^<>]+@[^<>]+$'; then | |
| 94 email_name="" | |
| 95 email_addr="${_addr}" | |
| 96 return 0 | |
| 97 fi | |
| 98 return 1 | |
| 99 } | |
| 100 | |
| 101 | |
| 102 send_mail() { | |
| 103 : 'Send the mail via the underlying configured mailer (dma, sendmail et al.). | |
| 104 | |
| 105 Args: | |
| 106 _recipient: The recipient name. | |
| 107 | |
| 108 Will be written into the "To:" header also. | |
| 109 | |
| 110 Input (Globals): | |
| 111 MAILER | |
| 112 MAILCONTENT | |
| 113 MAILFIFO | |
| 114 CC | |
| 115 FROM | |
| 116 REPLYTO | |
| 117 SUBJECT | |
| 118 | |
| 119 Returns: | |
| 120 0 on success, other values on errors or the error exit code from the | |
| 121 underlying mailer | |
| 122 | |
| 123 ' | |
| 124 local _recipient _rc _oifs _text _pid_mailer | |
| 125 | |
| 126 _recipient="$1" | |
| 127 _rc=0 | |
| 128 | |
| 129 mkfifo -m 0600 "${MAILFIFO}" | |
| 130 _rc=$? | |
| 131 if [ ${_rc} -ne 0 ]; then | |
| 132 return ${_rc} | |
| 133 fi | |
| 134 | |
| 135 exec 3<>"${MAILFIFO}" | |
| 136 | |
| 137 "$MAILER" -f bacula@fmgapp7-bacula9.intern.feldmann-mg.com hostmaster@feldmann-mg.com <&3 & | |
| 138 _pid_mailer=$! | |
| 139 | |
| 140 # preserve leading white space when reading | |
| 141 _oifs="$IFS" | |
| 142 IFS=" | |
| 143 " | |
| 144 cat "${MAILCONTENT}" | | |
| 145 while read _text; do | |
| 146 printf "%s\n" "$_text" >&3 | |
| 147 done | |
| 148 printf ".\n" >&3 | |
| 149 | |
| 150 IFS="$_oifs" | |
| 151 | |
| 152 # close the fd to the pipe: coproc should get EOF | |
| 153 exec 3>&- | |
| 154 | |
| 155 wait $_pid_mailer | |
| 156 _rc=$? | |
| 157 | |
| 158 # we are done with the named pipe | |
| 159 rm -f "${MAILFIFO}" | |
| 160 | |
| 161 return ${_rc} | |
| 162 } | |
| 163 | |
| 164 | |
| 165 while getopts "V8c:f:h:l:nr:s:" _opt; do | |
| 166 case ${_opt} in | |
| 167 V) | |
| 168 echo "bsmtp2dma v${VERSION} (rv:@@HGREVISION@@)" | |
| 169 echo "$USAGE" | |
| 170 exit 0; | |
| 171 ;; | |
| 172 8) | |
| 173 : # VOID | |
| 174 ;; | |
| 175 c) | |
| 176 CC="$OPTARG" | |
| 177 ;; | |
| 178 f) | |
| 179 FROM="$OPTARG" | |
| 180 ;; | |
| 181 h) | |
| 182 : # VOID | |
| 183 ;; | |
| 184 l) | |
| 185 : # VOID | |
| 186 ;; | |
| 187 n) | |
| 188 DRYRUN="YES" | |
| 189 ;; | |
| 190 r) | |
| 191 REPLYTO="$OPTARG" | |
| 192 ;; | |
| 193 s) | |
| 194 SUBJECT="$OPTARG" | |
| 195 ;; | |
| 196 \?) | |
| 197 exit 2; | |
| 198 ;; | |
| 199 *) | |
| 200 echo "ERROR: inconsistent option handling" >&2 | |
| 201 exit 2; | |
| 202 ;; | |
| 203 esac | |
| 204 done | |
| 205 | |
| 206 # return code | |
| 207 _rc=0 | |
| 208 | |
| 209 DRYRUN="NO" | |
| 210 | |
| 211 MAILTMPDIR="$(mktemp -d)" | |
| 212 MAILFIFO="${MAILTMPDIR}/mail-stdin" | |
| 213 MAILCONTENT="${MAILTMPDIR}/mail-text" | |
| 214 | |
| 215 # | |
| 216 # Clean up existing temporary stuff on all sorts of exit | |
| 217 # (including the "exit" call (signal 0)) | |
| 218 # | |
| 219 trap 'if [ -d "${MAILTMPDIR}" ]; then rm -r "${MAILTMPDIR}"; fi; exit;' 0 1 2 15 | |
| 220 | |
| 221 test -d "${MAILTMPDIR}" || { echo "ERROR: no existing private tmp dir" >&2; exit 1; } | |
| 222 | |
| 223 # | |
| 224 # Reset the Shell's option handling system to prepare for handling | |
| 225 # other arguments and probably command-local options | |
| 226 # | |
| 227 shift $((OPTIND-1)) | |
| 228 OPTIND=1 | |
| 229 | |
| 230 # early check whether some recipients are given | |
| 231 if [ $# -eq 0 ]; then | |
| 232 echo "ERROR: no recipient given" >&2 | |
| 233 exit 2; | |
| 234 fi | |
| 235 | |
| 236 # | |
| 237 # Collect the mail text from stdin into a temporary file | |
| 238 # | |
| 239 exec 3>"${MAILCONTENT}" | |
| 240 # preserve leading white space when reading | |
| 241 _oifs="$IFS" | |
| 242 IFS=" | |
| 243 " | |
| 244 while read _text; do | |
| 245 if [ "${_text}" = "." ]; then | |
| 246 break | |
| 247 else | |
| 248 printf "%s\n" "${_text}" >&3 | |
| 249 fi | |
| 250 done | |
| 251 exec 3>&- | |
| 252 IFS="$_oifs" | |
| 253 | |
| 254 # | |
| 255 # Now send the content of the collected mail content to all recipients | |
| 256 # | |
| 257 until [ $# -eq 0 ]; do | |
| 258 send_mail "$1" | |
| 259 _rcsm=$? | |
| 260 if [ \( ${_rcsm} -ne 0 \) -a \( ${_rc} -eq 0 \) ]; then | |
| 261 _rc=${_rcsm} | |
| 262 fi | |
| 263 shift | |
| 264 done | |
| 265 | |
| 266 exit ${_rc} |
