Adjusts how we resolve the attachment name when processing mime
attachment parameters:
* First check Content-Disposition::filename
* Then check Content-Type::name
De-couple parsing out the `Content-Id` header from having
`Content-Disposition`.
In the lua bindings; remove the synthesized filename fallback;
we now just leave it nil to match the rust logic.
This allows us to round-trip the non-conforming encoding scheme
that is in common use, and to emit it from our own mime builder
when attaching parts with non-ascii filenames.
If it fails, then the overall message parse attempt fails out,
but we want to allow operating on the borked message at some
basic level.
This commit adjusts the logic to assume reasonable fallback
values in case the various `Content-XXX` header parsing fails,
and to defer eg: detection of an unsupported charset until
the point where the content conversion is attempted.
The invalid headers are recorded as a new INVALID_MIME_HEADERS
conformance flag which causes check_fix_conformance to decide
that the message needs to be rebuilt. The rebuild process
will come up with its own Content-XXX headers for the rebuilt
message through its existing logic.
What a mess!
RFC 2047 defines an encoded-word as a way to indicate that some
text has 8-bit content and a specific charset, allowing for inline
transfer encoding to be applied to it.
It expressly says:
An 'encoded-word' MUST NOT appear within a 'quoted-string'.
An 'encoded-word' MUST NOT be used in parameter of a MIME
Content-Type or Content-Disposition field, or in any structured
field body except within a 'comment' or 'phrase'.
Today we encountered this header:
`Content-Disposition: attachment; filename="=?UTF-8?B?5pel5pys6Kqe44Gu5re75LuY?="`
which violates both of those restrictions.
RFC 2231 is a different RFC that specifies how to encode these sorts of
headers correctly.
Hunting around a bit on the internet, it appears that someone started to
use the bogus form, perhaps as a transitional workaround, or perhaps by
mistake, and it has become something of a de-facto accepted standard to
the point that gmail and fastmail both will generate this header
construction when attaching messages.
So we need to be able to parse these out.
This commit introduces a special case for this as the last step in the
MimeParameters::get method that will try to decode the retrieved value
as an encoded-word, and if successful, return that decoded value.
This commit adds some plumbing to facilitate generation of RFC 3464
non-delivery reports and some corresponding glue to enable calling
it from lua.
Examples in the docs that are also added.
The higher level goal is to facilitate generation of RFC 3464
messages in response to delivery failures.
The first step is to introduce this synchronous (wrt. message processing
flow) event hook that will allow the message content to be optionally
captured by the hook implementation. These need to be synchronous in
this way, otherwise a terminal dispoisition (eg: permanent failure) may
decide to remove the message from the spool concurrent with the log
processing. That concurrency concern doesn't exist for the existing
logger implementations because they make a point of capturing all
information from the message prior to enqueuing the data to the logger.
Later commits will provide some convenience functions for bounce message
generation based upon that state.
At some point in the past month or two, mkdocs started to fail for
me when docs use `{{since('dev')}}` to reference the install page.
The failure is because we didn't know the correct number of ../
to emit when computing the relative path to the root, because
mkdocs doesn't support absolute paths to other markdown files.
This commit does some grubbing around to try to figure out whether we
are `foo.md` vs. `foo/index.md` because that is the heart of the
problem: both pages would be reported as having `page.url = 'foo/'` but
the markdown links need to consider the file on the filesystem rather
than the effective URL path.
This commit:
* Adds auto-discovery of both module style and crate style tests
* Runs each test via its own instance of `kumod`, so that one test
cannot pollute the state of another
* Runs all lua tests concurrently
It was possible to deadlock your policy by triggering queue
length/emptiness checks conurrently with the queue consumer thread.
Let's make it more explicitly clear which methods cannot be used that
way by making their mutex acquisition non-blocking and raise an error.
In addition, let's improve the close method so that it doesn't require
exclusive access to the consumer side of the queue.
Provide a shutdown_logging event that can be used to explicitly close
queues on shutdown, if that is appropriate for your use case.
* implement support for compression in common http server code
Adds a decompression layer to enable receipt and automatic decompression of compressed request bodies.
Signed-off-by: Daniel Schaaff <daniel@danielschaaff.com>
This enables configuring mTLS support in the listener.
Adjust TLS client tests to use this on the sink side and verify
that mTLS works for both inbound and outbound SMTP.
refs: #100
refs: #391
Fix the performance of the success test cases (they would wait 50s for a
TransientFailure that would never occur).
Add assertion for new server tls info being set and recorded in the
Reception log records on the sink side.
refs: #100
refs: #391
This commit extracts the TLS version, cipher and subject name from
the TLS state and captures it:
* In the trace headers
* In the connection metadata
* In the Reception log record
In order to capture the info in trace headers, this commit will
now change the reception protocol to ESMTPS (for SSL) or ESMTPSA (for
authenticated SSL), and emit the version and cipher information as
a comment like: `with ESMTPS (TLSv1_3:TLS13_AES_256_GCM_SHA384)`.
closes: #100
The read_dir and glob functions have been logically moved into that new
namespace, leaving deprecated versions of them in the `kumo` module.
A new `kumo.fs.open` function that works similarly to `io.open` is
provided. This function cooperates with the kumo async io scheduler
and won't block it if the filesystem is under pressure.
It returns file handles that are simlar to the builtin lua file handle
objects, but do not support formatting or parsing of writes or reads
respectively: the calling code is responsible for that. The rationale
for this difference is that is that lua's semantics for those functions
are frankly a bit weird and are hard to replicate precisely.
This function allows defining a non-durable, non-persistent, in-memory
queue that is intended to be used as glue when building up more advanced
processing flows within kumomta.
The intent is that the queue is processed from within a task spawned via
`spawn_task`.
The motivating use case here is to allow using a rebind command to
specify `smarthost:port`. You can achieve that via an invocation
like:
```
kcli rebind --everything --set queue=smarthost:port
```
or:
```
kcli rebind --everything --set routing_domain=smarthost:port
```
refs: https://github.com/KumoCorp/kumomta/issues/352
No functional changes, just adds some illustrative unit tests
that show that the routing domain portion of the queue name
string can accept a port number.
The system doesn't understand what to do about that at this
time.
refs: https://github.com/KumoCorp/kumomta/issues/352