-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
1,106 additions
and
486 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
[package] | ||
|
||
name = "imap" | ||
version = "0.8.1" | ||
version = "0.9.0" | ||
authors = ["Matt McCoy <[email protected]>", | ||
"Jon Gjengset <[email protected]>"] | ||
documentation = "https://docs.rs/imap/" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,54 +10,57 @@ | |
[![Build Status](https://ci.appveyor.com/api/projects/status/github/mattnenterprise/rust-imap?svg=true)](https://ci.appveyor.com/api/projects/status/github/mattnenterprise/rust-imap) | ||
[![Coverage Status](https://coveralls.io/repos/github/mattnenterprise/rust-imap/badge.svg?branch=master)](https://coveralls.io/github/mattnenterprise/rust-imap?branch=master) | ||
|
||
IMAP client bindings for Rust. | ||
This crate lets you connect to and interact with servers that implement the IMAP protocol ([RFC | ||
3501](https://tools.ietf.org/html/rfc3501)). After authenticating with the server, IMAP lets | ||
you list, fetch, and search for e-mails, as well as monitor mailboxes for changes. | ||
|
||
## Usage | ||
To connect, use the `imap::connect` function. This gives you an unauthenticated `imap::Client`. You can | ||
then use `Client::login` or `Client::authenticate` to perform username/password or | ||
challenge/response authentication respectively. This in turn gives you an authenticated | ||
`Session`, which lets you access the mailboxes at the server. | ||
|
||
Here is a basic example of using the client. | ||
See the `examples/` directory for more examples. | ||
Below is a basic client example. See the `examples/` directory for more. | ||
|
||
```rust | ||
extern crate imap; | ||
extern crate native_tls; | ||
|
||
// To connect to the gmail IMAP server with this you will need to allow unsecure apps access. | ||
// See: https://support.google.com/accounts/answer/6010255?hl=en | ||
// Look at the `examples/gmail_oauth2.rs` for how to connect to gmail securely. | ||
fn main() { | ||
let domain = "imap.gmail.com"; | ||
let port = 993; | ||
let socket_addr = (domain, port); | ||
let ssl_connector = native_tls::TlsConnector::builder().build().unwrap(); | ||
let mut imap_socket = Client::secure_connect(socket_addr, domain, &ssl_connector).unwrap(); | ||
|
||
imap_socket.login("username", "password").unwrap(); | ||
|
||
match imap_socket.capabilities() { | ||
Ok(capabilities) => { | ||
for capability in capabilities.iter() { | ||
println!("{}", capability); | ||
} | ||
} | ||
Err(e) => println!("Error parsing capabilities: {}", e), | ||
fn fetch_inbox_top() -> imap::error::Result<Option<String>> { | ||
let domain = "imap.example.com"; | ||
let tls = native_tls::TlsConnector::builder().build().unwrap(); | ||
|
||
// we pass in the domain twice to check that the server's TLS | ||
// certificate is valid for the domain we're connecting to. | ||
let client = imap::connect((domain, 993), domain, &tls).unwrap(); | ||
|
||
// the client we have here is unauthenticated. | ||
// to do anything useful with the e-mails, we need to log in | ||
let mut imap_session = client | ||
.login("[email protected]", "password") | ||
.map_err(|e| e.0)?; | ||
|
||
// we want to fetch the first email in the INBOX mailbox | ||
imap_session.select("INBOX")?; | ||
|
||
// fetch message number 1 in this mailbox, along with its RFC822 field. | ||
// RFC 822 dictates the format of the body of e-mails | ||
let messages = imap_session.fetch("1", "RFC822")?; | ||
let message = if let Some(m) = messages.iter().next() { | ||
m | ||
} else { | ||
return Ok(None); | ||
}; | ||
|
||
match imap_socket.select("INBOX") { | ||
Ok(mailbox) => { | ||
println!("{}", mailbox); | ||
} | ||
Err(e) => println!("Error selecting INBOX: {}", e), | ||
}; | ||
// extract the message's body | ||
let body = message.rfc822().expect("message did not have a body!"); | ||
let body = std::str::from_utf8(body) | ||
.expect("message was not valid utf-8") | ||
.to_string(); | ||
|
||
match imap_socket.fetch("2", "body[text]") { | ||
Ok(messages) => { | ||
for message in messages.iter() { | ||
print!("{:?}", message); | ||
} | ||
} | ||
Err(e) => println!("Error Fetching email 2: {}", e), | ||
}; | ||
// be nice to the server and log out | ||
imap_session.logout()?; | ||
|
||
imap_socket.logout().unwrap(); | ||
Ok(Some(body)) | ||
} | ||
``` | ||
|
||
|
@@ -71,5 +74,5 @@ at your option. | |
## Contribution | ||
|
||
Unless you explicitly state otherwise, any contribution intentionally submitted | ||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any | ||
additional terms or conditions. | ||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall | ||
be dual licensed as above, without any additional terms or conditions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,47 @@ | ||
extern crate imap; | ||
extern crate native_tls; | ||
|
||
use native_tls::TlsConnector; | ||
|
||
// To connect to the gmail IMAP server with this you will need to allow unsecure apps access. | ||
// See: https://support.google.com/accounts/answer/6010255?hl=en | ||
// Look at the gmail_oauth2.rs example on how to connect to a gmail server securely. | ||
fn main() { | ||
let domain = "imap.gmail.com"; | ||
let port = 993; | ||
let socket_addr = (domain, port); | ||
let ssl_connector = TlsConnector::builder().build().unwrap(); | ||
let client = imap::client::secure_connect(socket_addr, domain, &ssl_connector).unwrap(); | ||
|
||
let mut imap_session = match client.login("username", "password") { | ||
Ok(c) => c, | ||
Err((e, _unauth_client)) => { | ||
eprintln!("failed to login: {}", e); | ||
return; | ||
} | ||
}; | ||
// To connect to the gmail IMAP server with this you will need to allow unsecure apps access. | ||
// See: https://support.google.com/accounts/answer/6010255?hl=en | ||
// Look at the gmail_oauth2.rs example on how to connect to a gmail server securely. | ||
fetch_inbox_top().unwrap(); | ||
} | ||
|
||
match imap_session.capabilities() { | ||
Ok(capabilities) => for capability in capabilities.iter() { | ||
println!("{}", capability); | ||
}, | ||
Err(e) => println!("Error parsing capability: {}", e), | ||
}; | ||
fn fetch_inbox_top() -> imap::error::Result<Option<String>> { | ||
let domain = "imap.example.com"; | ||
let tls = native_tls::TlsConnector::builder().build().unwrap(); | ||
|
||
match imap_session.select("INBOX") { | ||
Ok(mailbox) => { | ||
println!("{}", mailbox); | ||
} | ||
Err(e) => println!("Error selecting INBOX: {}", e), | ||
}; | ||
// we pass in the domain twice to check that the server's TLS | ||
// certificate is valid for the domain we're connecting to. | ||
let client = imap::connect((domain, 993), domain, &tls).unwrap(); | ||
|
||
match imap_session.fetch("2", "body[text]") { | ||
Ok(msgs) => for msg in &msgs { | ||
print!("{:?}", msg); | ||
}, | ||
Err(e) => println!("Error Fetching email 2: {}", e), | ||
// the client we have here is unauthenticated. | ||
// to do anything useful with the e-mails, we need to log in | ||
let mut imap_session = client | ||
.login("[email protected]", "password") | ||
.map_err(|e| e.0)?; | ||
|
||
// we want to fetch the first email in the INBOX mailbox | ||
imap_session.select("INBOX")?; | ||
|
||
// fetch message number 1 in this mailbox, along with its RFC822 field. | ||
// RFC 822 dictates the format of the body of e-mails | ||
let messages = imap_session.fetch("1", "RFC822")?; | ||
let message = if let Some(m) = messages.iter().next() { | ||
m | ||
} else { | ||
return Ok(None); | ||
}; | ||
|
||
imap_session.logout().unwrap(); | ||
// extract the message's body | ||
let body = message.rfc822().expect("message did not have a body!"); | ||
let body = std::str::from_utf8(body) | ||
.expect("message was not valid utf-8") | ||
.to_string(); | ||
|
||
// be nice to the server and log out | ||
imap_session.logout()?; | ||
|
||
Ok(Some(body)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,10 @@ | ||
/// This will allow plugable authentication mechanisms. | ||
/// | ||
/// This trait is used by `Client::authenticate` to [authenticate | ||
/// using SASL](https://tools.ietf.org/html/rfc3501#section-6.2.2). | ||
/// This trait allows for pluggable authentication schemes. It is used by `Client::authenticate` to | ||
/// [authenticate using SASL](https://tools.ietf.org/html/rfc3501#section-6.2.2). | ||
pub trait Authenticator { | ||
/// Type of the response to the challenge. This will usually be a | ||
/// `Vec<u8>` or `String`. It must not be Base64 encoded: the | ||
/// library will do it. | ||
/// The type of the response to the challenge. This will usually be a `Vec<u8>` or `String`. | ||
type Response: AsRef<[u8]>; | ||
/// For each server challenge is passed to `process`. The library | ||
/// has already decoded the Base64 string into bytes. | ||
/// | ||
/// The `process` function should return its response, not Base64 | ||
/// encoded: the library will do it. | ||
fn process(&self, &[u8]) -> Self::Response; | ||
|
||
/// Each base64-decoded server challenge is passed to `process`. | ||
/// The returned byte-string is base64-encoded and then sent back to the server. | ||
fn process(&self, challenge: &[u8]) -> Self::Response; | ||
} |
Oops, something went wrong.