Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
annotate sbin/bsmtp2dma @ 778:84527b00d29a
farray.sh: Implement Heapsort in the "standard" implementation.
BUGS: Performance here equals Shellsort.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 25 Oct 2024 20:29:04 +0200 |
| parents | 599fddb2370d |
| children | e2f262ec2bf4 |
| rev | line source |
|---|---|
| 110 | 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 | |
|
438
9c3b1966ba91
Extend copyright to 2024
Franz Glasner <fzglas.hg@dom66.de>
parents:
386
diff
changeset
|
7 :Copyright: (c) 2019-2024 Franz Glasner. |
| 110 | 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> | |
|
386
84d2735fe7f6
Simplified version tagging a lot: it is also faster now.
Franz Glasner <fzglas.hg@dom66.de>
parents:
317
diff
changeset
|
13 :ID: @(#)@@SIMPLEVERSIONTAG@@ |
| 110 | 14 |
| 15 ' | |
| 16 | |
|
643
4f2257ea7d0a
shellcheck: disable SC2034: VERSION appears unused...
Franz Glasner <fzglas.hg@dom66.de>
parents:
550
diff
changeset
|
17 # shellcheck disable=SC2034 # VERSION appears unused |
|
550
847ae246f3cc
Make the port really DATADIR and EXAMPLESDIR safe because the user may redefine DATADIR and EXAMPLESDIR.
Franz Glasner <fzglas.hg@dom66.de>
parents:
537
diff
changeset
|
18 VERSION='@@VERSION@@' |
| 110 | 19 |
| 20 USAGE=' | |
| 21 USAGE: bsmtp2dma [OPTIONS] RECIPIENT ... | |
| 22 | |
| 23 Options: | |
| 24 | |
| 111 | 25 -V Show the program version and usage and exit. |
| 26 | |
| 110 | 27 -8 Does nothing. Just a compatibility option for `bsmtp`. |
| 28 | |
|
316
dc3ac7fc06ea
Typo: "Fix then " -> "Fix the "
Franz Glasner <fzglas.hg@dom66.de>
parents:
145
diff
changeset
|
29 -c ADDRESS Set the "CC:" header. |
| 111 | 30 |
| 110 | 31 -d n Does nothing. Just a compatibility option for `bsmtp`. |
| 32 | |
| 33 -f ADDRESS Set the "From:" header. | |
| 34 | |
| 35 -h MAILHOST:PORT Does nothing. Just a compatibility option for `bsmtp`. | |
| 36 | |
| 111 | 37 -l NUMBER Does nothing. Just a compatibility option for `bsmtp`. |
| 110 | 38 |
| 39 -r ADDRESS Set the "Reply-To:" header | |
| 40 | |
| 111 | 41 -s SUBJECT Set the "Subject:" header |
| 110 | 42 |
| 43 | |
|
123
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
44 Files: |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
45 |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
46 The shell style configuration file in |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
47 |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
48 @@ETCDIR@@/bsmtp2dma.conf is |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
49 |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
50 sourced in at script start. |
|
397bf58e85d2
Document configuration file usage
Franz Glasner <fzglas.hg@dom66.de>
parents:
121
diff
changeset
|
51 |
| 110 | 52 ' |
| 53 | |
| 54 # | |
| 55 # Configuration directory | |
| 56 # | |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
57 : ${CONFIGDIR:="@@ETCDIR@@"} |
| 110 | 58 |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
59 [ -r "${CONFIGDIR}/bsmtp2dma.conf" ] && . "${CONFIGDIR}/bsmtp2dma.conf" |
| 110 | 60 |
| 61 | |
| 111 | 62 # |
| 110 | 63 # Default configuration values |
| 111 | 64 # |
| 65 # `sendmail` is also valid for `dma` because of the mapping within | |
| 66 # `/etc/mail/mailer.conf` | |
| 67 # | |
| 110 | 68 : ${MAILER:=/usr/sbin/sendmail} |
| 69 | |
| 70 | |
| 71 parse_addr() { | |
| 72 : 'Parse an possibly complex email address. | |
| 73 | |
| 74 Addresses can be of the form | |
| 75 | |
| 76 - Name Parts <user@domain.tld> | |
| 77 - user@domain.tld | |
| 78 | |
| 79 `Name Parts` may not contain ``<`` or ``>`` characters. | |
| 80 | |
| 81 Args: | |
| 82 _addr: the complex email address | |
| 83 | |
| 84 Returns: | |
| 85 0 on success, 1 on errors | |
| 86 | |
| 87 Output (Globals): | |
| 88 email_name: the name part (or empty) | |
| 89 email_addr: the technical address part (or empty) | |
| 90 | |
| 91 ' | |
| 92 local _addr | |
| 93 | |
| 94 _addr="$1" | |
| 111 | 95 test -n "${_addr}" || return 1 |
| 110 | 96 |
|
537
62cd970aea9c
Replace the use of "deprecated" egrep calls with "grep -E"
Franz Glasner <fzglas.hg@dom66.de>
parents:
438
diff
changeset
|
97 if printf "%s" "${_addr}" | /usr/bin/grep -q -E -e '^[^<>]+<[^<>]+@[^<>]+>$'; then |
| 110 | 98 email_name=$(printf '%s' "${_addr}" | sed -E -e 's/[[:space:]]*<.+$//') |
| 99 email_addr=$(printf '%s' "${_addr}" | sed -E -e 's/^[^<>]+<//' | sed -E -e 's/>$//') | |
| 100 return 0 | |
| 101 fi | |
|
537
62cd970aea9c
Replace the use of "deprecated" egrep calls with "grep -E"
Franz Glasner <fzglas.hg@dom66.de>
parents:
438
diff
changeset
|
102 if printf "%s" "${_addr}" | /usr/bin/grep -q -E -e '^[^<>]+@[^<>]+$'; then |
| 110 | 103 email_name="" |
| 104 email_addr="${_addr}" | |
| 105 return 0 | |
| 106 fi | |
| 107 return 1 | |
| 108 } | |
| 109 | |
| 110 | |
| 111 send_mail() { | |
| 112 : 'Send the mail via the underlying configured mailer (dma, sendmail et al.). | |
| 113 | |
| 114 Args: | |
| 115 _recipient: The recipient name. | |
| 116 | |
| 117 Will be written into the "To:" header also. | |
| 118 | |
| 119 Input (Globals): | |
| 120 MAILER | |
| 121 MAILCONTENT | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
122 MAILFIFO_STDIN |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
123 MAILFIFO_STDOUT |
| 110 | 124 CC |
| 125 FROM | |
| 126 REPLYTO | |
| 127 SUBJECT | |
| 128 | |
| 129 Returns: | |
| 130 0 on success, other values on errors or the error exit code from the | |
| 131 underlying mailer | |
| 132 | |
| 111 | 133 This procedure starts the configured mailer as coproc and sends |
| 134 email headers and contents to the started mailer. | |
| 135 | |
| 110 | 136 ' |
| 111 | 137 local _recipient _rc _oifs _text _pid_mailer _recipient_addr |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
138 local _from_from _from_addr _sender_addr _dummy |
| 110 | 139 |
| 140 _recipient="$1" | |
| 141 _rc=0 | |
| 142 | |
| 111 | 143 if parse_addr "${_recipient}"; then |
| 144 _recipient_addr="${email_addr}" | |
| 145 else | |
| 146 echo "ERROR: unknown recipient address format in \`${_recipient}'" >&2 | |
| 147 return 1 | |
| 148 fi | |
| 149 _sender_addr="$(whoami)@$(hostname -f)" | |
| 150 if [ -z "${FROM}" ]; then | |
| 151 _from_addr="${_sender_addr}" | |
| 152 _from_from="${_from_addr}" | |
| 153 else | |
| 154 if parse_addr "${FROM}"; then | |
| 155 _from_from="${FROM}" | |
| 156 _from_addr="${email_addr}" | |
| 157 else | |
| 158 echo "ERROR: unknown sender name in \`${FROM}'" >&2 | |
| 159 return 1 | |
| 160 fi | |
| 161 fi | |
| 162 | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
163 mkfifo -m 0600 "${MAILFIFO_STDIN}" |
| 110 | 164 _rc=$? |
| 165 if [ ${_rc} -ne 0 ]; then | |
| 166 return ${_rc} | |
| 167 fi | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
168 mkfifo -m 0600 "${MAILFIFO_STDOUT}" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
169 _rc=$? |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
170 if [ ${_rc} -ne 0 ]; then |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
171 rm -f "${MAILFIFO_STDIN}" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
172 return ${_rc} |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
173 fi |
| 110 | 174 |
| 121 | 175 # |
| 176 # Start the mailer **before** opening the pipe; otherwise a | |
| 177 # deadlock occurs | |
| 178 # | |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
179 "$MAILER" -f "${_sender_addr}" "${_recipient_addr}" <"${MAILFIFO_STDIN}" >"${MAILFIFO_STDOUT}" & |
| 110 | 180 _pid_mailer=$! |
| 181 | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
182 exec 3>"${MAILFIFO_STDIN}" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
183 exec 4<"${MAILFIFO_STDOUT}" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
184 |
| 111 | 185 printf "To: %s\n" "${_recipient}" >&3 |
| 186 printf "From: %s\n" "${_from_from}" >&3 | |
| 187 if [ "${_sender_addr}" != "${_from_addr}" ]; then | |
| 188 printf "Sender: %s\n" "${_sender_addr}" >&3 | |
| 189 fi | |
| 190 if [ -n "${SUBJECT}" ]; then | |
| 191 printf "Subject: %s\n" "${SUBJECT}" >&3 | |
| 192 fi | |
| 193 if [ -n "${REPLYTO}" ]; then | |
| 114 | 194 # |
| 195 # XXX TBD proper Reply-To header value checks: | |
| 196 # a comma separated list of full mail addresses | |
| 197 # | |
| 111 | 198 printf "Reply-To: %s\n" "${REPLYTO}" >&3 |
| 199 fi | |
| 200 if [ -n "${CC}" ]; then | |
| 114 | 201 # |
| 202 # XXX TBD proper CC header value checks: | |
| 203 # a comma separated list of full mail addresses | |
| 204 # | |
| 111 | 205 printf "Cc: %s\n" "${CC}" >&3 |
| 206 fi | |
| 207 printf "\n" >&3 | |
| 208 | |
| 209 # preserve leading white space when reading with `read` | |
| 110 | 210 _oifs="$IFS" |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
211 IFS=$'\n' |
|
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
212 while read -r _text; do |
|
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
213 printf "%s\n" "$_text" >&3 |
|
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
214 done <"${MAILCONTENT}" |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
215 # not all mailer recognize this |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
216 # printf ".\n" >&3 |
| 110 | 217 IFS="$_oifs" |
| 218 | |
| 121 | 219 # close the fd to the pipe: coproc should get EOF and terminate |
| 110 | 220 exec 3>&- |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
221 # read eventually remaining stuff from the mailer until EOF |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
222 IFS='' read -r _dummy <&4 |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
223 exec 4<&- |
| 110 | 224 |
| 225 wait $_pid_mailer | |
| 226 _rc=$? | |
| 227 | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
228 # we are done with the named pipes |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
229 rm -f "${MAILFIFO_STDIN}" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
230 rm -f "${MAILFIFO_STDOUT}" |
| 110 | 231 |
| 232 return ${_rc} | |
| 233 } | |
| 234 | |
| 235 | |
| 111 | 236 while getopts "V8c:d:f:h:l:nr:s:" _opt; do |
| 110 | 237 case ${_opt} in |
| 238 V) | |
|
386
84d2735fe7f6
Simplified version tagging a lot: it is also faster now.
Franz Glasner <fzglas.hg@dom66.de>
parents:
317
diff
changeset
|
239 printf 'bsmtp2dma %s\n' '@@SIMPLEVERSIONSTR@@' |
| 110 | 240 echo "$USAGE" |
| 241 exit 0; | |
| 242 ;; | |
| 243 8) | |
| 244 : # VOID | |
| 245 ;; | |
| 246 c) | |
| 247 CC="$OPTARG" | |
| 248 ;; | |
| 111 | 249 d) |
| 250 : # VOID | |
| 251 ;; | |
| 110 | 252 f) |
| 253 FROM="$OPTARG" | |
| 254 ;; | |
| 255 h) | |
| 256 : # VOID | |
| 257 ;; | |
| 258 l) | |
| 259 : # VOID | |
| 260 ;; | |
| 261 r) | |
| 262 REPLYTO="$OPTARG" | |
| 263 ;; | |
| 264 s) | |
| 265 SUBJECT="$OPTARG" | |
| 266 ;; | |
| 267 \?) | |
| 268 exit 2; | |
| 269 ;; | |
| 270 *) | |
| 271 echo "ERROR: inconsistent option handling" >&2 | |
| 272 exit 2; | |
| 273 ;; | |
| 274 esac | |
| 275 done | |
| 276 | |
| 277 # return code | |
| 278 _rc=0 | |
| 279 | |
| 280 MAILTMPDIR="$(mktemp -d)" | |
|
119
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
281 MAILFIFO_STDIN="${MAILTMPDIR}/mail-stdin" |
|
5c92aeaec114
Try to make the mailer's input independent of a trailing single "." -- as opensmtpd's sendmail does not grok them.
Franz Glasner <fzglas.hg@dom66.de>
parents:
114
diff
changeset
|
282 MAILFIFO_STDOUT="${MAILTMPDIR}/mail-stdout" |
| 110 | 283 MAILCONTENT="${MAILTMPDIR}/mail-text" |
| 284 | |
| 285 # | |
| 286 # Clean up existing temporary stuff on all sorts of exit | |
| 287 # (including the "exit" call (signal 0)) | |
| 288 # | |
| 111 | 289 trap 'if [ -d "${MAILTMPDIR}" ]; then rm -rf "${MAILTMPDIR}"; fi; exit;' 0 1 2 15 |
| 110 | 290 |
| 291 test -d "${MAILTMPDIR}" || { echo "ERROR: no existing private tmp dir" >&2; exit 1; } | |
| 292 | |
| 293 # | |
| 294 # Reset the Shell's option handling system to prepare for handling | |
| 295 # other arguments and probably command-local options | |
| 296 # | |
| 297 shift $((OPTIND-1)) | |
| 298 OPTIND=1 | |
| 299 | |
| 300 # early check whether some recipients are given | |
| 301 if [ $# -eq 0 ]; then | |
| 302 echo "ERROR: no recipient given" >&2 | |
| 303 exit 2; | |
| 304 fi | |
| 305 | |
| 306 # | |
| 307 # Collect the mail text from stdin into a temporary file | |
| 308 # | |
| 309 exec 3>"${MAILCONTENT}" | |
| 111 | 310 # preserve leading white space when reading with `read` |
| 110 | 311 _oifs="$IFS" |
|
704
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
312 IFS=$'\n' |
|
599fddb2370d
bsmtp2dma: Some modernizations: use "read -r" and enhance some quoting
Franz Glasner <fzglas.hg@dom66.de>
parents:
643
diff
changeset
|
313 while read -r _text; do |
| 110 | 314 if [ "${_text}" = "." ]; then |
| 315 break | |
| 316 else | |
| 317 printf "%s\n" "${_text}" >&3 | |
| 318 fi | |
| 319 done | |
| 320 exec 3>&- | |
| 321 IFS="$_oifs" | |
| 322 | |
| 323 # | |
| 324 # Now send the content of the collected mail content to all recipients | |
| 325 # | |
| 326 until [ $# -eq 0 ]; do | |
| 327 send_mail "$1" | |
| 328 _rcsm=$? | |
| 329 if [ \( ${_rcsm} -ne 0 \) -a \( ${_rc} -eq 0 \) ]; then | |
| 330 _rc=${_rcsm} | |
| 331 fi | |
| 332 shift | |
| 333 done | |
| 334 | |
| 335 exit ${_rc} |
