Giter VIP home page Giter VIP logo

rust-imap's Introduction

This crate lets you connect to and interact with servers that implement the IMAP protocol (RFC 3501 and various extensions).

It has moved to jonhoo/rust-imap.

rust-imap's People

Contributors

arges avatar artemgr avatar causal-agent avatar dario23 avatar frewsxcv avatar gcollura avatar greenpdx avatar greizgh avatar jonhoo avatar k-o-ta avatar mattnenterprise avatar miquelruiz avatar mordak avatar mtorromeo avatar nagy avatar rhn avatar svsintel avatar vandenoever avatar victorkoenders avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-imap's Issues

Feature request: IMAP IDLE support

I'm thinking of porting my mail notification program hasmail to Rust, but for that I need to be able to use IMAP's IDLE command. Is there any chance support for that might be added? I guess I could do it manually using run_command_and_read_response, but a more native approach would be really nice. Maybe even exposing IDLE as an Iterator?

Discarded EXPUNGE/EXISTS responses

When the wait functions return on an IdleHandle, the response doesn't contain the list of untagged EXPUNGE and EXISTS responses that have occurred. This means we don't necessarily know which sequence ids correspond to which messages anymore. E.g, we may be able to determine that a message was deleted because the exists parameter on the mailbox was decremented, but we don't know if that was the message with sequence id 1 or 10,000. This means that we have to maintain a record of the UID list and run unnecessary UID searches sometimes.

The wait functions currently return a Result<()>. They could be updated to return a list of EXPUNGE and EXISTS responses.

Port to native-tls

The native-tls crate has a better portability story than just using openssl does.

Cannot compile example

I encountered some troubles when I wanted to implement imap in my project.

error[E0308]: mismatched types
  --> src/server.rs:36:97
   |
36 |         let mut imap_socket = imap::client::Client::secure_connect(socket_addr, &master.domain, &ssl_connector).unwrap();
   |                                                                                                 ^^^^^^^^^^^^^^ expected struct `native_tls::TlsConnector`, found a different struct `native_tls::TlsConnector`
   |
   = note: expected type `&native_tls::TlsConnector` (struct `native_tls::TlsConnector`)
              found type `&native_tls::TlsConnector` (struct `native_tls::TlsConnector`)
note: Perhaps two different versions of crate `native_tls` are being used?

I fixed it by downgrading the native_tls dependency to version 0.1.
So my Cargo.toml looks like this now:

imap = "0.8.1"
native-tls = "0.1"

Maybe you could make the native_tls dependency of imap public.

Compiling issue - on mac?

Beware: Rust-newbie ahead!

I'm trying to use rust-imap on a MacOS X 10.11.6 with rust (cargo-0.17.0-dev) and I copy/pasted the example-program from the README.md-file into a new project:

cargo new --bin testimap
cd testimap
cat <<EOF > src/main.rs
extern crate imap;
extern crate openssl;
...
		Err(e) => println!("Error Fetching email 2: {.unwrap();
}
EOF
echo imap = \"0.2.1\" >> Cargo.toml 
cargo build

