|
1 |
| -//! This crate lets you connect to and interact with servers that implement the IMAP protocol |
2 |
| -//! ([RFC 3501](https://tools.ietf.org/html/rfc3501) and various extensions). |
3 |
| -//! After authenticating with the server, IMAP lets you list, fetch, and search for e-mails, |
| 1 | +//! # Async IMAP |
| 2 | +//! |
| 3 | +//! This crate lets you connect to and interact with servers |
| 4 | +//! that implement the IMAP protocol ([RFC 3501](https://tools.ietf.org/html/rfc3501) and extensions). |
| 5 | +//! After authenticating with the server, |
| 6 | +//! IMAP lets you list, fetch, and search for e-mails, |
4 | 7 | //! as well as monitor mailboxes for changes.
|
5 | 8 | //!
|
6 |
| -//! To connect, use the [`connect`] function. This gives you an unauthenticated [`Client`]. You can |
7 |
| -//! then use [`Client::login`] or [`Client::authenticate`] to perform username/password or |
8 |
| -//! challenge/response authentication respectively. This in turn gives you an authenticated |
9 |
| -//! [`Session`], which lets you access the mailboxes at the server. |
| 9 | +//! ## Connecting |
10 | 10 | //!
|
11 |
| -//! The documentation within this crate borrows heavily from the various RFCs, |
12 |
| -//! but should not be considered a complete reference. |
13 |
| -//! If anything is unclear, |
14 |
| -//! follow the links to the RFCs embedded in the documentation |
15 |
| -//! for the various types and methods and read the raw text there! |
| 11 | +//! Connect to the server, for example using TLS connection on port 993 |
| 12 | +//! or plain TCP connection on port 143 if you plan to use STARTTLS. |
| 13 | +//! can be used. |
| 14 | +//! Pass the stream to [`Client::new()`]. |
| 15 | +//! This gives you an unauthenticated [`Client`]. |
16 | 16 | //!
|
17 |
| -//! Below is a basic client example. See the `examples/` directory for more. |
| 17 | +//! Then read the server greeting: |
| 18 | +//! ```ignore |
| 19 | +//! let _greeting = client |
| 20 | +//! .read_response().await? |
| 21 | +//! .expect("unexpected end of stream, expected greeting"); |
| 22 | +//! ``` |
18 | 23 | //!
|
19 |
| -//! ```no_run |
20 |
| -//! use futures::prelude::*; |
21 |
| -//! use async_imap::error::Result; |
| 24 | +//! ## STARTTLS |
22 | 25 | //!
|
23 |
| -//! #[cfg(feature = "async-native-tls")] |
24 |
| -//! async fn fetch_inbox_top() -> Result<Option<String>> { |
25 |
| -//! let domain = "imap.example.com"; |
26 |
| -//! let tls = async_native_tls::TlsConnector::new(); |
| 26 | +//! If you connected on a non-TLS port, upgrade the connection using STARTTLS: |
| 27 | +//! ```ignore |
| 28 | +//! client.run_command_and_check_ok("STARTTLS", None).await?; |
| 29 | +//! let stream = client.into_inner(); |
| 30 | +//! ``` |
| 31 | +//! Convert this stream into a TLS stream using a library |
| 32 | +//! such as [`async-native-tls`](https://crates.io/crates/async-native-tls) |
| 33 | +//! or [Rustls](`https://crates.io/crates/rustls`). |
| 34 | +//! Once you have a TLS stream, wrap it back into a [`Client`]: |
| 35 | +//! ```ignore |
| 36 | +//! let client = Client::new(tls_stream); |
| 37 | +//! ``` |
| 38 | +//! Note that there is no server greeting after STARTTLS. |
27 | 39 | //!
|
28 |
| -//! // we pass in the domain twice to check that the server's TLS |
29 |
| -//! // certificate is valid for the domain we're connecting to. |
30 |
| -//! let client = async_imap::connect((domain, 993), domain, tls).await?; |
| 40 | +//! ## Authentication and session usage |
31 | 41 | //!
|
32 |
| -//! // the client we have here is unauthenticated. |
33 |
| -//! // to do anything useful with the e-mails, we need to log in |
34 |
| -//! let mut imap_session = client |
35 |
| -//! .login("[email protected]", "password") |
36 |
| -//! .await |
37 |
| -//! .map_err(|e| e.0)?; |
| 42 | +//! Once you have an established connection, |
| 43 | +//! authenticate using [`Client::login`] or [`Client::authenticate`] |
| 44 | +//! to perform username/password or challenge/response authentication respectively. |
| 45 | +//! This in turn gives you an authenticated |
| 46 | +//! [`Session`], which lets you access the mailboxes at the server. |
| 47 | +//! For example: |
| 48 | +//! ```ignore |
| 49 | +//! let mut session = client |
| 50 | +//! .login("[email protected]", "password").await |
| 51 | +//! .map_err(|(err, _client)| err)?; |
| 52 | +//! session.select("INBOX").await?; |
38 | 53 | //!
|
39 |
| -//! // we want to fetch the first email in the INBOX mailbox |
40 |
| -//! imap_session.select("INBOX").await?; |
| 54 | +//! // Fetch message number 1 in this mailbox, along with its RFC 822 field. |
| 55 | +//! // RFC 822 dictates the format of the body of e-mails. |
| 56 | +//! let messages_stream = imap_session.fetch("1", "RFC822").await?; |
| 57 | +//! let messages: Vec<_> = messages_stream.try_collect().await?; |
| 58 | +//! let message = messages.first().expect("found no messages in the INBOX"); |
41 | 59 | //!
|
42 |
| -//! // fetch message number 1 in this mailbox, along with its RFC822 field. |
43 |
| -//! // RFC 822 dictates the format of the body of e-mails |
44 |
| -//! let messages_stream = imap_session.fetch("1", "RFC822").await?; |
45 |
| -//! let messages: Vec<_> = messages_stream.try_collect().await?; |
46 |
| -//! let message = if let Some(m) = messages.first() { |
47 |
| -//! m |
48 |
| -//! } else { |
49 |
| -//! return Ok(None); |
50 |
| -//! }; |
| 60 | +//! // Extract the message body. |
| 61 | +//! let body = message.body().expect("message did not have a body!"); |
| 62 | +//! let body = std::str::from_utf8(body) |
| 63 | +//! .expect("message was not valid utf-8") |
| 64 | +//! .to_string(); |
51 | 65 | //!
|
52 |
| -//! // extract the message's body |
53 |
| -//! let body = message.body().expect("message did not have a body!"); |
54 |
| -//! let body = std::str::from_utf8(body) |
55 |
| -//! .expect("message was not valid utf-8") |
56 |
| -//! .to_string(); |
| 66 | +//! session.logout().await?; |
| 67 | +//! ``` |
57 | 68 | //!
|
58 |
| -//! // be nice to the server and log out |
59 |
| -//! imap_session.logout().await?; |
| 69 | +//! The documentation within this crate borrows heavily from the various RFCs, |
| 70 | +//! but should not be considered a complete reference. |
| 71 | +//! If anything is unclear, |
| 72 | +//! follow the links to the RFCs embedded in the documentation |
| 73 | +//! for the various types and methods and read the raw text there! |
60 | 74 | //!
|
61 |
| -//! Ok(Some(body)) |
62 |
| -//! } |
63 |
| -//! ``` |
| 75 | +//! See the `examples/` directory for usage examples. |
64 | 76 | #![warn(missing_docs)]
|
65 | 77 | #![deny(rust_2018_idioms, unsafe_code)]
|
66 | 78 |
|
|
0 commit comments