-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmail-prepender.sh
executable file
·94 lines (90 loc) · 2.79 KB
/
mail-prepender.sh
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/bin/bash
# ------------------------------------------------------------------------------
# Prepends (to stdin/stdout) email header strings given in as flags
# -i, -I, -a, or -A; after possible mbox 'From' & 'Return-Path' header lines.
#
# Procmail's formail mail (re)formatter is still a part of most distros and
# a dependency of, e.g., clamassassin. However, it can only append or replace
# header fields whereas such fields are better prepended similarly to the
# trace fields (RFC 5322, 3.6.7).
#
# This is intended as a limited formail replacement that ignores the nyanses of
# the flags and simply prepends the valid (RFC 5322, 2.2) non-empty headers
# keeping the other headers as is.
#
# Clamassassin uses 'formail -c -x' to extract the original subject. Therefore,
# '-x' & '-X' are implemented, too. Any other flags are ignored.
#
# Author : Esa Jokinen (oh2fih)
# Home : https://github.com/oh2fih/Misc-Scripts
# ------------------------------------------------------------------------------
# Handling 'formail -x' & '-X'; ignoring '-c' as grep only gives a single line
headerNameRegex=$'^[\x21-\x39\x3B-\x7E]+:'
while getopts ":x:X:" opts; do
case "${opts}" in
x) # Extract the contents of this headerfield from the header.
if [[ "$OPTARG" =~ $headerNameRegex ]]; then
grep "${OPTARG}" <&0 | head -n 1 | sed "s/${OPTARG}//"
fi
exit
;;
X) # Same as -x, but also preserves/includes the field name.
if [[ "$OPTARG" =~ $headerNameRegex ]]; then
grep "${OPTARG}" <&0 | head -n 1
fi
exit
;;
*) # Ignoring anything else, as -i|-I|-a|-A are handled elsewhere.
;;
esac
done
# A possible Mbox format's From line MUST come before any added headers &
# Return-Path header conventionally (spamassassin) comes before other headers
firstLine=""
secondLine=""
read -r line
if [[ "$line" =~ ^(From|Return-Path:)\ .* ]]; then
echo "$line"
if [[ "$line" =~ ^From\ .* ]]; then
read -r line
if [[ "$line" =~ ^Return-Path:\ .* ]]; then
echo "$line"
else
secondLine="$line"
fi
fi
else
firstLine="$line"
fi
# Prepend lines from flags
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-i|-I|-a|-A)
nextArg="$2"
while ! [[ "$nextArg" =~ ^-.* ]] && [[ $# -gt 1 ]]; do
# Only prepend valid (RFC 5322, 2.2) non-empty email header fields
headerRegex=$'^[\x21-\x39\x3B-\x7E]+:\ [\x20-\x7E]+'
if [[ "$nextArg" =~ $headerRegex ]]; then
echo "$nextArg"
fi
if ! [[ "$2" =~ ^-.* ]]; then
shift
nextArg="$2"
else
shift
break
fi
done
;;
esac
shift
done
# Rest of the stdin to stdout
if [[ "$firstLine" != "" ]]; then
echo "$firstLine"
fi
if [[ "$secondLine" != "" ]]; then
echo "$secondLine"
fi
cat <&0