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

Remove non-SMTP transports and connection setup code #57

Merged
merged 1 commit into from
Jan 31, 2023
Merged

Conversation

link2xt
Copy link
Collaborator

@link2xt link2xt commented Jan 25, 2023

Remove connection setup and all the "transports" except SMTP.

Now the user is responsible for providing a stream with TLS, read and write timeouts, buffering, SOCKS5 etc.

This makes it possible to have proper read and write timeouts instead of per-command timeouts,
use alternative TLS implementations such as Rustls and use SMTP over other proxies, such as HTTP CONNECT, without modifying the library.

let mut codec = ClientCodec::new();
let mut buf: Vec<u8> = vec![];

assert!(codec.encode(b"test\r\n", &mut buf).await.is_ok());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use Result/? to be less verbose?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was only moved around, it's not new code, so I think it makes sense to leave it as is.

src/smtp_client.rs Outdated Show resolved Hide resolved

/// Sends an AUTH command with the given mechanism, and handles challenge if needed
pub async fn auth(&mut self, mechanism: Mechanism, credentials: &Credentials) -> SmtpResult {
// TODO
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not new code, it is moved from src/smtp/client/inner.rs as is.

.command(AuthCommand::new(mechanism, credentials.clone(), None)?)
.await?;

while challenges > 0 && response.has_code(334) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant with a comment?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, moved code. Would be nice to cleanup, but I want to avoid changing it in this PR.

}

if challenges == 0 {
Err(Error::ResponseParsing("Unexpected number of challenges"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Number of challenges > N" would be more informative

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, the code was only moved

sent_commands += 1;

for _ in 0..sent_commands {
self.stream.read_response().await?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe read responses in parallel with sending commands? Can't RX overflow and server stop reading from the socket in the current approach?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened an issue at #58 so we don't forget,
but it's out of scope for this PR.

loop {
let read = reader.read_line(&mut buffer).await?;
if read == 0 {
break;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not return right from here? And does it need a special handling? Won't buffer be empty and parse_response() fail as needed?

Copy link
Collaborator

@Hocuri Hocuri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that much about this network stuff, either, but from what i can tell, lgtm.


impl<S: Read + Write + Unpin> SmtpTransport<S> {
/// Creates a new SMTP transport and connects.
pub async fn new(builder: SmtpClient, stream: S) -> Result<Self, Error> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a while to get why it's called builder, maybe call it smtp_client for the sake of least astonishment?

}

if challenges == 0 {
Err(Error::ResponseParsing("Unexpected number of challenges"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, the code was only moved

src/types.rs Outdated
Comment on lines 162 to 165
pub fn new(envelope: Envelope, message: impl AsRef<[u8]>) -> SendableEmail {
SendableEmail {
envelope,
message_id: message_id.as_ref().into(),
message: Message::Bytes(Cursor::new(message.as_ref().to_vec())),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make message: impl AsRef<[u8]> and then always call message.as_ref().to_vec()? Wouldn't it make sense to just make message: Vec<[u8]>? Then the caller has to sometimes call to_vec() themselves, but that seems OK.

After I wrote my comment, I noticed that you didn't introduce the AsRef, so we can just leave it as is for now. Then again, a major version bump is the only chance to do this change. Anyway, do as you like :)

@link2xt link2xt changed the title Version 2.0 Version 0.7.0 Jan 31, 2023
@link2xt link2xt changed the title Version 0.7.0 Remove non-SMTP transports and connection setup code Jan 31, 2023
Now the user is responsible for providing a stream with
TLS, read and write timeouts, buffering, SOCKS5 etc.

This makes it possible to have proper read and write
timeouts instead of per-command timeouts,
use alternative TLS implementations such as Rustls
and use SMTP over other proxies, such as HTTP CONNECT,
without modifying the library.
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.

None yet

3 participants