Skip to content

Commit 247b403

Browse files
committed
Upgrade to using async/await
1 parent 7c6c8d6 commit 247b403

File tree

4 files changed

+182
-174
lines changed

4 files changed

+182
-174
lines changed

tokio-imap/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ maintenance = { status = "passively-maintained" }
1818

1919
[dependencies]
2020
bytes = "0.4"
21-
futures = "0.1"
22-
futures-state-stream = "0.1"
21+
futures = { version = "0.3.0-alpha.19", package = "futures-preview" }
2322
imap-proto = { version = "0.9", path = "../imap-proto" }
2423
native-tls = "0.2"
2524
nom = "5"
26-
tokio = "0.1"
27-
tokio-tls = "0.2"
25+
rustls = "0.16.0"
26+
tokio = "0.2.0-alpha.6"
27+
tokio-rustls = "0.12.0-alpha.4"
28+
webpki-roots = "0.18.0"

tokio-imap/examples/basic.rs

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ use std::error::Error;
22
use std::fmt::{self, Display, Formatter};
33
use std::io;
44

5-
use futures::future::Future;
6-
use futures_state_stream::StateStream;
75
use tokio::runtime::current_thread;
86

97
use tokio_imap::client::builder::{
@@ -20,50 +18,72 @@ fn main() {
2018
let login = args.next().expect("no login provided");
2119
let password = args.next().expect("no password provided");
2220
let mailbox = args.next().expect("no mailbox provided");
23-
if let Err(cause) = imap_fetch(&server, login, password, mailbox) {
24-
eprintln!("Fatal error: {}", cause);
25-
};
21+
22+
let mut rt = current_thread::Runtime::new().unwrap();
23+
rt.block_on(async move {
24+
if let Err(cause) = imap_fetch(&server, login, password, mailbox).await {
25+
eprintln!("Fatal error: {}", cause);
26+
}
27+
});
2628
}
2729

28-
fn imap_fetch(
30+
async fn imap_fetch(
2931
server: &str,
3032
login: String,
3133
password: String,
3234
mailbox: String,
3335
) -> Result<(), ImapError> {
3436
eprintln!("Will connect to {}", server);
35-
let fut_connect = TlsClient::connect(server).map_err(|cause| ImapError::Connect { cause })?;
36-
let fut_responses = fut_connect
37-
.and_then(move |(_, tls_client)| {
38-
tls_client
39-
.call(CommandBuilder::login(&login, &password))
40-
.collect()
41-
})
42-
.and_then(move |(_, tls_client)| {
43-
tls_client.call(CommandBuilder::select(&mailbox)).collect()
44-
})
45-
.and_then(move |(_, tls_client)| {
46-
let cmd = CommandBuilder::uid_fetch()
47-
.all_after(1_u32)
48-
.attr(Attribute::Uid)
49-
.attr(Attribute::Rfc822);
50-
tls_client.call(cmd.build()).for_each(move |response_data| {
51-
process_email(&response_data);
52-
Ok(())
53-
})
54-
})
55-
.and_then(move |tls_client| tls_client.call(CommandBuilder::close()).collect())
56-
.and_then(|_| Ok(()))
57-
.map_err(|e| ImapError::UidFetch { cause: e });
58-
let res = current_thread::block_on_all({
59-
eprintln!("Fetching messages...");
60-
fut_responses
61-
});
37+
let (_, mut tls_client) = TlsClient::connect(server)
38+
.await
39+
.map_err(|e| ImapError::Connect { cause: e })?;
40+
41+
let responses = tls_client
42+
.call(CommandBuilder::login(&login, &password))
43+
.try_collect()
44+
.await
45+
.map_err(|e| ImapError::Login { cause: e })?;
46+
47+
match responses[0].parsed() {
48+
Response::Capabilities(_) => {}
49+
Response::Done { information, .. } => {
50+
if let Some(info) = information {
51+
eprintln!("Login failed: {:?}", info);
52+
}
53+
return Err(ImapError::Login {
54+
cause: io::Error::new(io::ErrorKind::Other, "login failed"),
55+
});
56+
}
57+
_ => unimplemented!(),
58+
}
59+
60+
let _ = tls_client
61+
.call(CommandBuilder::select(&mailbox))
62+
.try_collect()
63+
.await
64+
.map_err(|e| ImapError::Select { cause: e })?;
65+
66+
let cmd = CommandBuilder::uid_fetch()
67+
.all_after(1_u32)
68+
.attr(Attribute::Uid)
69+
.attr(Attribute::Rfc822);
70+
let _ = tls_client
71+
.call(cmd.build())
72+
.try_for_each(move |response_data| process_email(response_data))
73+
.await
74+
.map_err(|e| ImapError::UidFetch { cause: e })?;
75+
76+
let _ = tls_client
77+
.call(CommandBuilder::close())
78+
.try_collect()
79+
.await
80+
.map_err(|e| ImapError::Close { cause: e })?;
81+
6282
eprintln!("Finished fetching messages");
63-
res
83+
Ok(())
6484
}
6585

66-
fn process_email(response_data: &ResponseData) {
86+
async fn process_email(response_data: ResponseData) -> Result<(), io::Error> {
6787
if let Response::Fetch(_, ref attr_vals) = *response_data.parsed() {
6888
for val in attr_vals.iter() {
6989
match *val {
@@ -77,6 +97,7 @@ fn process_email(response_data: &ResponseData) {
7797
}
7898
}
7999
}
100+
Ok(())
80101
}
81102

82103
#[derive(Debug)]
@@ -85,6 +106,7 @@ pub enum ImapError {
85106
Login { cause: io::Error },
86107
Select { cause: io::Error },
87108
UidFetch { cause: io::Error },
109+
Close { cause: io::Error },
88110
}
89111

90112
impl Error for ImapError {
@@ -97,7 +119,8 @@ impl Error for ImapError {
97119
ImapError::Connect { ref cause }
98120
| ImapError::Login { ref cause }
99121
| ImapError::Select { ref cause }
100-
| ImapError::UidFetch { ref cause } => Some(cause),
122+
| ImapError::UidFetch { ref cause }
123+
| ImapError::Close { ref cause } => Some(cause),
101124
}
102125
}
103126
}
@@ -109,6 +132,7 @@ impl Display for ImapError {
109132
ImapError::Login { ref cause } => write!(f, "Login failed: {}", cause),
110133
ImapError::Select { ref cause } => write!(f, "Mailbox selection failed: {}", cause),
111134
ImapError::UidFetch { ref cause } => write!(f, "Fetching messages failed: {}", cause),
135+
ImapError::Close { ref cause } => write!(f, "Closing failed: {}", cause),
112136
}
113137
}
114138
}

0 commit comments

Comments
 (0)