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