piknik icon indicating copy to clipboard operation
piknik copied to clipboard

Add raw header support to MessageBuilder

Open demurgos opened this issue 2 years ago • 4 comments

Is your feature request related to a problem? Please describe. My project supports configuring the SMTP client through a configuration file: SMTP server, sender mailbox, credentials, etc. One of the settings is a custom list of extra headers to add to each outbound email. Custom headers are required for some providers but I don't want to hardcode these headers. For example, Postmark requires the X-PM-Message-Stream: outbound header.

I am now switching our implementation to be based on Lettre but fail to see how to support custom headers that are unknown at compile time (I can impl Header for a custom struct, but the name needs to be known at compile time).

Describe the solution you'd like I would like the message builder to provide a method such as .raw_header(name: HeaderName, value: String); or an API such as .header(RawHeader::new(name, value)) to allow adding headers where the name is not known at compile-time.

Looking into the code, I feel that it would involve having a cleaner separation between header types and header values (why do I need to implement parse for headers I intend to only write? It also makes it very complicated to get a dyn Header). I would also expect this feature to require changes to the Headers struct, so its API is closer to http:header::HeaderMap (which serves the same goal).

Describe alternatives you've considered An alternative would be to maintain a predefined list of known headers and handle the conversion from the list of raw headers to the strongly typed known headers myself. This is not desirable because it requires me to restrict the configuration to only known headers while new headers may be required by mail services at any time.

Additional context I suggest taking inspiration from how the http crate deals with its headers: it benefited from more work and usage.

demurgos avatar Aug 20 '21 07:08 demurgos

Did you find a solution to this issue @paolobarbolini ?

Hugo-Persson avatar Feb 09 '23 13:02 Hugo-Persson

Any plans to implement arbitrary headers? Is there an example how to add custom header to an outgoing email?

tosiara avatar Sep 28 '23 12:09 tosiara

Here is an example for an outgoing header:

#[derive(Clone,Debug)]
pub struct ListId<'a>(pub &'a str);

impl<'a> lettre::message::header::Header for ListId<'a> {
	fn name() -> lettre::message::header::HeaderName {
		lettre::message::header::HeaderName::new_from_ascii_str("List-Id")
	}

	fn parse(_: &str) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
		unimplemented!()
	}

	fn display(&self) -> lettre::message::header::HeaderValue {
		lettre::message::header::HeaderValue::new(
			Self::name(),
			self.0.into())
	}
}

kevincox avatar Sep 28 '23 12:09 kevincox