Commit Graph
1142 Commits
Author SHA1 Message Date
Wez Furlong fae08d33ab mailparsing: add Content-Disposition header 2023-08-13 22:10:15 -07:00
Wez Furlong e862291a5b mailparsing: tidy up and add some accessors 2023-08-13 22:10:15 -07:00
Wez Furlong fda09f0e7f mailparsing: collect child mime parts during parsing 2023-08-13 22:10:15 -07:00
Wez Furlong c3f6a10e6f mailparsing: factor out the rfc2045 info 2023-08-13 22:10:15 -07:00
Wez Furlong 2de1d0e316 mailparsing: add content-transfer-encoding decoding 2023-08-13 22:10:15 -07:00
Wez Furlong 00ebca113b mailparsing: impl EncodeHeaderValue for MimeParameters 2023-08-13 22:10:15 -07:00
Wez Furlong c943cf4d69 mailparsing: add Content-Type header parsing
This deals with the messy situation that is rfc 2231, and completes the
removal of pest from the mailparsing crate.
2023-08-13 22:10:15 -07:00
Wez Furlong 896e791e7c mailparsing: use AddrSpec rather than String in Mailbox
Since we need to be able to quote the local part, let's
use the structured type.
2023-08-13 22:10:14 -07:00
Wez Furlong 6edc40d17c mailparse: migrate unstructured header parsing to nom 2023-08-13 22:10:14 -07:00
Wez Furlong 278dd428f8 mailparsing: migrate msg_id header parsing to nom 2023-08-13 22:10:14 -07:00
Wez Furlong 985bb46447 mailparsing: migrate address list parsing to nom 2023-08-13 22:10:14 -07:00
Wez Furlong 0dbdff2a63 mailparsing: begin migrating to nom
I'd initially avoided this because I thought that pest would make
things easier overall, but I'm facing an impossible to debug
situation with the pest parser because the error/diagnostics
are not very friendly.

This commit introduces some plumbing that uses nom to build
the parser; the error reporting is much easier to understand
as we can annotate context information and display it in
an error-chain style with a helpful caret to highlight the
problem spots.

I'll convert more over in subsequent commits; this one is getting
large so this is a checkpoint.
2023-08-13 22:10:14 -07:00
Wez Furlong f8bb7a818e WIP: content-type header parsing 2023-08-13 22:10:14 -07:00
Wez Furlong 69fe6b2156 mailparsing: add Header::new_unstructured, improve 2047 handling 2023-08-13 22:10:14 -07:00
Wez Furlong 592a0eb750 mailparsing: more tests for quoting strings 2023-08-13 22:10:14 -07:00
Wez Furlong c1a4df279f mailparsing: start building out structured header assignment 2023-08-13 22:10:14 -07:00
Wez Furlong 1370eb25f2 mailparsing: refactor headermap ala DRY 2023-08-13 22:10:13 -07:00
Wez Furlong 75bb58d401 mailparsing: fix FIXME for obs_angle_addr 2023-08-13 22:10:13 -07:00
Wez Furlong f100b6f15a mailparse: fix FIXME for obs_phrase 2023-08-13 22:10:13 -07:00
Wez Furlong f2d086c997 mailparsing: support parsing rfc6532 internationalized headers 2023-08-13 22:10:13 -07:00
Wez Furlong 74a70e5650 mailparsing: support unstructured header field parsing 2023-08-13 22:10:13 -07:00
Wez Furlong 6896ddca26 mailparsing: tweak for rfc2184 2023-08-13 22:10:13 -07:00
Wez Furlong 82c5f17177 mailparsing: add message-id parsing 2023-08-13 22:10:13 -07:00
Wez Furlong 29ac66db4c mailparsing: add AddressList 2023-08-13 22:10:13 -07:00
Wez Furlong 6e52594de4 mailparsing: add Mailbox and MailboxList header parsing
For eg: the Sender and From headers.

This commit introduces a parser for RFC 5322 message header syntax,
as modified by RFC 2047 for encoded header fields.
2023-08-13 22:10:13 -07:00
Wez Furlong 41d7bf406f mailparsing: add HeaderMap 2023-08-13 22:10:12 -07:00
Wez Furlong 72e7118c46 mailparsing: refactor header parse result 2023-08-13 22:10:12 -07:00
Wez Furlong 4d945a7c52 add mailparsing crate
This kicks off our own mail parsing and building crate
2023-08-13 22:10:12 -07:00
Wez Furlong fc784caf07 cargo update 2023-08-13 22:09:40 -07:00
Wez Furlong 5bea1013da trace_smtp_server: add colorized output
Makes it easier to see the sent vs. received data
2023-08-13 16:57:00 -07:00
Wez Furlong 4f53566fde trace_smtp_server: show meta keys one per line
This makes it easier to read and see what changed
2023-08-13 16:40:04 -07:00
Wez Furlong c3e6a4fce7 trace_smtp_server: add timestamp to trace events 2023-08-13 15:34:28 -07:00
Wez Furlong 81ff4043e3 add kcli trace-smtp-server subcommand
This allows tracing incoming SMTP sessions.

Sessions are traced through to the cli in realtime.

The implementation is via a websocket, which makes this also potentially
pluggable into a webui in the future, although care must be taken to
ensure that only authorized system operators can enable this, as it can
reveal authentication secrets in the traced dialog, as well as the
content of messages.

This commit doesn't include documentation on the shape of the websocket
JSON at this time.

refs: https://github.com/KumoCorp/kumomta/issues/44

```
; ./target/debug/kcli trace-smtp-server
[127.0.0.1:51778->127.0.0.1:2025] === Connected {"received_from":"127.0.0.1:51778","received_via":"127.0.0.1:2025","reception_protocol":"ESMTP"}
[127.0.0.1:51778->127.0.0.1:2025] <-  220 foo Welcome to KumoMTA!
[127.0.0.1:51778->127.0.0.1:2025]  -> EHLO foo.lan
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_ehlo: Ok
[127.0.0.1:51778->127.0.0.1:2025] <-  250-foo Aloha foo.lan
[127.0.0.1:51778->127.0.0.1:2025] <-  250-PIPELINING
[127.0.0.1:51778->127.0.0.1:2025] <-  250-ENHANCEDSTATUSCODES
[127.0.0.1:51778->127.0.0.1:2025] <-  250 STARTTLS
[127.0.0.1:51778->127.0.0.1:2025]  -> STARTTLS
[127.0.0.1:51778->127.0.0.1:2025] <-  220 Ready to Start TLS
[127.0.0.1:51778->127.0.0.1:2025]  -> EHLO foo.lan
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_ehlo: Ok
[127.0.0.1:51778->127.0.0.1:2025] <-  250-foo Aloha foo.lan
[127.0.0.1:51778->127.0.0.1:2025] <-  250-PIPELINING
[127.0.0.1:51778->127.0.0.1:2025] <-  250-ENHANCEDSTATUSCODES
[127.0.0.1:51778->127.0.0.1:2025] <-  250 AUTH PLAIN
[127.0.0.1:51778->127.0.0.1:2025]  -> AUTH PLAIN AHNjb3R0AHRpZ2Vy
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_auth_plain: Ok: Bool(true)
[127.0.0.1:51778->127.0.0.1:2025] <-  235 2.7.0 AUTH OK!
[127.0.0.1:51778->127.0.0.1:2025] === conn_meta updated to {"authn_id":"scott","authz_id":"scott","received_from":"127.0.0.1:51778","received_via":"127.0.0.1:2025","reception_protocol":"ESMTP"}
[127.0.0.1:51778->127.0.0.1:2025]  -> MAIL FROM:<wez@example.com>
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_mail_from: Ok
[127.0.0.1:51778->127.0.0.1:2025] <-  250 OK EnvelopeAddress(\"wez@example.com\")
[127.0.0.1:51778->127.0.0.1:2025]  -> RCPT TO:<wez@wezfurlong.org>
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_rcpt_to: Ok
[127.0.0.1:51778->127.0.0.1:2025] <-  250 OK EnvelopeAddress(\"wez@wezfurlong.org\")
[127.0.0.1:51778->127.0.0.1:2025]  -> DATA
[127.0.0.1:51778->127.0.0.1:2025] <-  354 Send body; end with CRLF.CRLF
[127.0.0.1:51778->127.0.0.1:2025]  -> Date: Sun, 13 Aug 2023 10:10:40 -0700
[127.0.0.1:51778->127.0.0.1:2025]  -> To: wez@wezfurlong.org
[127.0.0.1:51778->127.0.0.1:2025]  -> From: wez@example.com
[127.0.0.1:51778->127.0.0.1:2025]  -> Subject: test Sun, 13 Aug 2023 10:10:40 -0700
[127.0.0.1:51778->127.0.0.1:2025]  -> Message-Id: <20230813101040.1426417@foo>
[127.0.0.1:51778->127.0.0.1:2025]  -> X-Mailer: swaks v20201014.0 jetmore.org/john/code/swaks/
[127.0.0.1:51778->127.0.0.1:2025]  ->
[127.0.0.1:51778->127.0.0.1:2025]  -> This is a test mailing
[127.0.0.1:51778->127.0.0.1:2025]  ->
[127.0.0.1:51778->127.0.0.1:2025]  ->
[127.0.0.1:51778->127.0.0.1:2025]  -> .
[127.0.0.1:51778->127.0.0.1:2025] === smtp_server_message_received: Ok
[127.0.0.1:51778->127.0.0.1:2025] === Message from=wez@example.com to=wez@wezfurlong.org id=5465de7739fc11ee8af250ebf67f93bd
[127.0.0.1:51778->127.0.0.1:2025] === Message queue=wezfurlong.org relay=true log_arf=false log_oob=false
[127.0.0.1:51778->127.0.0.1:2025] === Message meta: {"authn_id":"scott","authz_id":"scott","received_from":"127.0.0.1:51778","received_via":"127.0.0.1:2025","reception_protocol":"ESMTP"}
[127.0.0.1:51778->127.0.0.1:2025] <-  250 OK ids=5465de7739fc11ee8af250ebf67f93bd
[127.0.0.1:51778->127.0.0.1:2025]  -> QUIT
[127.0.0.1:51778->127.0.0.1:2025] <-  221 So long, and thanks for all the fish!
[127.0.0.1:51778->127.0.0.1:2025] === Closed
```
2023-08-13 10:17:04 -07:00
Wez Furlong 55770052a5 add kumo.encode module
This provides a variety of encode/decode functions for things
like base64 and base32 encoding
2023-08-12 08:42:44 -07:00
Wez Furlong a73912e7e1 rollup.lua: remove stray debug print 2023-08-12 07:24:29 -07:00
Wez Furlong d35bffc80d Automated doc formatting fix 2023-08-12 13:55:14 +00:00
Wez Furlong 7aa80bc34a rollup.lua: add ip-based rollup
How it works:

* When the lowest preference MX host names match a pattern like
  `.mail.protection.outlook.com`, the message has its routing_domain
  set to a placeholder domain whose name ends with `.ip_rollup`.
* That results in a scheduled queue name like
  `foo.com!outlook.ip_rollup`, which makes it possible to know both the
  original domain and the fact that rollup is in use.
* `get_queue_config` can check to see if the routing_domain is set to
  something that ends with `.ip_rollup` to override the `mx_list`
  in the queue configuration with just the lowest preference IP
  addresses from the original domain.
* Now, instead of computing a site_name base around
  `foo-com.mail.protection.outlook.com`, which includes the individual
  original recipient domain, and would cause there to be a separate
  ready queue for each domain, the overridden mx_list causes
  the site_name to be eg: `mx_list:[104.47.24.36],[104.47.25.36]`.
  That same site_name will be used for every domain that shares those
  same IP addresses
* When `get_egress_path_config` is called to get shaping parameters,
  it is passed the routing domain `outlook.ip_rollup`. You can use that
  name with mx_rollup=false as the key in your shaping.toml, of if you
  are directly implementing `get_egress_path_config`, you can use that
  name to determine the appropriate configuration.

