Bolte Bridge is a bidirectional bridge between traditional mailing lists and a Matrix room. Messages posted to the list appear in the room, and messages sent in the room are delivered to the list. Members can follow and join the conversation from whichever medium they prefer.
It aims for a seamless experience across both sides:
- Bidirectional relay between one mailing list and one Matrix room.
- Sender fidelity — list senders appear as themselves in Matrix, and Matrix users get a stable, attributable address on the list.
- Threading fidelity — email reply chains map to Matrix replies/threads and vice versa.
- No message loops — the bridge never re-bridges its own traffic.
Bolte Bridge is designed to support the Melbourne Linux User Group mailing list.
Build the bridge:
go buildThis produces the bolte-bridge executable in the current directory.
Run the built executable:
BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password> \
BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token> \
BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token> \
./bolte-bridge \
--email bridge@example.com \
--matrix-homeserver-url https://matrix.org \
--matrix-server-name matrix.org \
--matrix-appservice-id my-bridge \
--matrix-sender-localpart bridge-bot \
--matrix-room-id '!room:matrix.org'Alternatively, run the bridge directly with Go:
BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password> \
BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token> \
BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token> \
go run . \
--email bridge@example.com \
--matrix-homeserver-url https://matrix.org \
--matrix-server-name matrix.org \
--matrix-appservice-id my-bridge \
--matrix-sender-localpart bridge-bot \
--matrix-room-id '!room:matrix.org'The bridge signs in to a single mail account and connects to a Matrix homeserver, which it uses to bridge messages between the mailing list and a Matrix room. The mail account address, password, and Matrix appservice tokens are required; the bridge exits at startup if any of these are missing. Everything else has a default.
By default, the bridge creates and uses a SQLite database named bolte-bridge.db in the current working directory, and talks to Gmail's IMAP and SMTP endpoints, alongside the Matrix Client-Server API.
The bridge can be configured through either command-line flags or environment variables.
Command-line flags take precedence over environment variables, which in turn take precedence over built-in defaults.
The account password is the one exception: it can only be supplied through the
environment. It has no flag, so that it never appears in argv, where it would
be visible in the process table and in shell history.
| Flag | Description | Default |
|---|---|---|
-d, --db-path |
Path to the SQLite database. | bolte-bridge.db |
-e, --email |
Account name for IMAP/SMTP (the full email address). Required. | — |
--email-imap-addr |
host:port of the IMAP endpoint (implicit TLS). |
imap.gmail.com:993 |
--email-mailbox |
IMAP mailbox to fetch from. | INBOX |
--email-smtp-addr |
host:port of the SMTP submission endpoint (STARTTLS). |
smtp.gmail.com:587 |
--matrix-appservice-id |
Appservice registration ID. Required. | — |
--matrix-homeserver-url |
Base URL of the homeserver Client-Server API (e.g. https://matrix.org). Required. |
— |
--matrix-room-id |
The Matrix room to bridge (!room:server). Required. |
— |
--matrix-sender-localpart |
Appservice bot user localpart. Required. | — |
--matrix-server-name |
Homeserver server_name (e.g. matrix.org). Required. |
— |
Every setting is also readable from the environment, under the
BOLTE_BRIDGE_ prefix.
| Variable | Description | Default |
|---|---|---|
BOLTE_BRIDGE_DB_PATH |
Path to the SQLite database. | bolte-bridge.db |
BOLTE_BRIDGE_EMAIL_ACCOUNT |
Account name for IMAP/SMTP (the full email address). Required. | — |
BOLTE_BRIDGE_EMAIL_IMAP_ADDR |
host:port of the IMAP endpoint (implicit TLS). |
imap.gmail.com:993 |
BOLTE_BRIDGE_EMAIL_MAILBOX |
IMAP mailbox to fetch from. | INBOX |
BOLTE_BRIDGE_EMAIL_PASSWORD |
Account password. Required, and settable only here. | — |
BOLTE_BRIDGE_EMAIL_SMTP_ADDR |
host:port of the SMTP submission endpoint (STARTTLS). |
smtp.gmail.com:587 |
BOLTE_BRIDGE_MATRIX_APPSERVICE_ID |
Appservice registration ID. Required. | — |
BOLTE_BRIDGE_MATRIX_AS_TOKEN |
Appservice token (as_token). Required, settable only here. |
— |
BOLTE_BRIDGE_MATRIX_HOMESERVER_URL |
Base URL of the homeserver Client-Server API. Required. | — |
BOLTE_BRIDGE_MATRIX_HS_TOKEN |
Homeserver token (hs_token). Required, settable only here. |
— |
BOLTE_BRIDGE_MATRIX_ROOM_ID |
The Matrix room to bridge (!room:server). Required. |
— |
BOLTE_BRIDGE_MATRIX_SENDER_LOCALPART |
Appservice bot user localpart. Required. | — |
BOLTE_BRIDGE_MATRIX_SERVER_NAME |
Homeserver server_name. Required. |
— |
The IMAP endpoint is contacted over implicit TLS and the SMTP endpoint over STARTTLS, so the port you choose should be one the server offers for that scheme.
If you point the bridge at a Gmail account, the password is an app password, not the account's own password; Gmail rejects IMAP and SMTP logins that use the latter.
The following examples demonstrate both supported configuration methods.
Run against Gmail with the default endpoints and database:
export BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password>
export BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token>
export BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token>
go run . \
--email bridge@example.com \
--matrix-homeserver-url https://matrix.org \
--matrix-server-name matrix.org \
--matrix-appservice-id my-bridge \
--matrix-sender-localpart bridge-bot \
--matrix-room-id "!room:matrix.org"Use a custom database path:
export BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password>
export BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token>
export BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token>
go run . \
--email bridge@example.com \
--db-path bridge.db \
--matrix-homeserver-url https://matrix.org \
--matrix-server-name matrix.org \
--matrix-appservice-id my-bridge \
--matrix-sender-localpart bridge-bot \
--matrix-room-id "!room:matrix.org"Point the bridge at a non-Gmail provider, and read from a mailbox other than
INBOX:
export BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password>
export BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token>
export BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token>
go run . \
--email bridge@example.com \
--email-imap-addr imap.example.com:993 \
--email-smtp-addr smtp.example.com:587 \
--email-mailbox Lists/mlug \
--matrix-homeserver-url https://matrix.org \
--matrix-server-name matrix.org \
--matrix-appservice-id my-bridge \
--matrix-sender-localpart bridge-bot \
--matrix-room-id "!room:matrix.org"Or configure everything through the environment:
export BOLTE_BRIDGE_DB_PATH=bridge.db
export BOLTE_BRIDGE_EMAIL_ACCOUNT=bridge@example.com
export BOLTE_BRIDGE_EMAIL_PASSWORD=<app-password>
export BOLTE_BRIDGE_EMAIL_IMAP_ADDR=imap.example.com:993
export BOLTE_BRIDGE_EMAIL_SMTP_ADDR=smtp.example.com:587
export BOLTE_BRIDGE_EMAIL_MAILBOX=Lists/mlug
export BOLTE_BRIDGE_MATRIX_HOMESERVER_URL=https://matrix.org
export BOLTE_BRIDGE_MATRIX_SERVER_NAME=matrix.org
export BOLTE_BRIDGE_MATRIX_APPSERVICE_ID=my-bridge
export BOLTE_BRIDGE_MATRIX_AS_TOKEN=<as-token>
export BOLTE_BRIDGE_MATRIX_HS_TOKEN=<hs-token>
export BOLTE_BRIDGE_MATRIX_SENDER_LOCALPART=bridge-bot
export BOLTE_BRIDGE_MATRIX_ROOM_ID="!room:matrix.org"
go run .