Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom headers parsers #134

Merged
merged 4 commits into from
Feb 26, 2025
Merged

Conversation

mnako
Copy link
Owner

@mnako mnako commented Feb 21, 2025

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 and ResentDate) with the same parser (e.g. a CustomDateTypeHeaderParser()).

Instead, I am suggesting that we allow per-header configuration, e.g.:

emailParser: letters.NewEmailParser(
	letters.WithDateHeaderParser(
		func(s string) time.Time {
			// take the raw Date header, decode, and parse it
			// according to your needs here
		},
	),
)

That way, WithDateHeaderParser() and WithResentDateHeaderParser() 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.

@mnako mnako requested a review from ValleyCrisps February 21, 2025 15:42
@mnako mnako self-assigned this Feb 21, 2025
Lint code and documentation.
Lint code and documentation.
ValleyCrisps
ValleyCrisps previously approved these changes Feb 24, 2025
@mnako mnako changed the title wip: Allow custom headers parsers Allow custom headers parsers Feb 25, 2025
@mnako mnako merged commit 4e3cf3c into main Feb 26, 2025
7 checks passed
@mnako mnako deleted the feature/allow-custom-header-parsers branch February 26, 2025 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants