In messing with some IMAP rust examples, I'm running into a problem.
I have what appears to be two identical lines of code:
let body = message.body().expect("message did not have a body!");
appears twice in the program. When it is inside the fetch_inbox_top function it has no problem. But inside the main function I get an error about the body method:
|
| let body = message.body().expect("message did not have a body!");
| ^^^^ method not found in `&Fetches`
It finds the body method fine when called within fetch_inbox_top .... any idea why?
Full code:
extern crate imap;
use imap::types::UnsolicitedResponse;
mod mine;
struct Opt{
server: String,
port: u16,
username: String,
password: String,
mailbox: String,
}
fn main() {
let opt = Opt{
server: String::from("imap.mail.us-west-2.awsapps.com"),
port: 993,
username: String::from("removed"),
password: String::from("removed"),
mailbox: String::from("INBOX"),
};
let client = imap::ClientBuilder::new(opt.server.clone(), opt.port.clone())
.native_tls()
.expect("Could not connect to imap server");
let mut imap = client
.login(opt.username.clone(), opt.password.clone())
.expect("Could not authenticate");
imap.debug = true;
imap.select(&opt.mailbox).expect("Could not select mailbox");
let mut num_responses = 0;
let max_responses = 0;
fetch_inbox_top(&opt).unwrap();
let idle_result = imap.idle().wait_while(|response| {
num_responses += 1;
println!("IDLE response #{}: {:?}", num_responses, response);
(|| {
match response {
UnsolicitedResponse::Exists(num) => {
let messages = imap.fetch("1", "RFC822");
let message = if let Some(m) = messages.iter().next() {
m
} else {
return;
};
// extract the message's body
let body = message.body().expect("message did not have a body!");
let body = std::str::from_utf8(body)
.expect("message was not valid utf-8")
.to_string();
println!("{}", body);
},
_ => {
println!("unhandled {:?}", response);
}
}
})();
if max_responses != 0 && num_responses >= max_responses {
// Stop IDLE
false
} else {
// Continue IDLE
true
}
});
match idle_result {
Ok(reason) => println!("IDLE finished normally {:?}", reason),
Err(e) => println!("IDLE finished with error {:?}", e),
}
imap.logout().expect("Could not log out");
}
fn fetch_inbox_top(opt: &Opt) -> imap::error::Result<Option<String>> {
let client = imap::ClientBuilder::new(opt.server.clone(), opt.port.clone())
.native_tls()
.expect("Could not connect to imap server");
let mut imap_session = client
.login(opt.username.clone(), opt.password.clone())
.expect("Could not authenticate");
// 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);
};
// extract the message's body
let body = message.body().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))
}
Code for body:
/// The bytes that make up this message, included if `BODY[]` or `RFC822` was included in the
/// `query` argument to `FETCH`. The bytes SHOULD be interpreted by the client according to the
/// content transfer encoding, body type, and subtype.
pub fn body(&self) -> Option<&[u8]> {
self.fetch.iter().find_map(|av| match av {
AttributeValue::BodySection {
section: None,
data: Some(body),
..
}
| AttributeValue::Rfc822(Some(body)) => Some(&**body),
_ => None,
})
}