piknik
piknik copied to clipboard
feat: add lmtp support to smtp transport
I'm not sure what this API should look like, but I have tried my best to reuse most of the code.
Maybe it would be better to store LMTP as a config parameter and return multiple responses for plain SMTP too, instead of specializing on LMTP protocol using const generic?
I have tried implementing separate struct for LMTP protocol, wrapping SMTP, however it would be too much boilerplate to delegate every method except send to wrapped SMTP connection.
I also have tried to use sealed generic instead of boolean const, but this didn't go well too (But maybe this approach can be implemented, if I'll try harder?)
trait Protocol;
struct Smtp;
struct Lmtp;
impl Protocol for Smtp {}
impl Protocol for Lmtp {}
impl<P: Protocol> MtpConnection<P> {...}
impl MtpConnection<Smtp> {...}
impl MtpConnection<Lmtp> {...}
Fixes: https://github.com/lettre/lettre/issues/820
Thanks for the PR. I'll try looking at it in the following days.
Any progress?
How does this handle failures for individual recipients (https://datatracker.ietf.org/doc/html/rfc2033#section-4.3)? I think it might need to return a Vec<Result<Response, Error>> with one entry for each recipient.
I would also prefer to have LMTP separated out rather than a boolean parameter to the SMTP code that says "not actually SMTP". Possibly refactor the common code as "MailTransferProtocols" and then implement (E)SMTP and LMTP on top of that.
Other than that I'd love to see LMTP in lettre.
How does this handle failures for individual recipients (https://datatracker.ietf.org/doc/html/rfc2033#section-4.3)? I think it might need to return a Vec<Result<Response, Error>> with one entry for each recipient.
It does that using command_negative method, which skips conversion from negative response to Result, thus every response in the result vector might be negative, and that is exactly what we want.
Top-level error then only provides pool/server errors, such as connection failures, and usage of unsupported features in envelope, and I think this is the way it should work with the LMTP server (I have looked at the spec while implementing this feature, but I don't remember the exact motivation now).
I would also prefer to have LMTP separated out rather than a boolean parameter to the SMTP code that says "not actually SMTP". Possibly refactor the common code as "MailTransferProtocols" and then implement (E)SMTP and LMTP on top of that.
Yep, I don't like current approach (boolean generic) either, but I haven't managed to come with the better implementation, and I'm too lazy to implement it the other way.
I will finish this PR if we decide that current implementation is ok, or figure out an easier implementation with least amount of code duplication.
How does this handle failures for individual recipients (https://datatracker.ietf.org/doc/html/rfc2033#section-4.3)? I think it might need to return a Vec<Result<Response, Error>> with one entry for each recipient.
It does that using
command_negativemethod, which skips conversion from negative response to Result, thus every response in the result vector might be negative, and that is exactly what we want.
Oh yes I see it now, thanks. https://github.com/CertainLach/lettre/blob/5a68a43b9e449d27632cc9213552db5488c68a9c/src/transport/smtp/client/connection.rs#L410