Skip to content

Commit 60ed0ff

Browse files
Merge pull request #21 from async-email/runtimes
feat: runtime independent examples
2 parents d07ea40 + e282e7e commit 60ed0ff

File tree

19 files changed

+744
-623
lines changed

19 files changed

+744
-623
lines changed

Cargo.toml

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,33 @@ 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]
25-
imap-proto = "0.14.3"
26-
nom = "6.0"
28+
imap-proto = "0.16.1"
29+
nom = "7.0"
2730
base64 = "0.13"
2831
chrono = "0.4"
29-
async-native-tls = { version = "0.3.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"
33-
ouroboros = "0.9"
34+
ouroboros = "0.15"
3435
stop-token = "0.7"
3536
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"
41+
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 }
45+
3946

4047
[dev-dependencies]
41-
lettre_email = "0.9"
42-
pretty_assertions = "0.6.1"
43-
async-smtp = { version = "0.3.0" }
44-
async-std = { version = "1.8.0", default-features = false, features = ["std", "attributes"] }
45-
46-
[[example]]
47-
name = "basic"
48-
required-features = ["default"]
49-
50-
[[example]]
51-
name = "gmail_oauth2"
52-
required-features = ["default"]
53-
54-
[[test]]
55-
name = "imap_integration"
56-
required-features = ["default"]
48+
pretty_assertions = "1.2"
49+
async-std = { version = "1.8.0", features = ["std", "attributes"] }
50+
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
51+

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/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ Examples:
77
* basic - This is a very basic example of using the client.
88

99
* idle - This is a basic example of how to perform an IMAP IDLE call
10-
and interrupt it based on typing a line into stdin.
10+
and interrupt it based on typing a line into stdin.
1111

1212
* gmail_oauth2 - This is an example using oauth2 for logging into
13-
gmail via the OAUTH2 mechanism.
13+
gmail via the OAUTH2 mechanism.
14+
15+
* futures - The basic example, but using the `futures` executor.

examples/gmail_oauth2.rs

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

examples/src/bin/basic.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use std::env;
2+
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+
}
18+
}
19+
20+
async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Result<Option<String>> {
21+
let tls = async_native_tls::TlsConnector::new();
22+
let imap_addr = (imap_server, 993);
23+
24+
// we pass in the imap_server twice to check that the server's TLS
25+
// certificate is valid for the imap_server we're connecting to.
26+
let client = async_imap::connect(imap_addr, imap_server, tls).await?;
27+
println!("-- connected to {}:{}", imap_addr.0, imap_addr.1);
28+
29+
// the client we have here is unauthenticated.
30+
// to do anything useful with the e-mails, we need to log in
31+
let mut imap_session = client.login(login, password).await.map_err(|e| e.0)?;
32+
println!("-- logged in a {}", login);
33+
34+
// we want to fetch the first email in the INBOX mailbox
35+
imap_session.select("INBOX").await?;
36+
println!("-- INBOX selected");
37+
38+
// fetch message number 1 in this mailbox, along with its RFC822 field.
39+
// RFC 822 dictates the format of the body of e-mails
40+
let messages_stream = imap_session.fetch("1", "RFC822").await?;
41+
let messages: Vec<_> = messages_stream.try_collect().await?;
42+
let message = if let Some(m) = messages.first() {
43+
m
44+
} else {
45+
return Ok(None);
46+
};
47+
48+
// extract the message's body
49+
let body = message.body().expect("message did not have a body!");
50+
let body = std::str::from_utf8(body)
51+
.expect("message was not valid utf-8")
52+
.to_string();
53+
println!("-- 1 message received, logging out");
54+
55+
// be nice to the server and log out
56+
imap_session.logout().await?;
57+
58+
Ok(Some(body))
59+
}

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

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

3+
use async_imap::error::{Error, Result};
4+
use futures::TryStreamExt;
5+
66
fn main() -> Result<()> {
7-
task::block_on(async {
7+
futures::executor::block_on(async {
88
let args: Vec<String> = env::args().collect();
99
if args.len() != 4 {
1010
eprintln!("need three arguments: imap-server login password");
@@ -19,12 +19,11 @@ fn main() -> Result<()> {
1919

2020
async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Result<Option<String>> {
2121
let tls = async_native_tls::TlsConnector::new();
22-
let imap_addr = (imap_server, 993);
2322

2423
// we pass in the imap_server twice to check that the server's TLS
2524
// certificate is valid for the imap_server we're connecting to.
26-
let client = async_imap::connect(imap_addr, imap_server, tls).await?;
27-
println!("-- connected to {}:{}", imap_addr.0, imap_addr.1);
25+
let client = async_imap::connect((imap_server, 993), imap_server, tls).await?;
26+
println!("-- connected to {}:{}", imap_server, 993);
2827

2928
// the client we have here is unauthenticated.
3029
// to do anything useful with the e-mails, we need to log in
@@ -38,7 +37,7 @@ async fn fetch_inbox_top(imap_server: &str, login: &str, password: &str) -> Resu
3837
// fetch message number 1 in this mailbox, along with its RFC822 field.
3938
// RFC 822 dictates the format of the body of e-mails
4039
let messages_stream = imap_session.fetch("1", "RFC822").await?;
41-
let messages: Vec<_> = messages_stream.collect::<Result<_>>().await?;
40+
let messages: Vec<_> = messages_stream.try_collect().await?;
4241
let message = if let Some(m) = messages.first() {
4342
m
4443
} else {

examples/src/bin/gmail_oauth2.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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+
while let Some(msg) = msgs.next().await {
53+
print!("{:?}", msg?);
54+
}
55+
}
56+
57+
imap_session.logout().await?;
58+
Ok(())
59+
}

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)