~kris/dots

srice

ref: e98f3b030dc24445bd55c68d95d2d81933fd68b3 srice/.local/bin/misc/email -rw-r--r-- 1.9 KiB
e98f3b03 — Kris Yotam chore: sync local state after restore (push updates, no pull) a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

# email — send emails with optional attachments via msmtp
# usage: email [-a account] [-s subject] [-f file]... <recipient> [body]
# examples:
#   email kris@example.com "hello"
#   email -s "Report" -f data.csv kris@example.com
#   echo "body" | email -s "Subject" -f a.csv -f b.csv kris@example.com

die() { printf '%s: %s\n' "${0##*/}" "$*" >&2; exit 1; }

account="gmail"
subject="(no subject)"
files=()
boundary="----=_boundary_$(date +%s)_$$"

while [[ $# -gt 0 ]]; do
	case "${1}" in
		-a) account="${2}"; shift ;;
		-s) subject="${2}"; shift ;;
		-f) files+=("${2}"); shift ;;
		-h) printf 'usage: email [-a account] [-s subject] [-f file]... <recipient> [body]\n'; exit 0 ;;
		-*) die "unknown option: ${1}" ;;
		*)  break ;;
	esac
	shift
done

[[ $# -lt 1 ]] && die "no recipient specified"
to="${1}"
shift

# body from arg, stdin, or empty
if [[ $# -gt 0 ]]; then
	body="$*"
elif [[ ! -t 0 ]]; then
	body="$(cat)"
else
	body=""
fi

# build and send
{
	printf 'To: %s\n' "${to}"
	printf 'Subject: %s\n' "${subject}"
	printf 'MIME-Version: 1.0\n'

	if [[ ${#files[@]} -eq 0 ]]; then
		printf 'Content-Type: text/plain; charset=utf-8\n\n'
		printf '%s\n' "${body}"
	else
		printf 'Content-Type: multipart/mixed; boundary="%s"\n\n' "${boundary}"

		# body part
		printf -- '--%s\n' "${boundary}"
		printf 'Content-Type: text/plain; charset=utf-8\n\n'
		printf '%s\n\n' "${body}"

		# attachments
		for f in "${files[@]}"; do
			[[ -f "${f}" ]] || die "file not found: ${f}"
			fname="${f##*/}"
			printf -- '--%s\n' "${boundary}"
			printf 'Content-Type: application/octet-stream; name="%s"\n' "${fname}"
			printf 'Content-Disposition: attachment; filename="%s"\n' "${fname}"
			printf 'Content-Transfer-Encoding: base64\n\n'
			base64 "${f}"
			printf '\n'
		done

		printf -- '--%s--\n' "${boundary}"
	fi
} | msmtp -a "${account}" "${to}"

printf 'sent to %s via %s\n' "${to}" "${account}"