aboutsummaryrefslogtreecommitdiffstats
path: root/ansible/roles/postfix/templates/services/fredrick-reply.sh.j2
blob: 90ebe043b57490746411cfb57c62f0ce393a0a6a (plain) (blame)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env sh
# {{ ansible_managed }}
#
# Replies for Fredrick whilst he's travelling for work, and forwards replies to
# DevOps to respond for him if necessary.

FREDRICK_TOKEN='{{ postfix_fredrick_generator_token }}'
FREDRICK_ENDPOINT="https://fredrick.python-discord.workers.dev/"

# Read email into variable
EMAIL=$(cat)

# Find the sender
SENDER=$(echo "$EMAIL" | maddr -h from -)

# Grab the display name of the sender
SENDER_DISPLAY_NAME=$(echo "$EMAIL" | maddr -h from -d -)

# Grab the target address
RECIPIENT=$(echo "$EMAIL" | maddr -a -h to -)

# Sender date as a unix timestamp
DATE_UNIX=$(echo "$EMAIL" | mhdr -h date -D -)

# Find message ID to use later to add to a reply chain
MESSAGE_ID=$(echo "$EMAIL" | mhdr -h message-id -)

MESSAGE_DATE=$(echo "$EMAIL" | mhdr -h date -)

# Extract the original Subject and prefix it with "Re: " if necessary
ORIGINAL_SUBJECT=$(echo "$EMAIL" | mhdr -h subject -)

LIST_ID=$(echo "$EMAIL" | mhdr -h list-id -)
if [ "$LIST_ID" != "" ]; then
    # We don't reply to all mailing list posts.
    SHOULD_REPLY=$(awk 'BEGIN { srand(); print rand() <= 0.25 }')
    if [ "$SHOULD_REPLY" = "0" ]; then
        echo "fredrick: don't feel like replying to mailing list post (\"$ORIGINAL_SUBJECT\")."
        exit 0
    fi
fi

# Construct the reply subject
REPLY_SUBJECT="Re: $ORIGINAL_SUBJECT"

# Decode the text/plain component of the message body
#
# We strip off a line on some emails about being unable to find a filter
BODY=$(echo "$EMAIL" | mshow - -N -h "" -A text/plain | grep -v "^no filter or default handler$")

# Convert to a multiline JSON value that we can ship to the Fred API
JSON_BODY=$(echo -n "$BODY" | jq -R -s . | sed 's/\\n/\\\\n/g')

# We build the request to send off to the Fredrick generator
FINAL_JSON=$(jq -r -c -n \
    --arg from "$SENDER" \
    --arg subject "$ORIGINAL_SUBJECT" \
    --arg sent_at_unix "$DATE_UNIX" \
    --arg sent_at_unparsed "$MESSAGE_DATE" \
    --argjson body "$JSON_BODY" \
    '{sent_at_unix: $sent_at_unix, sent_at_unparsed: $sent_at_unparsed,
      from: $from, subject: $subject, body: $body}')

FRED_RESPONSE=$(curl -X POST "$FREDRICK_ENDPOINT" \
    -H "Authorization: $FREDRICK_TOKEN" \
    -H "Content-Type: application/json" \
    -d "$FINAL_JSON" -s)

# Fredrick likes to try add a Subject: line on sometimes
FILTERED=$(echo "$FRED_RESPONSE" | grep -v "^Subject:")

# Path where scheduled replies are stored
REPLIES_PATH=/var/tmp/fredrick-vacation-replies

if [ ! -d "$REPLIES_PATH" ]; then
    # -p is to prevent race conditions from concurrent script runs
    mkdir -p "$REPLIES_PATH"
fi

REPLY_PATH=$(mktemp --tmpdir="$REPLIES_PATH" --suffix=.eml)

(
  echo "Subject: $REPLY_SUBJECT"
  echo "From: Fredrick <[email protected]>"
  echo "To: $SENDER"
  echo "Bcc: [email protected]"
  echo "In-Reply-To: $MESSAGE_ID"
  echo "References: $MESSAGE_ID"
  echo
  echo "$FILTERED"
  echo
  # Quote the original message
  echo "On $MESSAGE_DATE, $SENDER_DISPLAY_NAME wrote:"
  echo "$BODY" | awk -F '\n' '{ print "> " $1 }'
) > "$REPLY_PATH"

ATSCRIPT=$(mktemp --suffix=fredrick-atscript.sh)

cat > "$ATSCRIPT" <<EOF
/usr/sbin/sendmail -t < "$REPLY_PATH"
rm "$REPLY_PATH"
EOF

# Use the z queue for maximum niceness
case $RECIPIENT in
    "fredrick+ritalin@"*)
        at -q z -f "$ATSCRIPT" now + 1 min
        ;;
    *)
        reply_delay=$(awk 'BEGIN { srand(); print (rand() * 100) + 20 }')
        at -q z -f "$ATSCRIPT" now + "$reply_delay" min
        ;;
esac
rm "$ATSCRIPT"