275 lines
11 KiB
Markdown
275 lines
11 KiB
Markdown
# Postmoogle [](https://matrix.to/#/#postmoogle:etke.cc)[](https://ko-fi.com/etkecc) [](https://gitlab.com/etke.cc/postmoogle/-/commits/main) [](https://goreportcard.com/report/gitlab.com/etke.cc/postmoogle) [](https://pkg.go.dev/gitlab.com/etke.cc/postmoogle)
|
|
|
|
> [more about that name](https://finalfantasy.fandom.com/wiki/The_Little_Postmoogle_That_Could)
|
|
|
|
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
|
|
|
|
- [x] SMTP server (plaintext and SSL)
|
|
- [x] Matrix bot
|
|
- [x] Configuration in room's account data
|
|
- [x] Receive emails to matrix rooms
|
|
- [x] Receive attachments
|
|
- [x] Catch-all mailbox
|
|
- [x] 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
|
|
|
|
- [x] SMTP client
|
|
- [x] SMTP server (you can use Postmoogle as general purpose SMTP server to send emails from your scripts or apps)
|
|
- [x] Send a message to matrix room with special format to send a new email
|
|
- [ ] 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
|
|
|
|
<details>
|
|
<summary>other optional config parameters</summary>
|
|
|
|
* **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_USERS` for syntax examples
|
|
|
|
You can find default values in [config/defaults.go](config/defaults.go)
|
|
|
|
</details>
|
|
|
|
### 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).
|
|
|
|
<details>
|
|
<summary>TL;DR</summary>
|
|
|
|
1. Configure DMARC record
|
|
2. Configure SPF record
|
|
3. Configure MX record
|
|
4. Configure DKIM record (use `!pm dkim`)
|
|
|
|
</details>
|
|
|
|
**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;`.
|
|
|
|
<details>
|
|
<summary>Example</summary>
|
|
|
|
```bash
|
|
$ 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
|
|
```
|
|
|
|
</details>
|
|
|
|
**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)
|
|
|
|
<details>
|
|
<summary>Example</summary>
|
|
|
|
```bash
|
|
$ 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
|
|
```
|
|
|
|
</details>
|
|
|
|
**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.
|
|
|
|
<details>
|
|
<summary>Example</summary>
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
</details>
|
|
|
|
**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:
|
|
|
|
<details>
|
|
<summary>!pm dkim</summary>
|
|
|
|
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.
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Example</summary>
|
|
|
|
```bash
|
|
$ 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
|
|
```
|
|
|
|
</details>
|
|
|
|
## Usage
|
|
|
|
### How to start
|
|
|
|
1. Invite the bot into a room you want to use as mailbox
|
|
2. Read the bot's introduction
|
|
3. Set mailbox using `!pm mailbox NAME` where `NAME` is part of email (e.g. `NAME@example.com`)
|
|
4. 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`)
|
|
|
|
<details>
|
|
<summary>Full list of available commands</summary>
|
|
|
|
* **!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 `nosender` of the room (`true` - hide email sender; `false` - show email sender)
|
|
* **!pm norecipient** - Get or set `norecipient` of the room (`true` - hide recipient; `false` - show recipient)
|
|
* **!pm nosubject** - Get or set `nosubject` of the room (`true` - hide email subject; `false` - show email subject)
|
|
* **!pm nohtml** - Get or set `nohtml` of the room (`true` - ignore HTML in email; `false` - parse HTML in emails)
|
|
* **!pm nothreads** - Get or set `nothreads` of the room (`true` - ignore email threads; `false` - convert email threads into matrix threads)
|
|
* **!pm nofiles** - Get or set `nofiles` of 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 `spamlist` of 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
|
|
|
|
</details>
|
|
|
|
|
|
## Where to get
|
|
|
|
[docker registry](https://gitlab.com/etke.cc/postmoogle/container_registry), [etke.cc](https://etke.cc)
|