```lua
kumo.on('get_queue_config', function(domain, tenant, campaign, routing_domain)
  local params = {}
  rollup.apply_ip_rollup_to_queue_config(domain, routing_domain, params
  return kumo.make_queue_config(params)
end)

kumo.on('smtp_server_message_received', function(msg)
  rollup.reroute_using_ip_rollup(msg, {
    ['.mail.protection.outlook.com.'] = 'outlook.ip_rollup',
  })
end)
```

In your shaping.toml:

```toml
["outlook.ip_rollup"]
mx_rollup = false
 # shaping parameters here
```

Caveats:

* With this technique, we'll never try to use any of the lower
  priority/higher preference value MX records for any of the matching
  domains.
* The IP addresses to which the MX host names resolve can vary over time.
  We'll still queue the mail to the same scheduled queue (eg:
  `foo.com!outlook.ip_rollup`), but it's possible for there to be
  multiple ready queues with different names based on those changed
  IPs.  This is actually a feature: if the destination domain has
  an outage and are now publishing different IPs, we'll pick those up
  and use them.
* Since the ready queue names look like `mx_list:[104.47.24.36],[104.47.25.36]`
  it can be hard to intuit just from glancing at that name where those queues go.
2023-08-12 06:52:39 -07:00
Wez Furlong 99fcfbc64e kumod: refresh queue_config periodically
This commit causes the scheduled queue maintainer to refresh
the queue config by calling the get_queue_config event approximately
every minute while the queue is alive.

In addition, we now thread the routing_domain through to get_queue_config
2023-08-12 06:22:54 -07:00
Wez Furlong d8a6bceef0 add kumo.digest lua module
Compute hashes
2023-08-11 21:44:40 -07:00
Wez Furlong e042e81de9 kumo.dns: add lookup_addr function
Resolves a hostname to its v4 and v6 addresses and returns them.

Fixes up a typo in the docs for lookup_mx that incorrectly
showed it as resolve_mx.
2023-08-11 16:51:54 -07:00
Wez Furlong a6b79054b7 traffic-gen: rename --domain to --domain-suffix, add new --domain opt
You may now remove or replace the test domain suffix from the set
of senders/recipients by usingn `--domain-suffix ''` to remove
it, or some other value to set it to something else.

`--domain` can now be used multiple times to build out the list
of test domains.
2023-08-11 12:37:15 -07:00
Wez Furlong a6a711e72f simple_policy: remove rollup from testing policy 2023-08-11 12:36:54 -07:00
Wez Furlong 9d1ca9dc11 routing.md: update to show new smart hosting options 2023-08-11 11:17:02 -07:00
Wez Furlong dc78142c35 docs: operation: tidy up formatting, show more kcli usage 2023-08-11 10:36:32 -07:00
Wez Furlong 55237b94ef spool.md: tweak layout, make it obvious that we rec. RocksDB 2023-08-11 09:58:47 -07:00
Wez Furlong 811b64c1ff example.md: fixup example
Needs to pull in the utils to use merge_into
2023-08-11 09:55:13 -07:00
Wez Furlong 00f2a95335 dkim.md: fixup links, tidy up some formatting, wordwrap 2023-08-11 09:53:08 -07:00
Wez Furlong 6545e8c0a5 queuemanagement.md: fixup examples, add cross links 2023-08-11 09:45:47 -07:00
Wez Furlong 2fc79766f2 sendingips.md: rearrange contents for the common case
We had a user get tripped up by the incorrect example on this page.
I think they probably should have been using the helper, but the
way this page was constructed, it was easy to keep reading past
the bit about the helper and get bogged down by the lua examples.

Rearrange this page to try to avoid that.
2023-08-11 09:36:18 -07:00
Wez Furlong a8ea458ced sendingips.md: fix incorrect pool lua example
I've seen this trip up at least two people so far.

While we're in there, update the example to show how to memoize and make
it both easier to write and more efficient at runtime.
2023-08-11 09:30:31 -07:00