Skip to content

Commit 0f7dfe4

Browse files
feat: add releasemail script
Signed-off-by: Ar Rakin <[email protected]>
1 parent 68ae80f commit 0f7dfe4

File tree

1 file changed

+332
-0
lines changed

1 file changed

+332
-0
lines changed

mail/releasemail

+332
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
#!/bin/sh
2+
#
3+
# releasemail -- generate a release announcement email
4+
#
5+
# This program is part of OSN Commons.
6+
# Copyright (C) 2024 OSN Developers.
7+
#
8+
# OSN Commons is free software: you can redistribute it and/or modify it
9+
# under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# OSN Commons is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with OSN Commons. If not, see <https://www.gnu.org/licenses/>.
20+
#
21+
22+
SHORT_OPTIONS="hvr:f:H:A:s:MP:R:n"
23+
LONG_OPTIONS="help,version,recipients:,from:,header:,attachment:,subject:,mail-now,no-print,project:,release:"
24+
25+
me=$0
26+
canonical_name=$(echo $me | rev | cut -d'/' -f1 | rev)
27+
28+
if [ $(echo $me | cut -c1) = "/" ]; then
29+
me=$canonical_name
30+
fi
31+
32+
version="1.0.0"
33+
argv=$(getopt -o $SHORT_OPTIONS --long $LONG_OPTIONS -n "$me" -- "$@")
34+
35+
if [ $? -ne 0 ]; then
36+
echo "Try '$0 --help' for more information." >&2
37+
exit 1
38+
fi
39+
40+
eval set -- "$argv"
41+
42+
stdout_is_tty=$?
43+
44+
if [ -t 1 ]; then
45+
stdout_is_tty=1
46+
else
47+
stdout_is_tty=0
48+
fi
49+
50+
usage() {
51+
echo "Usage: $0 [OPTION]... [BODY]"
52+
echo " $0 [OPTION]... -"
53+
echo "Generate a release announcement email."
54+
echo
55+
echo "Options:"
56+
echo " -h, --help Display this help and exit"
57+
echo " -v, --version Display version information and exit"
58+
echo " -r, --recipients List of email addresses to send the email to"
59+
echo " -f, --from Email address to send the email from"
60+
echo " -H, --header Additional header to include in the email"
61+
echo " -A, --attachment Attach a file to the email"
62+
echo " -s, --subject Subject of the email"
63+
echo " -M, --mail-now Immediately send the email"
64+
echo " -n, --no-print Do not print the email to stdout"
65+
echo " -P, --project Project name"
66+
echo " -R, --release Version number of the release"
67+
echo ""
68+
echo "Bug reports and general questions should be sent to "
69+
70+
exit 0
71+
}
72+
73+
show_version() {
74+
echo "releasemail (OSN Commons) v$version"
75+
echo ""
76+
echo "License GPLv3+: GNU GPL version 3 or later <https://www.gnu.org/licenses/>"
77+
echo "This is free software: you are free to change and redistribute it."
78+
echo "There is NO WARRANTY, to the extent permitted by law."
79+
echo ""
80+
echo "Written by Ar Rakin."
81+
exit 0
82+
}
83+
84+
invalid_usage() {
85+
echo "$me: $@" >&2
86+
echo "Try '$me --help' for more information." >&2
87+
exit 1
88+
}
89+
90+
color() {
91+
if [ "$stdout_is_tty" = "1" ]; then
92+
echo "\033[$1m$2\033[0m"
93+
else
94+
echo $2
95+
fi
96+
}
97+
98+
validate_email() {
99+
echo "$1" | grep -Eq '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,})?$'
100+
return $?
101+
}
102+
103+
recipients=""
104+
from=""
105+
headers=""
106+
mail_headers=""
107+
user_body=""
108+
attachments=""
109+
user_subject=""
110+
send=0
111+
no_print=0
112+
project=""
113+
release=""
114+
115+
while true; do
116+
case "$1" in
117+
-h | --help)
118+
usage
119+
;;
120+
-v | --version)
121+
show_version
122+
;;
123+
-r | --recipients)
124+
for recipient in $(echo $2 | tr ',' ' '); do
125+
if ! validate_email "$recipient"; then
126+
invalid_usage "Invalid email address: $recipient"
127+
fi
128+
129+
if [ -z "$recipients" ]; then
130+
recipients="$recipient"
131+
continue
132+
fi
133+
134+
recipients="$recipients $recipient"ents="$recipients,$recipient"
135+
done
136+
137+
shift 2
138+
;;
139+
-f | --from)
140+
if ! validate_email "$2"; then
141+
invalid_usage "Invalid email address: $recipient"
142+
fi
143+
144+
from=$2
145+
shift 2
146+
;;
147+
-H | --header)
148+
if echo "$2" | grep -Eq '^From:|To:|Subject:'; then
149+
invalid_usage "Disallowed header: $2"
150+
fi
151+
152+
if echo "$2" | grep -Eq '^\s*$'; then
153+
invalid_usage "Empty header passed to option -- '$1'"
154+
fi
155+
156+
if echo -e "$2" | grep -q $'\n'; then
157+
invalid_usage "Header must not have newline character"
158+
fi
159+
160+
name=$(echo "$2" | cut -d':' -f1 | sed 's/^[[:space:]]*//')
161+
value=$(echo "$2" | cut -d':' -f2- | sed 's/^[[:space:]]*//')
162+
code=197
163+
164+
case "$name" in
165+
X-*)
166+
code=33
167+
;;
168+
*) ;;
169+
esac
170+
171+
header=$(color "32" "$name:")" $(color "38;5;$code" "$value")"
172+
173+
if [ -z "$headers" ]; then
174+
headers="$header"
175+
else
176+
headers="$headers\n$header"
177+
fi
178+
179+
quoted_2=$(echo "$2" | sed 's/"/\\"/g')
180+
mail_headers="$mail_headers -a \"$quoted_2\""
181+
shift 2
182+
;;
183+
184+
-A | --attachment)
185+
escaped=$(echo "$2" | sed 's/"/\\"/g')
186+
187+
if [ -z "$attachments" ]; then
188+
attachments="\"$escaped\""
189+
else
190+
attachments="$attachments \"$escaped\""
191+
fi
192+
193+
shift 2
194+
;;
195+
196+
-s | --subject)
197+
user_subject="$2"
198+
shift 2
199+
;;
200+
201+
-M | --mail-now)
202+
send=1
203+
shift
204+
;;
205+
206+
-n | --no-print)
207+
no_print=1
208+
shift
209+
;;
210+
211+
-P | --project)
212+
project="$2"
213+
shift 2
214+
;;
215+
216+
-R | --release)
217+
release="$2"
218+
shift 2
219+
;;
220+
221+
--)
222+
shift
223+
break
224+
;;
225+
226+
-*)
227+
invalid_usage "Unknown option: $1"
228+
;;
229+
esac
230+
done
231+
232+
if [ "$@" = "-" ]; then
233+
if [ -t 0 ]; then
234+
invalid_usage "Cannot read from stdin in interactive mode"
235+
fi
236+
237+
user_body="$(cat)"
238+
elif [ -n "$@" ]; then
239+
user_body="$@"
240+
fi
241+
242+
if [ -z "$recipients" ]; then
243+
invalid_usage "No recipients specified"
244+
fi
245+
246+
if [ -z "$from" ]; then
247+
invalid_usage "No from address specified"
248+
fi
249+
250+
if [ -z "$user_subject" ] || [ -z "$user_body" ]; then
251+
if [ -z "$project" ]; then
252+
invalid_usage "No project name specified\nPlease either specify a project name or provide a subject and body"
253+
fi
254+
255+
if [ -z "$release" ]; then
256+
invalid_usage "No release version specified\nPlease either specify a release version or provide a subject and body"
257+
fi
258+
fi
259+
260+
if [ -z "$user_subject" ]; then
261+
subject="$project v$release released"
262+
else
263+
subject="$user_subject"
264+
fi
265+
266+
if [ -n "$user_body" ]; then
267+
body="$user_body"
268+
else
269+
body="$project v$release has been released. Please visit the project's website for more information."
270+
body="$body\nThank you for using $project."
271+
body="$body\n\nSincerely,\n$project Developers"
272+
fi
273+
274+
mail="$(color "32" "To:") $(color "1;38;5;112" "$recipients")\n"
275+
mail="$mail$(color "32" "Subject:") $(color "38;5;119" "$subject")\n"
276+
mail="$mail$(color "32" "From:") $(color "38;5;197" "$from")\n"
277+
278+
if [ -n "$headers" ]; then
279+
mail="$mail$headers\n"
280+
fi
281+
282+
mail="$mail\n$body"
283+
284+
if [ $no_print -eq 0 ]; then
285+
echo "$mail"
286+
fi
287+
288+
if [ $send -eq 1 ]; then
289+
mail_cmd=$(command -v mail)
290+
291+
if [ -z "$mail_cmd" ]; then
292+
echo "$me: The 'mail' command is not available" >&2
293+
echo "$me: Please install a mail client to send emails" >&2
294+
exit 1
295+
fi
296+
297+
mail_cmd="$(command -v mail)"
298+
299+
if [ -z "$mail_cmd" ]; then
300+
echo "$me: The 'mail' command is not available" >&2
301+
echo "$me: Please install GNU mailutils to send emails" >&2
302+
exit 1
303+
fi
304+
305+
mail_cmd="$mail_cmd \"$(echo "$recipients" | sed 's/"/\\"/g')\""
306+
mail_cmd="$mail_cmd --content-type='text/plain'"
307+
mail_cmd="$mail_cmd -s \"$(echo "$subject" | sed 's/"/\\"/g')\""
308+
mail_cmd="$mail_cmd -r \"$(echo "$from" | sed 's/"/\\"/g')\""
309+
mail_cmd="$mail_cmd $mail_headers"
310+
311+
if [ -n "$attachments" ]; then
312+
for attachment in $attachments; do
313+
mail_cmd="$mail_cmd -A $attachment"
314+
done
315+
fi
316+
317+
code=0
318+
319+
if [ -n "$RELEASEMAIL_DEBUG" ]; then
320+
set -x
321+
fi
322+
323+
echo "$body" | eval $mail_cmd
324+
set +x
325+
326+
code=$?
327+
328+
if [ $code -ne 0 ]; then
329+
echo "$me: Failed to send email" >&2
330+
exit 1
331+
fi
332+
fi

0 commit comments

Comments
 (0)