Skip to content

Commit 3a7d108

Browse files
full tokio support
1 parent 2b5b5ad commit 3a7d108

File tree

17 files changed

+660
-592
lines changed

17 files changed

+660
-592
lines changed

Cargo.toml

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ is-it-maintained-issue-resolution = { repository = "async-email/async-imap" }
1919
is-it-maintained-open-issues = { repository = "async-email/async-imap" }
2020

2121
[features]
22-
default = []
22+
default = ["runtime-async-std"]
23+
24+
runtime-async-std = ["async-std", "async-native-tls/runtime-async-std"]
25+
runtime-tokio = ["tokio", "async-native-tls/runtime-tokio"]
2326

2427
[dependencies]
2528
imap-proto = "0.16.1"
2629
nom = "7.0"
2730
base64 = "0.13"
2831
chrono = "0.4"
29-
async-native-tls = { version = "0.3" }
30-
async-std = { version = "1.8.0", default-features = false, features = ["std"] }
3132
pin-utils = "0.1.0-alpha.4"
3233
futures = "0.3.15"
3334
ouroboros = "0.15"
@@ -36,30 +37,15 @@ byte-pool = "0.2.2"
3637
once_cell = "1.8.0"
3738
log = "0.4.8"
3839
thiserror = "1.0.9"
40+
async-channel = "1.6.1"
3941

40-
[dev-dependencies]
41-
lettre_email = "0.9"
42-
pretty_assertions = "1.2"
43-
async-smtp = { version = "0.4" }
44-
async-std = { version = "1.8.0", default-features = false, features = ["std", "attributes"] }
45-
tokio = { version = "1", features = ["rt-multi-thread"] }
46-
47-
[[example]]
48-
name = "basic"
49-
required-features = ["default"]
42+
async-native-tls = { version = "0.4", default-features = false }
43+
async-std = { version = "1.8.0", default-features = false, features = ["std"], optional = true }
44+
tokio = { version = "1", features = ["net", "sync", "time"], optional = true }
5045

51-
[[example]]
52-
name = "gmail_oauth2"
53-
required-features = ["default"]
5446

55-
[[example]]
56-
name = "futures"
57-
required-features = ["default"]
58-
59-
[[example]]
60-
name = "tokio"
61-
required-features = ["default"]
47+
[dev-dependencies]
48+
pretty_assertions = "1.2"
49+
async-std = { version = "1.8.0", features = ["std", "attributes"] }
50+
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
6251

63-
[[test]]
64-
name = "imap_integration"
65-
required-features = ["default"]

examples/Cargo.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "async-imap-examples"
3+
version = "0.1.0"
4+
publish = false
5+
authors = ["dignifiedquire <[email protected]>"]
6+
license = "Apache-2.0/MIT"
7+
edition = "2018"
8+
9+
[features]
10+
default = ["runtime-async-std"]
11+
12+
runtime-async-std = ["async-std", "async-native-tls/runtime-async-std", "async-smtp/runtime-async-std", "async-imap/runtime-async-std"]
13+
runtime-tokio = ["tokio", "async-native-tls/runtime-tokio", "async-smtp/runtime-tokio", "async-imap/runtime-tokio"]
14+
15+
[dependencies]
16+
async-imap = { path = "../", default-features = false }
17+
async-native-tls = { version = "0.4", default-features = false }
18+
async-smtp = { version = "0.4", default-features = false, features = ["smtp-transport"] }
19+
20+
async-std = { version = "1.8.0", features = ["std", "attributes"], optional = true }
21+
futures = "0.3.21"
22+
tokio = { version = "1", features = ["rt-multi-thread", "macros"], optional = true }
23+
24+
[patch.crates-io]
25+
async-smtp = { git = "https://github.com/async-email/async-smtp", branch = "tokio" }

examples/gmail_oauth2.rs

Lines changed: 0 additions & 63 deletions
This file was deleted.

examples/basic.rs renamed to examples/src/bin/basic.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
use async_imap::error::{Error, Result};
2-
use async_std::prelude::*;
3-
use async_std::task;
41
use std::env;
52

