11 KiB
Postmoogle 

An Email to Matrix bridge. 1 room = 1 mailbox.
Postmoogle is an actual SMTP server that allows you to send and receive emails on your matrix server. It can't be used with arbitrary email providers, because it acts as an actual email provider itself, so you can use it to send emails from your apps and scripts as well.
Roadmap
Receive
- SMTP server (plaintext and SSL)
- Matrix bot
- Configuration in room's account data
- Receive emails to matrix rooms
- Receive attachments
- Catch-all mailbox
- Map email threads to matrix threads
deep dive
features in that section considered as "nice to have", but not a priority
- DKIM verification
- SPF verification
- DMARC verification
- Blocklists
Send
- SMTP client
- SMTP server (you can use Postmoogle as general purpose SMTP server to send emails from your scripts or apps)
- Send a message to matrix room with special format to send a new email, even to multiple email addresses at once
- Reply to matrix thread sends reply into email thread
Configuration
1. Bot (mandatory)
env vars
- POSTMOOGLE_HOMESERVER - homeserver url, eg:
https://matrix.example.com - POSTMOOGLE_LOGIN - user login/localpart, eg:
moogle - POSTMOOGLE_PASSWORD - user password
- POSTMOOGLE_DOMAIN - SMTP domain to listen for new emails
other optional config parameters
- POSTMOOGLE_PORT - SMTP port to listen for new emails
- POSTMOOGLE_TLS_PORT - secure SMTP port to listen for new emails. Requires valid cert and key as well
- POSTMOOGLE_TLS_CERT - path to your SSL certificate (chain)
- POSTMOOGLE_TLS_KEY - path to your SSL certificate's private key
- POSTMOOGLE_TLS_REQUIRED - require TLS connection, even on the non-TLS port (
POSTMOOGLE_PORT). TLS connections are always required on the TLS port (POSTMOOGLE_TLS_PORT) regardless of this setting. - POSTMOOGLE_DATA_SECRET - secure key (password) to encrypt account data, must be 16, 24, or 32 bytes long
- POSTMOOGLE_NOENCRYPTION - disable matrix encryption (libolm) support
- POSTMOOGLE_STATUSMSG - presence status message
- POSTMOOGLE_SENTRY_DSN - sentry DSN
- POSTMOOGLE_LOGLEVEL - log level
- POSTMOOGLE_DB_DSN - database connection string
- POSTMOOGLE_DB_DIALECT - database dialect (postgres, sqlite3)
- POSTMOOGLE_MAXSIZE - max email size (including attachments) in megabytes
- POSTMOOGLE_ADMINS - a space-separated list of admin users. See
POSTMOOGLE_USERSfor syntax examples
You can find default values in config/defaults.go
2. DNS (optional)
The following configuration is needed only if you want to send outgoing emails via Postmoogle (it's not necessary if you only want to receive emails).
TL;DR
- Configure DMARC record
- Configure SPF record
- Configure MX record
- Configure DKIM record (use
!pm dkim)
First, add a new DMARC DNS record of the TXT type for subdomain _dmarc with a proper policy. The simplest policy you can use is: v=DMARC1; p=quarantine;.
Example
$ dig txt _dmarc.example.com
; <<>> DiG 9.18.6 <<>> txt _dmarc.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57306
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;_dmarc.example.com. IN TXT
;; ANSWER SECTION:
_dmarc.example.com. 1799 IN TXT "v=DMARC1; p=quarantine;"
;; Query time: 46 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 04 21:31:30 EEST 2022
;; MSG SIZE rcvd: 79
Second, add a new SPF DNS record of the TXT type for your domain that will be used with Postmoogle, with format: v=spf1 ip4:SERVER_IP -all (replace SERVER_IP with your server's IP address)
Example
$ dig txt example.com
; <<>> DiG 9.18.6 <<>> txt example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24796
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com. IN TXT
;; ANSWER SECTION:
example.com. 1799 IN TXT "v=spf1 ip4:111.111.111.111 -all"
;; Query time: 36 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 04 21:35:04 EEST 2022
;; MSG SIZE rcvd: 255
Third, add a new MX DNS record of the MX type for your domain that will be used with postmoogle. It should point to the same (sub-)domain.
Looks odd, but some mail servers will refuse to interact with your mail server (and Postmoogle is already a mail server) without MX records.
Example
dig MX example.com
; <<>> DiG 9.18.6 <<>> MX example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12688
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com. IN MX
;; ANSWER SECTION:
example.com. 1799 IN MX 10 example.com.
;; Query time: 40 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Tue Sep 06 16:44:47 EEST 2022
;; MSG SIZE rcvd: 59
Fourth (and the last one), add new DKIM DNS record of TXT type for subdomain postmoogle._domainkey that will be used with postmoogle.
You can get that signature using the !pm dkim command:
!pm dkim
DKIM signature is: v=DKIM1; k=rsa; p=MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxJVqmBHhK9FY93q1o3WEaP2GKMh/3LNMyvi1uSjOKxIyfWv685KxX1EUrbHakQRCTtUM7efKEsXsXBh+DQru2TE32yFpL9afA5BbHj3KePGFY8KJ2m0sQxbQcvn2KjJC0IQ15mk0rninPhtphU/2zLsd6e7Rl1m3L+9Osk320GbfDgSKjRPcSiwVMbLJpSOP0H0F3cIu+c1fHZHfmWy0O+us42C3HTLTlD779LTnQnKlAOQD/+DYYqz6TGGxEwUG2BRQ8O8w7/wXEkg/6a/MxNtPnc59g29CpqRsDkuYiR3UIpqzLDoqHlaoKNbYy34R+4aIjfNpmZyR5kIumws+3MJtJt9UhBTMloqd8lZDPaPmX2NEDqbcSTkHMQrphk+EWSCc7OvbKRaXZ0SyJLpLjxRwKrpeO0JAI0ZpnAFS11uBEe9GSS8uzIIFNYVD1vHloAFKvUJEhyuVyz9/SyqTnArN3ZTiC5cqD1MB86q5QPrKqZfp1dAnv7xAJThL0AP/AgMBAAE=.
You need to add it to your DNS records (if not already):
Add new DNS record with type = TXT, key (subdomain/from): postmoogle._domainkey and value (to):
v=DKIM1; k=rsa; p=MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxJVqmBHhK9FY93q1o3WEaP2GKMh/3LNMyvi1uSjOKxIyfWv685KxX1EUrbHakQRCTtUM7efKEsXsXBh+DQru2TE32yFpL9afA5BbHj3KePGFY8KJ2m0sQxbQcvn2KjJC0IQ15mk0rninPhtphU/2zLsd6e7Rl1m3L+9Osk320GbfDgSKjRPcSiwVMbLJpSOP0H0F3cIu+c1fHZHfmWy0O+us42C3HTLTlD779LTnQnKlAOQD/+DYYqz6TGGxEwUG2BRQ8O8w7/wXEkg/6a/MxNtPnc59g29CpqRsDkuYiR3UIpqzLDoqHlaoKNbYy34R+4aIjfNpmZyR5kIumws+3MJtJt9UhBTMloqd8lZDPaPmX2NEDqbcSTkHMQrphk+EWSCc7OvbKRaXZ0SyJLpLjxRwKrpeO0JAI0ZpnAFS11uBEe9GSS8uzIIFNYVD1vHloAFKvUJEhyuVyz9/SyqTnArN3ZTiC5cqD1MB86q5QPrKqZfp1dAnv7xAJThL0AP/AgMBAAE=
Without that record other email servers may reject your emails as spam, kupo.
Example
$ dig TXT postmoogle._domainkey.example.com
; <<>> DiG 9.18.6 <<>> TXT postmoogle._domainkey.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59014
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;postmoogle._domainkey.example.com. IN TXT
;; ANSWER SECTION:
postmoogle._domainkey.example.com. 600 IN TXT "v=DKIM1; k=rsa; p=MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxJVqmBHhK9FY93q1o3WEaP2GKMh/3LNMyvi1uSjOKxIyfWv685KxX1EUrbHakQRCTtUM7efKEsXsXBh+DQru2TE32yFpL9afA5BbHj3KePGFY8KJ2m0sQxbQcvn2KjJC0IQ15mk0rninPhtphU/2zLsd6e7Rl1m3L+9Osk320GbfDgSKjRPcSiwVMbLJpSOP0H0F3cIu+c1fHZHfmWy0O+us42C3HTLTlD779LTnQnKlAOQD/+DYYqz6TGGxEwUG2BRQ8O8w7/wXEkg/6a/MxNtPnc59g29CpqRsDkuYiR3UIpqzLDoqHlaoKNbYy34R+4aIjfNpmZyR5kIumws+3MJtJt9UhBTMloqd8lZDPaPmX2NEDqbcSTkHMQrphk+EWSCc7OvbKRaXZ0SyJLpLjxRwKrpeO0JAI0ZpnAFS11uBEe9GSS8uzIIFNYVD1vHloAFKvUJEhyuVyz9/SyqTnArN3ZTiC5cqD1MB86q5QPrKqZfp1dAnv7xAJThL0AP/AgMBAAE="
;; Query time: 90 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Mon Sep 05 16:16:21 EEST 2022
;; MSG SIZE rcvd: 525
Usage
How to start
- Invite the bot into a room you want to use as mailbox
- Read the bot's introduction
- Set mailbox using
!pm mailbox NAMEwhereNAMEis part of email (e.g.NAME@example.com) - Done. Mailbox owner and other options will be set automatically when you configure mailbox.
If you want to change them - check available options in the help message (
!pm help)
Full list of available commands
- !pm help - Show help message
- !pm stop - Disable bridge for the room and clear all configuration
- !pm mailbox - Get or set mailbox of the room
- !pm owner - Get or set owner of the room
- !pm password - Get or set SMTP password of the room's mailbox
- !pm nosender - Get or set
nosenderof the room (true- hide email sender;false- show email sender) - !pm norecipient - Get or set
norecipientof the room (true- hide recipient;false- show recipient) - !pm nosubject - Get or set
nosubjectof the room (true- hide email subject;false- show email subject) - !pm nohtml - Get or set
nohtmlof the room (true- ignore HTML in email;false- parse HTML in emails) - !pm nothreads - Get or set
nothreadsof the room (true- ignore email threads;false- convert email threads into matrix threads) - !pm nofiles - Get or set
nofilesof the room (true- ignore email attachments;false- upload email attachments)
- !pm spamcheck:mx - only accept email from servers which seem prepared to receive it (those having valid MX records) (
true- enable,false- disable) - !pm spamcheck:smtp - only accept email from servers which seem prepared to receive it (those listening on an SMTP port) (
true- enable,false- disable) - !pm spamlist - Get or set
spamlistof the room (comma-separated list), eg:spammer@example.com,*@spammer.org,noreply@*
- !pm dkim - Get DKIM signature
- !pm catch-all - Configure catch-all mailbox
- !pm users - Get or set allowed users patterns
- !pm mailboxes - Show the list of all mailboxes
- !pm delete <mailbox> - Delete specific mailbox