mox/smtpserver
s0ph0s a183a9b174 Add support for negotiating IMAP, SMTP & HTTP on 443
This PR adds support for negotiating IMAP, SMTP & HTTP on the configured HTTPS port using TLS ALPN. This is intended to be useful for deploying Mox as a chatmail server. The upstream implementation of chatmail servers uses `imap` and `smtp` as the “next protocol” values for IMAP and SMTP, respectively: https://github.com/deltachat/chatmail/blob/main/cmdeploy/src/cmdeploy/nginx/nginx.conf.j2#L16-L17

To test, configure Mox as is standard for the `mox localserve` mode, but add this block under `Listeners.local`:
```sconf
		AutoconfigHTTPS:
			Enabled: true
			Port: 1443
```

Then run Mox and use OpenSSL’s s_client mode to connect to the local instance:
```
> openssl s_client -quiet -connect localhost:1443 -alpn smtp
depth=0 O = mox localserve, CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 O = mox localserve, CN = localhost
verify return:1
220 localhost ESMTP mox 7f5e1087d42d5d7bf57649c5c6a2155c3706ce39+modifications
HELO test
550 5.5.0 your ehlo domain does not resolve to an IP address (htqp11_GJOmHEhSs_Y03eg)
QUIT
221 2.0.0 okay thanks bye
^C
> openssl s_client -quiet -crlf -connect localhost:1443 -alpn imap
depth=0 O = mox localserve, CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 O = mox localserve, CN = localhost
verify return:1
* OK [CAPABILITY IMAP4rev2 IMAP4rev1 ENABLE LITERAL+ IDLE SASL-IR BINARY UNSELECT UIDPLUS ESEARCH SEARCHRES MOVE UTF8=ACCEPT LIST-EXTENDED SPECIAL-USE LIST-STATUS AUTH=SCRAM-SHA-256-PLUS AUTH=SCRAM-SHA-256 AUTH=SCRAM-SHA-1-PLUS AUTH=SCRAM-SHA-1 AUTH=CRAM-MD5 ID APPENDLIMIT=9223372036854775807 CONDSTORE QRESYNC STATUS=SIZE QUOTA QUOTA=RES-STORAGE AUTH=PLAIN] mox imap
c1 STARTTLS
c1 BAD STARTTLS unrecognized syntax/command: tls already active
^C
> openssl s_client -quiet -crlf -connect localhost:1443
depth=0 O = mox localserve, CN = localhost
verify error:num=18:self signed certificate
verify return:1
depth=0 O = mox localserve, CN = localhost
verify return:1
GET / HTTP/1.1
Host: localhost

HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Mon, 25 Nov 2024 07:28:00 GMT
Content-Length: 19

404 page not found
^C
```

As part of this change, I had to `go get golang.org/x/net/http2`. (The default `http.Server` supports HTTP2 if you leave it alone, but that built-in support is deactivated if I set `TLSNextProto` to a non-nil value. To ensure that Mox continues to support HTTP2, [the Go documentation](https://pkg.go.dev/net/http@go1.23.3#hdr-HTTP_2) directs folks with "…more complex configurations…" to import x/net/http2.) Go decided that it also wanted to update a bunch of other dependencies while it was at it. This has caused the large number of dependency updates. I can revert these and attempt a more surgical addition of the http2 library, if you’d like.

There are also two major deficiencies in this code that I’d like advice on correcting:
1. Right now, this ALPN feature is enabled when Mox is configured to provide Autoconfigure services to mail clients. I chose to do this because it was relatively straightforward to implement. However, the resulting behavior is extremely non-obvious. **How would you recommend exposing the ALPN feature in the configuration?**
2. I’m not sure what the best way to expose the private `serve()` functions in `imapserver` and `smtpserver` are. The current implementation creates a public function called `ServeConn()` in each module that just calls the private `serve()` function with all the same arguments, but this feels redundant. **Would you recommend making the `serve()` functions public, using public wrappers but with a more limited set of parameters, or something else entirely?**

Thanks!
2024-11-25 02:48:42 -05:00
..
alias_test.go when opening an account by email address, such as during login attempts, and address is an alias, fail with proper error "no such credentials" instead of with error "no such account", which printing a stack trace 2024-11-10 23:20:17 +01:00
alignment.go switch to slog.Logger for logging, for easier reuse of packages by external software 2023-12-14 13:45:52 +01:00
analyze.go fix embarrasing bug in checking if string is ascii 2024-10-04 20:05:28 +02:00
dnsbl.go switch to slog.Logger for logging, for easier reuse of packages by external software 2023-12-14 13:45:52 +01:00
dsn.go ensure senderaccount is always set for messages in queue 2024-04-28 11:03:47 +02:00
error.go for imap/smtp syntax errors, only echo the remaining buffer if the connection is authenticated 2023-03-10 11:32:34 +01:00
fuzz_test.go in more tests, after closing accounts, check the last reference is indeed gone 2024-04-16 17:33:54 +02:00
limitwriter.go mox! 2023-01-30 14:27:06 +01:00
mx.go implement dnssec-awareness throughout code, and dane for incoming/outgoing mail delivery 2023-10-10 12:09:35 +02:00
parse.go add parser of Authentication-Results, and fix bugs it found in our generated headers 2024-03-13 17:35:53 +01:00
parse_test.go mox! 2023-01-30 14:27:06 +01:00
rejects.go replace packages slog and slices from golang.org/x/exp with stdlib 2024-02-08 14:49:01 +01:00
reputation.go add more details to x-mox-reason message header added during delivery, for understanding why a message is accepted/rejected 2024-10-04 16:01:30 +02:00
reputation_test.go add more details to x-mox-reason message header added during delivery, for understanding why a message is accepted/rejected 2024-10-04 16:01:30 +02:00
server.go Add support for negotiating IMAP, SMTP & HTTP on 443 2024-11-25 02:48:42 -05:00
server_test.go use debug logging in tests 2024-05-10 15:51:48 +02:00