6-
fn main() -> Result<()> {
7-
task::block_on(async {
8-
let args: Vec<String> = env::args().collect();
9-
if args.len() != 4 {
10-
eprintln!("need three arguments: imap-server login password");
11-
Err(Error::Bad("need three arguments".into()))
12-
} else {
13-
let res = fetch_inbox_top(&args[1], &args[2], &args[3]).await?;
14-
println!("**result:\n{}", res.unwrap());
15-
Ok(())
16-
}
17-
})
3+
use async_imap::error::{Error, Result};
4+
use futures::TryStreamExt;
5+
6+
#[cfg_attr(feature = "runtime-tokio", tokio::main)]
7+
#[cfg_attr(feature = "runtime-async-std", async_std::main)]
8+
async fn main() -> Result<()> {
9+
let args: Vec<String> = env::args().collect();
10+
if args.len() != 4 {
11+
eprintln!("need three arguments: imap-server login password");
12+
Err(Error::Bad("need three arguments".into()))
13+
} else {
14+
let res = fetch_inbox_top(&args[1], &args[2], &args[3]).await?;
15+
println!("**result:\n{}", res.unwrap());
16+
Ok(())
17+
}
1818
}
1919

2020
async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Result<Option<String>> {
@@ -38,7 +38,7 @@ async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Resu
3838
// fetch message number 1 in this mailbox, along with its RFC822 field.
3939
// RFC 822 dictates the format of the body of e-mails
4040
let messages_stream = imap_session.fetch("1", "RFC822").await?;
41-
let messages: Vec<_> = messages_stream.collect::<Result<_>>().await?;
41+
let messages: Vec<_> = messages_stream.try_collect().await?;
4242
let message = if let Some(m) = messages.first() {
4343
m
4444
} else {

examples/futures.rs renamed to examples/src/bin/futures.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use async_imap::error::{Error, Result};
2-
use async_std::prelude::*;
31
use std::env;
42

3+
use async_imap::error::{Error, Result};
4+
use futures::TryStreamExt;
5+
56
fn main() -> Result<()> {
67
futures::executor::block_on(async {
78
let args: Vec<String> = env::args().collect();
@@ -36,7 +37,7 @@ async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Resu
3637
// fetch message number 1 in this mailbox, along with its RFC822 field.
3738
// RFC 822 dictates the format of the body of e-mails
3839
let messages_stream = imap_session.fetch("1", "RFC822").await?;
39-
let messages: Vec<_> = messages_stream.collect::<Result<_>>().await?;
40+
let messages: Vec<_> = messages_stream.try_collect().await?;
4041
let message = if let Some(m) = messages.first() {
4142
m
4243
} else {

examples/src/bin/gmail_oauth2.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use async_imap::error::Result;
2+
use futures::StreamExt;
3+
4+
struct GmailOAuth2 {
5+
user: String,
6+
access_token: String,
7+
}
8+
9+
impl async_imap::Authenticator for &GmailOAuth2 {
10+
type Response = String;
11+
12+
fn process(&mut self, _data: &[u8]) -> Self::Response {
13+
format!(
14+
"user={}\x01auth=Bearer {}\x01\x01",
15+
self.user, self.access_token
16+
)
17+
}
18+
}
19+
20+
#[cfg_attr(feature = "runtime-tokio", tokio::main)]
21+
#[cfg_attr(feature = "runtime-async-std", async_std::main)]
22+
async fn main() -> Result<()> {
23+
let gmail_auth = GmailOAuth2 {
24+
user: String::from("[email protected]"),
25+
access_token: String::from("<access_token>"),
26+
};
27+
let domain = "imap.gmail.com";
28+
let port = 993;
29+
let socket_addr = (domain, port);
30+
let tls = async_native_tls::TlsConnector::new();
31+
let client = async_imap::connect(socket_addr, domain, tls).await?;
32+
33+
let mut imap_session = match client.authenticate("XOAUTH2", &gmail_auth).await {
34+
Ok(c) => c,
35+
Err((e, _unauth_client)) => {
36+
println!("error authenticating: {}", e);
37+
return Err(e);
38+
}
39+
};
40+
41+
match imap_session.select("INBOX").await {
42+
Ok(mailbox) => println!("{}", mailbox),
43+
Err(e) => println!("Error selecting INBOX: {}", e),
44+
};
45+
46+
{
47+
let mut msgs = imap_session.fetch("2", "body[text]").await.map_err(|e| {
48+
eprintln!("Error Fetching email 2: {}", e);
49+
e
50+
})?;
51+
52+
// TODO: get rid of this
53+
let mut msgs = unsafe { std::pin::Pin::new_unchecked(&mut msgs) };
54+
55+
while let Some(msg) = msgs.next().await {
56+
print!("{:?}", msg?);
57+
}
58+
}
59+
60+
imap_session.logout().await?;
61+
Ok(())
62+
}

examples/idle.rs renamed to examples/src/bin/idle.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
use async_imap::error::{Error, Result};
2-
use async_std::prelude::*;
3-
// use async_std::io;
4-
use async_imap::extensions::idle::IdleResponse::*;
5-
use async_std::task;
61
use std::env;
72
use std::time::Duration;
83

9-
fn main() -> Result<()> {
10-
task::block_on(async {
11-
let args: Vec<String> = env::args().collect();
12-
if args.len() != 4 {
13-
eprintln!("need three arguments: imap-server login password");
14-
Err(Error::Bad("need three arguments".into()))
15-
} else {
16-
fetch_and_idle(&args[1], &args[2], &args[3]).await?;
17-
Ok(())
18-
}
19-
})
4+
use async_imap::error::{Error, Result};
5+
use async_imap::extensions::idle::IdleResponse::*;
6+
use futures::StreamExt;
7+
8+
#[cfg(feature = "runtime-async-std")]
9+
use async_std::{task, task::sleep};
10+
11+
#[cfg(feature = "runtime-tokio")]
12+
use tokio::{task, time::sleep};
13+
14+
#[cfg_attr(feature = "runtime-tokio", tokio::main)]
15+
#[cfg_attr(feature = "runtime-async-std", async_std::main)]
16+
async fn main() -> Result<()> {
17+
let args: Vec<String> = env::args().collect();
18+
if args.len() != 4 {
19+
eprintln!("need three arguments: imap-server login password");
20+
Err(Error::Bad("need three arguments".into()))
21+
} else {
22+
fetch_and_idle(&args[1], &args[2], &args[3]).await?;
23+
Ok(())
24+
}
2025
}
2126

2227
async fn fetch_and_idle(imap_server: &str, login: &str, password: &str) -> Result<()> {
@@ -59,7 +64,7 @@ async fn fetch_and_idle(imap_server: &str, login: &str, password: &str) -> Resul
5964

6065
task::spawn(async move {
6166
println!("-- thread: waiting for 30s");
62-
task::sleep(Duration::from_secs(30)).await;
67+
sleep(Duration::from_secs(30)).await;
6368
println!("-- thread: waited 30 secs, now interrupting idle");
6469
drop(interrupt);
6570
});

0 commit comments

Comments
 (0)