Skip to content

Commit 0545405

Browse files
committed
First try
1 parent f0614fc commit 0545405

File tree

6 files changed

+80
-20
lines changed

6 files changed

+80
-20
lines changed

src/file/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
//! It can be useful for testing purposes, or if you want to keep track of sent messages.
44
//!
55
6-
use std::path::PathBuf;
6+
use std::{path::PathBuf, time::Duration};
77

88
use async_std::fs::File;
99
use async_std::path::Path;
1010
use async_std::prelude::*;
1111
use async_trait::async_trait;
12-
use serde_json;
1312

1413
use crate::file::error::FileResult;
1514
use crate::Envelope;
@@ -71,4 +70,12 @@ impl<'a> Transport<'a> for FileTransport {
7170
.await?;
7271
Ok(())
7372
}
73+
74+
async fn send_with_timeout(
75+
&mut self,
76+
email: SendableEmail,
77+
_timeout: Option<&Duration>,
78+
) -> Self::Result {
79+
self.send(email).await // Writing to a file does not have a timeout, so just ignore it.
80+
}
7481
}

src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub use crate::smtp::client::net::ClientTlsParameters;
3434
pub use crate::smtp::{ClientSecurity, SmtpClient, SmtpTransport};
3535

3636
use async_trait::async_trait;
37+
use std::time::Duration;
3738

3839
/// Transport method for emails
3940
#[async_trait]
@@ -43,4 +44,10 @@ pub trait Transport<'a> {
4344

4445
/// Sends the email
4546
async fn send(&mut self, email: SendableEmail) -> Self::Result;
47+
48+
async fn send_with_timeout(
49+
&mut self,
50+
email: SendableEmail,
51+
timeout: Option<&Duration>,
52+
) -> Self::Result;
4653
}

src/sendmail/mod.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use async_trait::async_trait;
1010
use log::info;
1111
use std::convert::AsRef;
1212
use std::io::prelude::*;
13-
use std::process::{Command, Stdio};
13+
use std::{
14+
process::{Command, Stdio},
15+
time::Duration,
16+
};
1417

1518
pub mod error;
1619

@@ -84,9 +87,17 @@ impl<'a> Transport<'a> for SendmailTransport {
8487
.await?;
8588

8689
if output.status.success() {
87-
return Ok(());
90+
Ok(())
91+
} else {
92+
Err(error::Error::Client(String::from_utf8(output.stderr)?))
8893
}
94+
}
8995

90-
Err(error::Error::Client(String::from_utf8(output.stderr)?))
96+
async fn send_with_timeout(
97+
&mut self,
98+
email: SendableEmail,
99+
_timeout: Option<&Duration>,
100+
) -> Self::Result {
101+
self.send(email).await
91102
}
92103
}

src/smtp/client/inner.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<S: Connector + Write + Read + Unpin> InnerClient<S> {
9999
}
100100

101101
/// Get the read and write timeout.
102-
pub fn timeout(&mut self) -> Option<&Duration> {
102+
pub fn timeout(&self) -> Option<&Duration> {
103103
self.timeout.as_ref()
104104
}
105105

@@ -194,25 +194,41 @@ impl<S: Connector + Write + Read + Unpin> InnerClient<S> {
194194
})
195195
.await?;
196196

197-
self.read_response().await
197+
let timeout = self.timeout().cloned();
198+
self.read_response(timeout.as_ref()).await
198199
}
199200

