Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As we have seen in a number of issues and PRs, users report the need to parse non-compliant emails. This PR offers a first draft of the idea of allowing per-header custom parsers.
Rationale
Rather than entertaining every single discussion and discovery of another way how an email spotted in the wild can broken and offering an ad-hoc fix for dates, unescaped characters, etc., I would like to offer our users the possibility to customise the default headers parsers to their needs.
This will allow them to parse the emails they encounter faster (e.g. they can write a custom parser for their need without waiting for the maintainers of letters to triage the issue and catch up to their needs) and will allow us to concentrate on developing the core functionality rather than focusing on non-compliant edge cases.
How
I have briefly considered allowing per-type parser customisation, e.g. configuring the parser with a
WithCustomDateFn()
,WithCustomAddressFn()
,WithCustomAddressListFn()
, etc. but I concluded that this might not be flexible enough.Per-type custom parsers would force users to parse different headers of the same type (e.g.
Date
andResentDate
) with the same parser (e.g. aCustomDateTypeHeaderParser()
).Instead, I am suggesting that we allow per-header configuration, e.g.:
That way,
WithDateHeaderParser()
andWithResentDateHeaderParser()
can take differently customised functions.ExtraHeaders is a special case, it takes a map of string to parseStringHeaderFn type, to allow custom-parsing of any arbitrary extra headers by name.
The suggested implementation is pretty verbose, but I opted for strict typing, even of the parser function types.
More tests and updated documentation is still needed, but the implementation should already by largely correct.