This outputs the following for me:

Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling pkg-config v0.3.9
   Compiling libc v0.2.21
   Compiling openssl v0.8.3
   Compiling void v1.0.2
   Compiling regex-syntax v0.4.0
   Compiling utf8-ranges v1.0.0
   Compiling openssl-sys v0.7.17
   Compiling thread-id v3.0.0
   Compiling bitflags v0.7.0
   Compiling lazy_static v0.2.6
   Compiling memchr v1.0.1
   Compiling unreachable v0.1.1
   Compiling thread_local v0.3.3
   Compiling aho-corasick v0.6.3
   Compiling regex v0.2.1
   Compiling imap v0.2.1
   Compiling testimap v0.1.0 (file:///Users/ineiti/IdeaProjects/testimap)
error[E0463]: can't find crate for `openssl`
 --> src/main.rs:2:1
  |
2 | extern crate openssl;
  | ^^^^^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to previous error

error: Could not compile `testimap`.

Is there a problem with the MacOSX-openssl support? I installed it with brew install openssl, but I never know which package it takes. Is this a rust-imap issue? openssl-issue?

Detect closed connections

The current code (in Client::readline) ignores the case when self.stream.read returns Ok(0), and simply keeps on spinning. However, when Ok(0) is returned, this is a signal that the underlying stream has been closed by the other end (see in particular the openssl error code https://docs.rs/openssl/0.9.17/openssl/ssl/enum.Error.html#variant.ZeroReturn which is translated into Ok(0) when using the Read trait, the documentation on Read::read, and the manpage for the recv system call).

The right thing for rust-imap to do is probably to translate this into an error, or alternatively to try and re-establish the connection. It is not entirely clear, but I would guess the former is most appropriate. The infinite spinning it does now certainly isn't :)

Displaying email content

Hello, I used a previous versions of this crate to fetch and get the email content, but with the updated version i don't find anything on how to access the contents of the fetch.

Previously i fetched and got my reponsse like this:

match imap_socket.fetch(&seq, "BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)]") {
    Ok(lines) => {
        println!("{:?}", lines[0]);
        // from = lines[1];
        // subject = lines[2];
        // date = lines[3];
    }
    Err(e) => println!("Error Fetching email {}: {}", x, e),
};

But now even with this and the example you give, I only get a list of flags and some ID/UID
Fetch { message: 348, flags: ["\\Seen"], uid: None, rfc822_header: None, rfc822: None }Mailbox emails number = 538

I have looked in the documentation and found that now fetch return a vector of imap::Fetch, but i am not abble to find anything leading to my fetch content.

Also, i am very new to RUST so i don't really understand all i am doing ๐Ÿ˜•

Provide variants of all interfaces with typed arguments

Most of the APIs we currently expose take &str arguments whose format is strictly dictated by RFC 3501. That's unfortunate, because it makes it easy for users to do things that are incorrect. Instead, we should write up typed versions of all those APIs (probably using the builder pattern) such that none of the APIs can be misused. We may want to just provide builders for the most common arguments, and then continue to expose string-only APIs for the more esoteric use-cases.

This should help with #74, and would be a good way to deal with #60.

Run rustfmt on the codebase

The code currently doesn't follow the style dictated by rustfmt. It'd be nice if we formatted the code once such that it follows the standard, as that would avoid unnecessary changes in later PRs/commits.

Debug Support

Support should be added for debugging. It will print both the sent commands, and the data received back from the server.

Here is an example:

server: * OK Dovecot ready.
client: a1 LOGIN MyUsername MyPassword
server: a1 OK Logged in.
client: a2 LIST "" "*"
server: * LIST (\HasNoChildren) "." "INBOX"
server: a2 OK List completed.
client: a3 EXAMINE INBOX
server: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
server: * OK [PERMANENTFLAGS ()] Read-only mailbox.
server: * 1 EXISTS
server: * 1 RECENT
server: * OK [UNSEEN 1] First unseen.
server: * OK [UIDVALIDITY 1257842737] UIDs valid
server: * OK [UIDNEXT 2] Predicted next UID
server: a3 OK [READ-ONLY] Select completed.
client: a4 FETCH 1 BODY[]
server: * 1 FETCH (BODY[] {405}
server: Return-Path: [email protected]
server: Received: from client.example.com ([192.0.2.1])
server:         by mx1.example.com with ESMTP
server:         id <[email protected]>
server:         for <[email protected]>; Tue, 20 Jan 2004 22:34:24 +0200
server: From: [email protected]
server: Subject: Test message
server: To: [email protected]
server: Message-Id: <[email protected]>
server: 
server: This is a test message.
server: )
server: a4 OK Fetch completed.
client: a5 LOGOUT
server: * BYE Logging out
server: a5 OK Logout completed.

Client.authenticate() should Base64 encode the data from the Authenticator

RFC 3501 6.2.2. AUTHENTICATE Command says that

The client response consists of a single line consisting of a BASE64 encoded string.

So the Base64 encoding is really part of the IMAP protocol. The PLAIN SASL mecanism specification even does not show the encoding. That means that every Authenticator::process method has to do the Base64 encoding. It would be easier for everybody if that process was done inside Client.do_auth_handshake() for every Authenticator.

If that sounds reasonnable I can provide a pull request.

Fail more gracefully if we fail to decode server replies

Currently, this line will always trigger, which causes us to send a logout to the server. Which is probably fine. But then we try to read the response to the LOGOUT, where we fail because we didn't finish parsing the response that caused us to terminate the connection in the first place. In particular, we often then hit a reply with the tag of the previous reply, which violates the assertion here. That logic should be cleaned up so we fail in a more helpful way.

Using extern crate, compile issue.

I tried to compile my freshly created Hello World Rust application with the imap crate.
After doing so, the compiler stumbles upon a compile error for the unrachable library, saying it cannot find the void crate it wants to use.

See also my StackOverflow question, here.
I have more info to be found there in terms of code snippets and things I've tried.

0.7.0 examples are out of date

Attempting to compile the example code in README.md with version 0.7.0 of the library yields the following compiler output:

error[E0599]: no method named `capability` found for type `imap::client::Client<native_tls::TlsStream<std::net::TcpStream>>` in the current scope
  --> src/main.rs:19:23
   |
19 |     match imap_socket.capability() {
   |                       ^^^^^^^^^^
   |
   = help: did you mean `capabilities`?

error[E0277]: `imap::Fetch` doesn't implement `std::fmt::Display`
  --> src/main.rs:38:30
   |
38 |                 print!("{}", line);
   |                              ^^^^ `imap::Fetch` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
   |
   = help: the trait `std::fmt::Display` is not implemented for `imap::Fetch`
   = note: required because of the requirements on the impl of `std::fmt::Display` for `&imap::Fetch`
   = note: required by `std::fmt::Display::fmt`

error: aborting due to 2 previous errors

error: Could not compile `comptest`.

Documentation of this new library interface would be very helpful; I switched to 0.6.0 this morning after a frustrating night of trying to figure out 0.7.0

Support fetching non-UTF-8 data.

The code currently assumes that all data is valid UTF-8, which is not true for a number of services (#11). A past PR (#33) tried to address this by changing all return types to Vec<u8>, but this makes for a much less pleasant API. Some further discussion on this can be found in #33 (comment). Ideally we'd like more structured responses (#28), though that will also eventually have this issue.

Some good points have been brought up in various comments from the aforementioned threads:

  • We can't just re-encode data to UTF-8, because it'll cause checksums and signatures to no longer match. #33 (comment)
  • RFC5738, which adds "UTF-8 compatability" for IMAP servers is often not supported, and also leaves a bunch of data in its original encoding. #11 (comment)

I think what we'd want is a way for the user to choose whether they want data to be parsed as UTF-8 or not, and if they choose not, to just get the raw bytes. Crucially though, the interface for when you do have UTF-8 data should not be significantly more complex than today. One way of achieving this is by using a trait that is implemented for Client with an Output associated type that implements From<Vec<u8>> (or something along those lines). @sanmai-NL also discussed a related solution in #11 (comment).

Relicense under dual MIT/Apache-2.0

This issue was automatically generated. Feel free to close without ceremony if
you do not agree with re-licensing or if it is not possible for other reasons.
Respond to @cmr with any questions or concerns, or pop over to
#rust-offtopic on IRC to discuss.

You're receiving this because someone (perhaps the project maintainer)
published a crates.io package with the license as "MIT" xor "Apache-2.0" and
the repository field pointing here.

TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that
license is good for interoperation. The MIT license as an add-on can be nice
for GPLv2 projects to use your code.

Why?

The MIT license requires reproducing countless copies of the same copyright
header with different names in the copyright field, for every MIT library in
use. The Apache license does not have this drawback. However, this is not the
primary motivation for me creating these issues. The Apache license also has
protections from patent trolls and an explicit contribution licensing clause.
However, the Apache license is incompatible with GPLv2. This is why Rust is
dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for
GPLv2 compat), and doing so would be wise for this project. This also makes
this crate suitable for inclusion and unrestricted sharing in the Rust
standard distribution and other projects using dual MIT/Apache, such as my
personal ulterior motive, the Robigalia project.

Some ask, "Does this really apply to binary redistributions? Does MIT really
require reproducing the whole thing?" I'm not a lawyer, and I can't give legal
advice, but some Google Android apps include open source attributions using
this interpretation. Others also agree with
it
.
But, again, the copyright notice redistribution is not the primary motivation
for the dual-licensing. It's stronger protections to licensees and better
interoperation with the wider Rust ecosystem.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright) and then add the following to
your README:

## License

Licensed under either of
 * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
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.

and in your license headers, use the following boilerplate (based on that used in Rust):

// Copyright (c) 2016 rust-imap developers
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these
from the Rust repo for a plain-text
version.

And don't forget to update the license metadata in your Cargo.toml to:

license = "MIT/Apache-2.0"

I'll be going through projects which agree to be relicensed and have approval
by the necessary contributors and doing this changes, so feel free to leave
the heavy lifting to me!

Contributor checkoff

To agree to relicensing, comment with :

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option

Or, if you're a contributor, you can check the box in this repo next to your
name. My scripts will pick this exact phrase up and check your checkbox, but
I'll come through and manually review this issue later as well.

Making imap::client::Client a trait?

At the moment I'm trying to use this library for some personal tools. One thing I would really like to do is to write a function that "sets up" a client. However (and pardon me if I'm not understanding the problem correctly -- I'm still quite new to Rust) as far as I can tell, there isn't a nice way for me to currently write a function that can return either an encrypted client struct (imap::client::Client<TlsStream<TcpStream>>) or an unencrypted client struct (imap::client::Client<TcpSream>). I believe this is because imap::client::Client is a struct and not a trait (so I cannot write a function that returns a trait object).

Is it reasonable to make imap::client::Client a trait? I'd be happy to work on this myself, but I thought I'd ask first because it's possible what I'm suggesting is not a good Rust practice.

Build fail on system with openssl 1.1.1

Easy fix, you just need to update the openssl library

Related Github issue:
sfackler/rust-openssl#994

this is the error:

   Compiling openssl v0.9.24                                                                                                                                                                                      
error: failed to run custom build command for `openssl v0.9.24`                                                                                                                                                   
process didn't exit successfully: `~/projects/rust/mail_test/target/debug/build/openssl-d6940fa3998f9474/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'Unable to detect OpenSSL version', ~/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-0.9.24/build.rs:16:14
note: Run with `RUST_BACKTRACE=1` for a backtrace.

NOTIFY extension and asynchronous events

I'm currently looking into writing a tool to monitor mailboxes for status changes. The typical way for this is probably SELECT/IDLE but I have quite a lot of mailboxes that I'd like to check. I could get a list of all mailboxes and check their statuses periodically but when I'm on a low-bandwidth connection with unfortunate and expensive mobile plans, that would also be a bad idea.
Therefore, I would like to use my server's NOTIFY extension (as in RFC5465). After authenticating, I'd issue a notify request for a set of events on a set of mailboxes, that could look like this:
a NOTIFY SET (personal (MessageNew MessageExpunge))
The server responds with a OK NOTIFY completed. (at least Dovecot does). After some time, additional (untagged) responses are generated asynchronously, i.e.

* STATUS Sent (MESSAGES 1082 UIDNEXT 4821 UNSEEN 0)
* STATUS INBOX (MESSAGES 307 UIDNEXT 13311 UNSEEN 1)

until I either disconnect or stop them by issuing NOTIFY NONE.

Well, the notification request can be sent by the current API. However, I don't see a way to collect those untagged status reports. One problem might be that they may be scattered through the whole connection like that (C being the client, S the server):

C: a NOTIFY SET (personal messagenew messageexpunge)
S: a OK NOTIFY completed.
C: a NOOP
S: * STATUS Foo (...)
S: a OK NOOP completed.
S: * STATUS Bar (...)

I haven't looked into the depths of rust-imap but I guess that it could probably interfere with the response parsing. My uneducated guess would be that implementing something like the IdleHandle where all those STATUS messages are collected that are not a direct response to a STATUS command. That might be hard to detect, though, if at all possible.

Do you have any ideas how to support this type of operation?

More involved parsing

Currently, all the commands simply return Vec<String>. It'd be great if they returned more semantically relevant results (i.e., fully parsed structs). This would also let us make the IDLE handle return an Iterator over said structs, so you could monitor changes to the mailbox in real-time.

panic on hotmail/outlook.com IMAP fetch

I put content of example.rs into a test of my project, use imap-mail.outlook.com:993.

I got a panic at 'imap_socket.fetch("2", "body[text]");'.

My env is rust-1.8.0

thread 'test_imap_fetch' panicked at 'calledResult::unwrap()on anErrvalue: FromUtf8Error { bytes: [215, 238, 189, 252, 180, 211, 32, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 213, 202, 187, 167, 32, 118, 101, 42, 42, 42, 42, 42, 64, 111, 117, 116, 108, 111, 111, 107, 46, 99, 111, 109, 32, 214, 208, 201, 190, 179, 253, 193, 203, 210, 212, 207, 194, 176, 178, 200, 171, 208, 197, 207, 162, 58, 13, 10], error: Utf8Error { valid_up_to: 0 } }', ../src/libcore/result.rs:746 stack backtrace: 1: 0x10a5dfae8 - sys::backtrace::tracing::imp::write::h3b28049ffa6d6406ZZu 2: 0x10a5e1875 - panicking::default_handler::_$u7b$$u7b$closure$u7d$$u7d$::closure.43942 3: 0x10a5e13d7 - panicking::default_handler::h9792cd244a79d9daorz 4: 0x10a5d4366 - sys_common::unwind::begin_unwind_inner::h127fbab41243a988LYt 5: 0x10a5d481e - sys_common::unwind::begin_unwind_fmt::h849e306453bce5feRXt 6: 0x10a5df007 - rust_begin_unwind 7: 0x10a6060f0 - panicking::panic_fmt::h98b8cbb286f5298alcM 8: 0x10a4f4b29 - result::unwrap_failed::h7834371121640111038 9: 0x10a4f4945 - result::Result<T, E>::unwrap::h5359275872070956371 10: 0x10a4f0837 - client::IMAPStream::read_response::haf4a98f70dfa51f1hEa 11: 0x10a4de1c2 - client::IMAPStream::run_command::h920cc295b4f173d4kza 12: 0x10a4ed351 - client::IMAPStream::fetch::h2876f40048060ec4Upa 13: 0x10a4bb36e - mail::imap_fetch::h3d57dadf089b9b98Maa 14: 0x10a497848 - test_imap_fetch::h8dacc3008846b6edgaa 15: 0x10a4b578b - boxed::F.FnBox<A>::call_box::h9454666050355180836 16: 0x10a4b7bfd - sys_common::unwind::try::try_fn::h13611093186668648166 ...

Panicked with `Parse(Unexpected("MailboxData(Recent(1))"))`

Hello!

I wrote a minimal example of my code, which works totally fine when only one guy sends an email. However, when I try to send an email from two different email addresses to server at the same time, my server panics.

Cargo.toml

[package]
name = "imap_test"
version = "0.1.0"
authors = ["Kevin Per <[email protected]>"]

[dependencies]
imap = "0.8.1"
native-tls = "0.1" 
mailparse = "0.6.2"

main.rs:

extern crate imap;
extern crate mailparse;
extern crate native_tls;

use imap::client::Client;
use native_tls::{TlsConnector, TlsStream};
use std::net::TcpStream;

use mailparse::*;

fn main() {
    let domain = "";
    let email = "";
    let password = "";


    let socket_addr = (domain.clone(), 993);
    let ssl_connector = TlsConnector::builder().unwrap().build().unwrap();
    let mut imap_socket =
        imap::client::Client::secure_connect(socket_addr, domain.clone(), &ssl_connector)
            .unwrap();

    imap_socket
        .login(email, password)
        .unwrap();

    loop {
        match imap_socket.select("INBOX") {
            Ok(mailbox) => {
                println!("{}", mailbox);
            }
            Err(e) => println!("Error selecting INBOX: {}", e),
        };

        let mut unseen = imap_socket
            .run_command_and_read_response("UID SEARCH UNSEEN 1:*")
            .unwrap();

        // remove last line of response (OK Completed)
        unseen.pop();

        let mut uids = Vec::new();
        let unseen = ::std::str::from_utf8(&unseen[..]).unwrap();
        let unseen = unseen.split_whitespace().skip(2);
        for uid in unseen.take_while(|&e| e != "" && e != "Completed") {
            if let Ok(uid) = usize::from_str_radix(uid, 10) {
                uids.push(format!("{}", uid));
            }
        }

        uids.reverse(); //latest first

        for uid in uids.iter() {
            let raw = imap_socket.uid_fetch(uid, "RFC822").unwrap(); //here it panics!

            for message in raw.iter() {
                let m = message.rfc822();

                if m.is_none() {
                    continue;
                }

                let parsed = parse_mail(m.unwrap()).unwrap();

                let subject = parsed.headers.get_first_value("Subject").unwrap().unwrap();
                let from = parsed.headers.get_first_value("From").unwrap().unwrap();

                if parsed.subparts.len() > 0 {
                    let body = parsed.subparts[0].get_body().unwrap();

                    println!("From: {}", from);
                    println!("Subject: {}", subject);
                    println!("Body: {}", body);
                }
            }
        }
    }
}

Simple LIST command fails with Gmail

Hey there.

I'm trying to LIST all mailboxes with Gmail.

Connecting works fine, but executing the list command results in weird "Unknown command" errors.

NOTE: the value for the command changes with each invocation.

 INFO 2018-07-16T14:19:51Z: mycloudbackup::service::email: listing mailboxes...
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: BadResponse("Unknown command q4-v6mb43737048lth")

stack backtrace:
   0:     0x55ab9a875425 - backtrace::backtrace::libunwind::trace::hf612167c3b0ad921
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/libunwind.rs:53
                         - backtrace::backtrace::trace::h574c6ad167c02b7c
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/mod.rs:42
   1:     0x55ab9a870c5e - backtrace::capture::Backtrace::new_unresolved::hfc2f37046d10e114
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/capture.rs:88
   2:     0x55ab9a86f037 - failure::backtrace::internal::InternalBacktrace::new::h50a420eea00b0a25
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.1/src/backtrace/internal.rs:44
   3:     0x55ab9a86e7dc - failure::backtrace::Backtrace::new::ha4994e8172e6037b
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.1/src/backtrace/mod.rs:98
   4:     0x55ab9a6e4d4d - <failure::error::Error as core::convert::From<F>>::from::h2008397b91b24e51
                        at /home/theduke/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.1/src/error.rs:34
   5:     0x55ab9a6e4852 - mycloudbackup::service::email::EmailService::run::h09ca1ab1e24544f2
                        at src/service/email/mod.rs:40
   6:     0x55ab9a6e6a3e - mycloudbackup::main::h1b5295b517f21400
                        at src/main.rs:30
   7:     0x55ab9a6e3e7f - std::rt::lang_start::{{closure}}::hf04d67d357e8192d
                        at /checkout/src/libstd/rt.rs:74
   8:     0x55ab9a95a2e2 - std::rt::lang_start_internal::{{closure}}::h72602870b4a34363
                        at libstd/rt.rs:59
                         - std::panicking::try::do_call::hc2917ab2c572e22d
                        at libstd/panicking.rs:310
   9:     0x55ab9a973239 - __rust_maybe_catch_panic
                        at libpanic_unwind/lib.rs:105
  10:     0x55ab9a95f4f5 - std::panicking::try::h3777f1f99a655493
                        at libstd/panicking.rs:289
                         - std::panic::catch_unwind::hab6d1467193fc938
                        at libstd/panic.rs:374
                         - std::rt::lang_start_internal::h106bcdfb2e3beaf8
                        at libstd/rt.rs:58
  11:     0x55ab9a6e3e57 - std::rt::lang_start::hfacb80090f7d05a5
                        at /checkout/src/libstd/rt.rs:74
  12:     0x55ab9a6e6adc - main
  13:     0x7fa1a55b306a - __libc_start_main
  14:     0x55ab9a6dc369 - _start
  15:                0x0 - <unknown>', libcore/result.rs:945:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:227
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:463
   5: std::panicking::begin_panic_fmt
             at libstd/panicking.rs:350
   6: rust_begin_unwind
             at libstd/panicking.rs:328
   7: core::panicking::panic_fmt
             at libcore/panicking.rs:71
   8: core::result::unwrap_failed
             at /checkout/src/libcore/macros.rs:26
   9: <core::result::Result<T, E>>::unwrap
             at /checkout/src/libcore/result.rs:782
  10: mycloudbackup::main
             at src/main.rs:30
  11: std::rt::lang_start::{{closure}}
             at /checkout/src/libstd/rt.rs:74
  12: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:310
  13: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:105
  14: std::rt::lang_start_internal
             at libstd/panicking.rs:289
             at libstd/panic.rs:374
             at libstd/rt.rs:58
  15: std::rt::lang_start
             at /checkout/src/libstd/rt.rs:74
  16: main
  17: __libc_start_main
  18: _start
        let ssl_connector = TlsConnector::builder()?.build()?;
        let socket_addr = (conf.domain.as_str(), conf.socket);
        let mut imap = Client::secure_connect(socket_addr, &conf.domain, &ssl_connector)?;

        // List all folders.
        info!("listing mailboxes...");
        let folders = imap.list("", "*")?;
        println!("{:#?}", folders);

What is the situation with pushing updates to crates.io ?

Hello everyone.

So the last push to crates.io was in April. However there were quite a few updates since then on github. Also I've seen a few issues being opened about this as well.

So what is the current situation here? Is the original contributor not responding? Can he/she not just add other contributors to the "Allowed to publish to crates.io" list? Is the original contributor sick? I really like this crate, but it'd be much more helpful if there'd be up to date versions on crates.io

Could someone enlighten me please?

Add more serious testing

While we currently have some amount of inline unit testing, we really want to test this library against a "real" IMAP server. The way to do that is probably to spin up GreenMail on Travis and then do a bunch of operations on the mail server.

I think what we'll want is this:

  • Pull in the GreenMail Docker image on Travis (see this .travis.yml for how)
  • Use lettre to populate the server with a bunch of different e-mails.
  • And then write tests that fetch, move, inspect, delete, expunge, and otherwise test all the things that imap lets you do.

Compilation error - use nom

Hi, thank you for create this package. Very useful.
One small thing. When compiling, I got
error[E0658]: access to extern crates through prelude is experimental (see issue #44660)
--> /root/.cargo/git/checkouts/rust-imap-eddc04189818a7a1/f02950a/src/client.rs:776:25
|
776 | Err(nom::Err::Incomplete(..)) => {
|

I added
use nom;
to src/client.rs, and everything was fine.

Can you please fix it?

Tagging

Could you use git tags to mark (past and future) released versions?

Does rust-imap parse things twice?

It seems like a common pattern in the codebase is to use run_command_and_read_response, and then parse its output. However, read_response already fully parses the response, its just that the results of the parsing seems to be discarded https://github.com/mattnenterprise/rust-imap/blob/master/src/client.rs#L521.

Assuming my reading of the code is correct, is there a reason it's laid out like this, as opposed to read_response returning a Vec of the parsed responses or similar?

Enabling debug output causes a panic.

Running the following code with version 0.7.0 of the library:

fn main() {
    let domain = "imap.gmail.com";
    let port = 993;
    let socket_addr = (domain, port);
    let ssl_connector = TlsConnector::builder().unwrap().build().unwrap();
    let mut imap_socket = Client::secure_connect(socket_addr, domain, ssl_connector).unwrap();

    imap_socket.debug = true;

    imap_socket.login("username", "password").unwrap();

    imap_socket.logout().unwrap();
}

Has a panic at runtime with the following stacktrace:

[jakob@Epsilon comptest]$ RUST_BACKTRACE=1 target/debug/comptest 
C: a1 LOGIN "username" "password"
thread 'main' panicked at 'attempt to subtract with overflow', /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:574:30
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at libstd/sys_common/backtrace.rs:59
             at libstd/panicking.rs:380
   3: std::panicking::default_hook
             at libstd/panicking.rs:396
   4: std::panicking::rust_panic_with_hook
             at libstd/panicking.rs:576
   5: std::panicking::begin_panic
             at libstd/panicking.rs:537
   6: std::panicking::begin_panic_fmt
             at libstd/panicking.rs:521
   7: rust_begin_unwind
             at libstd/panicking.rs:497
   8: core::panicking::panic_fmt
             at libcore/panicking.rs:71
   9: core::panicking::panic
             at libcore/panicking.rs:51
  10: <imap::client::Client<T>>::readline
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:574
  11: <imap::client::Client<T>>::read_response_onto
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:496
  12: <imap::client::Client<T>>::read_response
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:482
  13: <imap::client::Client<T>>::run_command_and_read_response
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:477
  14: <imap::client::Client<T>>::run_command_and_check_ok
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:466
  15: <imap::client::Client<T>>::login
             at /home/jakob/.cargo/registry/src/github.com-1ecc6299db9ec823/imap-0.7.0/src/client.rs:291
  16: comptest::main
             at src/main.rs:19
  17: std::rt::lang_start::{{closure}}
             at /checkout/src/libstd/rt.rs:74
  18: std::panicking::try::do_call
             at libstd/rt.rs:59
             at libstd/panicking.rs:479
  19: __rust_maybe_catch_panic
             at libpanic_unwind/lib.rs:102
  20: std::rt::lang_start_internal
             at libstd/panicking.rs:458
             at libstd/panic.rs:358
             at libstd/rt.rs:58
  21: std::rt::lang_start
             at /checkout/src/libstd/rt.rs:74
  22: main
  23: __libc_start_main
  24: _start

Fix crate documentation

The crate's documentation is currently pretty minimal, especially the top-level docs (docs.rs/imap for example has almost nothing). This should be fixed. We should also turn on #![deny(missing_docs)] to ensure that things stay documented going forwards.

Please consider to upgrade openssl dependency

openssl can be compiled with single version only, so in single project all crates with dependency of openssl should use same version of the openssl crate. If you'll upgrade dependency (and it may require some small changes in code), this crate will be more easy to add into projects :)

APPEND support is incomplete

At the moment APPEND only supports setting the body of the message. However, RFC3501 allows users to specify the flag set to be applied to a message, as well as the date the message was received. Quoting the specification:

6.3.11. APPEND Command

   Arguments:  mailbox name
               OPTIONAL flag parenthesized list
               OPTIONAL date/time string
               message literal

We could change the append method to:

use chrono::DateTime;
use chrono::offset::Utc;

fn append(&mut self, folder: &str,
          flags: Vec<String>,
          datetime: DateTime<Utc>,
          message: &[u8]) { /* ... */ } 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.