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.
IMAP client for Rust
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.
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
?
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.
The native-tls crate has a better portability story than just using openssl does.
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.
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?
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 :)
at line https://github.com/mattnenterprise/rust-imap/blob/master/src/client.rs#L282, seems like you forget to check the return size of read, as a result, if the read
always reads 0 bytes, the program will stuck in this loop and never returned until the program runs out of systems memory.
This is the result from strace.
And I add these to client.rs in order to detect this abnormal behavior.
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 ๐
@mattnenterprise in addr2line
, we're switching to cargo-tarpaulin
for code coverage, and completely removing cargo-travis
. Might be something we'll want to do here as well.
The "unwrap" call in https://github.com/mattnenterprise/rust-imap/blob/master/src/client.rs#L34 is causing the library to panic on connection errors.
Are you interested in a pull request so it returns an error instead of panicking? That way a connection problem could be properly handled from the caller.
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.
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.
@jonhoo Would it be easier just to move this repo to an organization so you can publish to crates.io ?
The process of adding others is described at https://doc.rust-lang.org/cargo/reference/publishing.html#cargo-owner
I guess we could create a dummy organization and team, but never move the repo as an alternative. If you didn't want to move the repo.
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.
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.
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.
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.
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
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:
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).
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.
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.
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!
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.
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.
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.
The openssl crate removed SslStream::new
, which was fixed in #5, but that fix isn't available on crates.io yet.
The README says that rust-imap are "IMAP client bindings for Rust." Is this correct? Skipping through the source code this seems not to be the case.
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?
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.
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 'called
Result::unwrap()on an
Errvalue: 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 ...
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);
}
}
}
}
}
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);
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?
While 0.9
made some significant improvements to the imap
crates' interface, we still have some way to go. In particular, we should go through the Rust API guidelines checklist and do the best we can to match its recommendations. I think this is probably a blocker for 1.0.
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:
.travis.yml
for how)lettre
to populate the server with a bunch of different e-mails.imap
lets you do.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?
For example, operations like listing and searching (including the UID variants) should be both supported and well documented, as it's something many users are likely to want to do. See also #73 (comment)
Could you use git tags to mark (past and future) released versions?
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?
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
for local setups and for all ssh setups its nice to use ssh myuser@myhost' ~/.local/bin/run-imapserver
as email client
@jonhoo I'm thinking it might be a good idea to do some sort of code formatting check with rustfmt in CI.
Is support for the STORE command in the roadmap? (https://tools.ietf.org/html/rfc3501#section-6.4.6)
I could work on it if there's interest.
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.
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 :)
The error that is current returned is pretty hard to understand unless you're intimately familiar with the internals of rust-imap
.
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]) { /* ... */ }
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.