200201
/// Send the given SMTP command to the server.
201-
pub async fn command<C: Display>(mut self: Pin<&mut Self>, command: C) -> SmtpResult {
202-
self.as_mut().write(command.to_string().as_bytes()).await?;
203-
self.read_response().await
202+
pub async fn command<C: Display>(self: Pin<&mut Self>, command: C) -> SmtpResult {
203+
let timeout = self.timeout;
204+
self.command_with_timeout(command, timeout.as_ref()).await
205+
}
206+
207+
pub async fn command_with_timeout<C: Display>(
208+
mut self: Pin<&mut Self>,
209+
command: C,
210+
timeout: Option<&Duration>,
211+
) -> SmtpResult {
212+
self.as_mut()
213+
.write(command.to_string().as_bytes(), timeout)
214+
.await?;
215+
self.read_response(timeout).await
204216
}
205217

206218
/// Writes the given data to the server.
207-
async fn write(mut self: Pin<&mut Self>, string: &[u8]) -> Result<(), Error> {
219+
async fn write(
220+
mut self: Pin<&mut Self>,
221+
string: &[u8],
222+
timeout: Option<&Duration>,
223+
) -> Result<(), Error> {
208224
if self.stream.is_none() {
209225
return Err(From::from("Connection closed"));
210226
}
211227
let this = self.as_mut().project();
212228
let _: Pin<&mut Option<S>> = this.stream;
213229
let mut stream = this.stream.as_pin_mut().ok_or(Error::NoStream)?;
214230

215-
with_timeout(this.timeout.as_ref(), async move {
231+
with_timeout(timeout, async move {
216232
stream.write_all(string).await?;
217233
stream.flush().await?;
218234
Ok(())
@@ -227,15 +243,15 @@ impl<S: Connector + Write + Read + Unpin> InnerClient<S> {
227243
}
228244

229245
/// Read an SMTP response from the wire.
230-
pub async fn read_response(mut self: Pin<&mut Self>) -> SmtpResult {
246+
pub async fn read_response(mut self: Pin<&mut Self>, timeout: Option<&Duration>) -> SmtpResult {
231247
let this = self.as_mut().project();
232248
let stream = this.stream.as_pin_mut().ok_or(Error::NoStream)?;
233249

234250
let mut reader = BufReader::new(stream);
235251
let mut buffer = String::with_capacity(100);
236252

237253
loop {
238-
let read = with_timeout(this.timeout.as_ref(), reader.read_line(&mut buffer)).await?;
254+
let read = with_timeout(timeout, reader.read_line(&mut buffer)).await?;
239255
if read == 0 {
240256
break;
241257
}

src/smtp/smtp_client.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,8 @@ impl<'a> SmtpTransport {
306306
.await?;
307307

308308
client.set_timeout(self.client_info.timeout);
309-
let _response = client.read_response().await?;
309+
let timeout = client.timeout().cloned();
310+
let _response = client.read_response(timeout.as_ref()).await?;
310311
}
311312

312313
self.post_connect().await
@@ -498,6 +499,15 @@ impl<'a> Transport<'a> for SmtpTransport {
498499

499500
/// Sends an email
500501
async fn send(&mut self, email: SendableEmail) -> SmtpResult {
502+
let timeout = self.client.timeout().cloned();
503+
self.send_with_timeout(email, timeout.as_ref()).await
504+
}
505+
506+
async fn send_with_timeout(
507+
&mut self,
508+
email: SendableEmail,
509+
timeout: Option<&Duration>,
510+
) -> Self::Result {
501511
let message_id = email.message_id().to_string();
502512

503513
// Mail
@@ -516,10 +526,10 @@ impl<'a> Transport<'a> for SmtpTransport {
516526
try_smtp!(
517527
client
518528
.as_mut()
519-
.command(MailCommand::new(
520-
email.envelope().from().cloned(),
521-
mail_options,
522-
))
529+
.command_with_timeout(
530+
MailCommand::new(email.envelope().from().cloned(), mail_options),
531+
timeout
532+
)
523533
.await,
524534
self
525535
);
@@ -529,7 +539,7 @@ impl<'a> Transport<'a> for SmtpTransport {
529539
try_smtp!(
530540
client
531541
.as_mut()
532-
.command(RcptCommand::new(to_address.clone(), vec![]))
542+
.command_with_timeout(RcptCommand::new(to_address.clone(), vec![]), timeout)
533543
.await,
534544
self
535545
);

src/stub/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use log::info;
77

88
use crate::SendableEmail;
99
use crate::Transport;
10+
use std::time::Duration;
1011

1112
/// This transport logs the message envelope and returns the given response
1213
#[derive(Debug, Clone, Copy)]
@@ -45,4 +46,12 @@ impl<'a> Transport<'a> for StubTransport {
4546
);
4647
self.response
4748
}
49+
async fn send_with_timeout(
50+
&mut self,
51+
email: SendableEmail,
52+
timeout: Option<&Duration>,
53+
) -> Self::Result {
54+
info!("Timeout: {:?}", timeout);
55+
self.send(email).await
56+
}
4857
}

0 commit comments

Comments
 (0)