Matrix To MMS-Over-Email Bridge: Step 2 — Matrix Over Email
This step was considerably harder than the last, but the end result turned out to be pretty simple. Here’s how it works:
- I use matrix-commander on smirkingface to listen for new messages.
- For each message, I send it to my phone via email, from an address specific to that room.
- Upon recieving an email from my phone on ~team, I send the body to the Matrix room specified in the to address.
That’s really it. I did encounter some hurdles, though:
- My phone provider’s gateway marked many of the addresses I tried to send from as spam.
- matrix-commander ocassionally randomly stops.
I fixed these by mapping Matrix room IDs to human-readable IDs such as “room-number-7”, and by putting the program in a while loop (don’t look at me like that — I made this because I promised a friend, it doesn’t need to be high quality).
On smirkingface
matrix2email
#!/bin/sh
TO_ADDR="enter email address here"
FROM_USER="enter sender email address local part here"
FROM_DOMAIN="enter sender email address domain here"
unescape() {
printf '%s\n' "$1" | sed -E '
s/\\"/"/g;
s/\\t/\t/g;
s/\\r/\r/g;
s/\\n/\n/g;
s/\\e/\\/g
'
}
# room_avatar_url has to be last bc it has a good chance of being null
matrix-commander -l -o json --download-media --listen-self \
| jq --raw-output --unbuffered '
. | [
.source.type,
.source.content.body,
.source.content.msgtype,
.room.room_id,
(.room.users | length),
.room_display_name,
.sender_nick,
.room.room_avatar_url
] | @tsv' \
| while IFS=$'\t\n' read -r event body mime room users name sender icon; do
[ "$event" = "m.room.message" ] || continue
if grep -Eq "^$room " ~matrix/rooms; then
addr="$(grep -E "^$room " ~matrix/rooms \
| head -n 1 | cut -d' ' -f2)"
else
# map mxid to something that doesn’t look like spam
touch ~matrix/rooms
num="$(wc -l <~matrix/rooms)"
addr="${FROM_USER}+room.no.${num}@${FROM_DOMAIN}"
printf '%s %s\n' "$room" "$addr" >>~matrix/rooms
# inform ~team so it can add a ~/.forward file
printf 'room.no.%s\n' "$num" \
| mailx -s "New forward file" \
-r "matrix@${FROM_DOMAIN}" \
"matrix@${FROM_DOMAIN}"
# inform user so they can name the chat and etc
file="$(mktemp)"
trap "rm -rf '$file'" INT TERM HUP EXIT
matrix-commander --download "$icon" --file-name "$file"
unescape "$(
printf '%s ' "“$name” ($room) is <$addr>"
printf '\n'
)" \
| mailx -s "" \
-r "${FROM_USER}+matrix@${FROM_DOMAIN}" \
-S "sendcharsets=utf-8,UTF-8" \
-a "$file" \
"$TO_ADDR"
rm "$file"
fi
file="$body"
[ "$users" -gt 2 ] && body="<$sender> $body"
if [ "$mime" = "m.text" ] || [ "$mime" = "m.notice" ] \
|| [ "$mime" = "text/plain" ] \
|| [ "$mime" = "text/markdown" ]
then
unescape "$body" | mailx -s "" \
-r "$addr" \
-S "sendcharsets=utf-8,UTF-8" \
"$TO_ADDR"
else
echo "$file" >~matrix/file-name
unescape "$body" | mailx -s "" \
-r "$addr" \
-S "sendcharsets=utf-8,UTF-8" \
-a ~matrix/media/"$(unescape "$file")" \
"$TO_ADDR"
rm ~matrix/media/"$(unescape "$file")"
fi
done
restart.sh
#!/bin/sh
while :; do
./matrix2email
done
email2matrix
#!/bin/sh
to="$1"
body="$(cat)"
matrix-commander \
--room "$(grep -F "$to" ~matrix/rooms | cut -d " " -f 1)" \
--message "$body"
On ~team
#!/bin/sh
# POSIX sh lacks $HOSTNAME and `hostname`
hostname() {
set -- $(grep -F "$(cat /etc/hostname)" /etc/hosts)
printf '%s\n' "$2"
}
OTHER_MACHINE="enter fqdn here"
email="$(cat)"
from="$(
printf '%s\n' "$email" \
| grep -Em1 "^From:" \
| cut -d : -f 2- \
| sed -E 's/^[[:blank:]]*(.*<)?//g; s/>?[[:blank:]]*$//g'
)"
to="$(
printf '%s\n' "$email" \
| grep -Em1 "^To:" \
| cut -d : -f 2- \
| sed -E 's/^[[:blank:]]*(.*<)?//g; s/>?[[:blank:]]*$//g'
)"
split="$(printf '%s\n' "$email" | grep -En "^$" | cut -d : -f 1)"
body="$(printf '%s\n' "$email" | tail -n +"$((split + 1))")"
if [ "$from" = "matrix@$(hostname)" ]; then
ln ~/.forward+matrix ~/".forward+matrix+$body"
else
printf '%s\n' "$body" \
| ssh "matrix@$OTHER_MACHINE" -t /usr/local/share/matrix/email2matrix "$to"
fi
#MatrixMMSEmail #HacksAndProjects
© DJ Chase, 2023. Licensed under the Academic Free License (AFL 3.0).