some more commands
This commit is contained in:
parent
508429ff5d
commit
5438bb170d
8 changed files with 994 additions and 27 deletions
742
Cargo.lock
generated
742
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,7 @@ inotify = { version = "0.9.2", features = ["stream"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
panorama-imap = { path = "imap", version = "0" }
|
panorama-imap = { path = "imap", version = "0" }
|
||||||
parking_lot = "0.11.1"
|
parking_lot = "0.11.1"
|
||||||
|
pgp = "0.7.1"
|
||||||
pin-project = "1.0.5"
|
pin-project = "1.0.5"
|
||||||
rustls-connector = "0.13.1"
|
rustls-connector = "0.13.1"
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
|
|
|
@ -146,6 +146,7 @@ impl ClientAuthenticated {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the LIST command
|
||||||
pub async fn list(&mut self) -> Result<()> {
|
pub async fn list(&mut self) -> Result<()> {
|
||||||
let cmd = Command::List {
|
let cmd = Command::List {
|
||||||
reference: "".to_owned(),
|
reference: "".to_owned(),
|
||||||
|
@ -155,4 +156,14 @@ impl ClientAuthenticated {
|
||||||
debug!("list response: {:?}", resp);
|
debug!("list response: {:?}", resp);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the SELECT command
|
||||||
|
pub async fn select(&mut self, mailbox: impl AsRef<str>) -> Result<()> {
|
||||||
|
let cmd = Command::Select {
|
||||||
|
mailbox: mailbox.as_ref().to_owned(),
|
||||||
|
};
|
||||||
|
let resp = self.execute(cmd).await?;
|
||||||
|
debug!("select response: {:?}", resp);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,22 @@ fn build_resp_code(pair: Pair<Rule>) -> Option<ResponseCode> {
|
||||||
Rule::capability_data => ResponseCode::Capabilities(build_capabilities(pair)),
|
Rule::capability_data => ResponseCode::Capabilities(build_capabilities(pair)),
|
||||||
Rule::resp_text_code_readwrite => ResponseCode::ReadWrite,
|
Rule::resp_text_code_readwrite => ResponseCode::ReadWrite,
|
||||||
Rule::resp_text_code_uidvalidity => ResponseCode::UidValidity(build_number(unwrap1(pair))),
|
Rule::resp_text_code_uidvalidity => ResponseCode::UidValidity(build_number(unwrap1(pair))),
|
||||||
|
Rule::resp_text_code_uidnext => ResponseCode::UidNext(build_number(unwrap1(pair))),
|
||||||
Rule::resp_text_code_unseen => ResponseCode::Unseen(build_number(unwrap1(pair))),
|
Rule::resp_text_code_unseen => ResponseCode::Unseen(build_number(unwrap1(pair))),
|
||||||
|
// TODO: maybe have an actual type for these flags instead of just string
|
||||||
|
Rule::resp_text_code_permanentflags => {
|
||||||
|
ResponseCode::PermanentFlags(pair.into_inner().map(|p| p.as_str().to_owned()).collect())
|
||||||
|
}
|
||||||
|
Rule::resp_text_code_other => {
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
|
let pair = pairs.next().unwrap();
|
||||||
|
let a = pair.as_str().to_owned();
|
||||||
|
let mut b = None;
|
||||||
|
if let Some(pair) = pairs.next() {
|
||||||
|
b = Some(pair.as_str().to_owned());
|
||||||
|
}
|
||||||
|
ResponseCode::Other(a, b)
|
||||||
|
}
|
||||||
_ => unreachable!("{:#?}", pair),
|
_ => unreachable!("{:#?}", pair),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -241,8 +256,9 @@ fn build_flag(mut pair: Pair<Rule>) -> MailboxFlag {
|
||||||
"\\Deleted" => MailboxFlag::Deleted,
|
"\\Deleted" => MailboxFlag::Deleted,
|
||||||
"\\Seen" => MailboxFlag::Seen,
|
"\\Seen" => MailboxFlag::Seen,
|
||||||
"\\Draft" => MailboxFlag::Draft,
|
"\\Draft" => MailboxFlag::Draft,
|
||||||
s if s.starts_with("\\") => MailboxFlag::Ext(s.to_owned()),
|
// s if s.starts_with("\\") => MailboxFlag::Ext(s.to_owned()),
|
||||||
_ => unreachable!("{:#?}", pair.as_str()),
|
// TODO: what??
|
||||||
|
s => MailboxFlag::Ext(s.to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +325,9 @@ fn build_mailbox_list(pair: Pair<Rule>) -> (Vec<String>, Option<String>, String)
|
||||||
|
|
||||||
fn build_mbx_list_flags(pair: Pair<Rule>) -> Vec<String> {
|
fn build_mbx_list_flags(pair: Pair<Rule>) -> Vec<String> {
|
||||||
assert!(matches!(pair.as_rule(), Rule::mbx_list_flags));
|
assert!(matches!(pair.as_rule(), Rule::mbx_list_flags));
|
||||||
pair.into_inner().map(|pair| pair.as_str().to_owned()).collect()
|
pair.into_inner()
|
||||||
|
.map(|pair| pair.as_str().to_owned())
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unwraps a singleton pair (a pair that only has one element in its `inner` list)
|
/// Unwraps a singleton pair (a pair that only has one element in its `inner` list)
|
||||||
|
|
|
@ -68,8 +68,8 @@ mailbox = { ^"INBOX" | astring }
|
||||||
mailbox_data = { mailbox_data_flags | mailbox_data_list | (^"LSUB" ~ sp ~ mailbox_list) | (^"SEARCH" ~ (sp ~ nz_number)*) | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | mailbox_data_recent }
|
mailbox_data = { mailbox_data_flags | mailbox_data_list | (^"LSUB" ~ sp ~ mailbox_list) | (^"SEARCH" ~ (sp ~ nz_number)*) | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | mailbox_data_recent }
|
||||||
mailbox_data_exists = { number ~ sp ~ ^"EXISTS" }
|
mailbox_data_exists = { number ~ sp ~ ^"EXISTS" }
|
||||||
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
|
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
|
||||||
mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
|
||||||
mailbox_data_list = { ^"LIST" ~ sp ~ mailbox_list }
|
mailbox_data_list = { ^"LIST" ~ sp ~ mailbox_list }
|
||||||
|
mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
||||||
mailbox_list = { mailbox_list_flags ~ sp ~ mailbox_list_string ~ sp ~ mailbox }
|
mailbox_list = { mailbox_list_flags ~ sp ~ mailbox_list_string ~ sp ~ mailbox }
|
||||||
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
||||||
mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
||||||
|
@ -87,10 +87,10 @@ msg_att = { "(" ~ msg_att_dyn_or_stat ~ (sp ~ msg_att_dyn_or_stat)* ~ ")" }
|
||||||
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
|
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
|
||||||
msg_att_dynamic = { ^"FLAGS" ~ sp ~ "(" ~ (flag_fetch ~ (sp ~ flag_fetch)*)? ~ ")" }
|
msg_att_dynamic = { ^"FLAGS" ~ sp ~ "(" ~ (flag_fetch ~ (sp ~ flag_fetch)*)? ~ ")" }
|
||||||
msg_att_static = { msg_att_static_envelope | msg_att_static_internaldate | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | msg_att_static_rfc822_size | msg_att_static_body | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | (^"UID" ~ sp ~ uniqueid) }
|
msg_att_static = { msg_att_static_envelope | msg_att_static_internaldate | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | msg_att_static_rfc822_size | msg_att_static_body | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | (^"UID" ~ sp ~ uniqueid) }
|
||||||
|
msg_att_static_body = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
||||||
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
||||||
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
||||||
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
||||||
msg_att_static_body = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
|
||||||
nil = { ^"NIL" }
|
nil = { ^"NIL" }
|
||||||
nstring = { string | nil }
|
nstring = { string | nil }
|
||||||
number = @{ digit{1,} }
|
number = @{ digit{1,} }
|
||||||
|
@ -103,11 +103,14 @@ resp_cond_state = { resp_status ~ sp ~ resp_text }
|
||||||
resp_specials = @{ "]" }
|
resp_specials = @{ "]" }
|
||||||
resp_status = { (^"OK" | ^"NO" | ^"BAD") }
|
resp_status = { (^"OK" | ^"NO" | ^"BAD") }
|
||||||
resp_text = { ("[" ~ resp_text_code ~ "]" ~ sp)? ~ text }
|
resp_text = { ("[" ~ resp_text_code ~ "]" ~ sp)? ~ text }
|
||||||
resp_text_code = { ^"ALERT" | (^"BADCHARSET" ~ (sp ~ "(" ~ astring ~ (sp ~ astring)* ~ ")")?) | capability_data | ^"PARSE" | (^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")") | ^"READ-ONLY" | resp_text_code_readwrite | ^"TRYCREATE" | (^"UIDNEXT" ~ sp ~ nz_number) | resp_text_code_uidvalidity | resp_text_code_unseen | (atom ~ (sp ~ resp_text_code_atom)?) }
|
resp_text_code = { ^"ALERT" | (^"BADCHARSET" ~ (sp ~ "(" ~ astring ~ (sp ~ astring)* ~ ")")?) | capability_data | ^"PARSE" | resp_text_code_permanentflags | ^"READ-ONLY" | resp_text_code_readwrite | ^"TRYCREATE" | resp_text_code_uidnext | resp_text_code_uidvalidity | resp_text_code_unseen | resp_text_code_other }
|
||||||
resp_text_code_atom = @{ (!"]" ~ text_char){1,} }
|
resp_text_code_atom = @{ (!"]" ~ text_char){1,} }
|
||||||
|
resp_text_code_permanentflags = { ^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")" }
|
||||||
resp_text_code_readwrite = { ^"READ-WRITE" }
|
resp_text_code_readwrite = { ^"READ-WRITE" }
|
||||||
resp_text_code_uidvalidity = { ^"UIDVALIDITY" ~ sp ~ nz_number }
|
resp_text_code_uidvalidity = { ^"UIDVALIDITY" ~ sp ~ nz_number }
|
||||||
|
resp_text_code_uidnext = { ^"UIDNEXT" ~ sp ~ nz_number }
|
||||||
resp_text_code_unseen = { ^"UNSEEN" ~ sp ~ nz_number }
|
resp_text_code_unseen = { ^"UNSEEN" ~ sp ~ nz_number }
|
||||||
|
resp_text_code_other = { (atom ~ (sp ~ resp_text_code_atom)?) }
|
||||||
response = { continue_req | response_data | response_done }
|
response = { continue_req | response_data | response_done }
|
||||||
response_data = { "*" ~ sp ~ (resp_cond_state | resp_cond_bye | mailbox_data | message_data | capability_data) ~ crlf }
|
response_data = { "*" ~ sp ~ (resp_cond_state | resp_cond_bye | mailbox_data | message_data | capability_data) ~ crlf }
|
||||||
response_done = { response_tagged | response_fatal }
|
response_done = { response_tagged | response_fatal }
|
||||||
|
|
|
@ -51,6 +51,7 @@ pub enum ResponseCode {
|
||||||
AppendUid(u32, Vec<UidSetMember>),
|
AppendUid(u32, Vec<UidSetMember>),
|
||||||
CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
|
CopyUid(u32, Vec<UidSetMember>, Vec<UidSetMember>),
|
||||||
UidNotSticky,
|
UidNotSticky,
|
||||||
|
Other(String, Option<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
|
227
rfc/rfc2177.txt
Normal file
227
rfc/rfc2177.txt
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Network Working Group B. Leiba
|
||||||
|
Request for Comments: 2177 IBM T.J. Watson Research Center
|
||||||
|
Category: Standards Track June 1997
|
||||||
|
|
||||||
|
|
||||||
|
IMAP4 IDLE command
|
||||||
|
|
||||||
|
Status of this Memo
|
||||||
|
|
||||||
|
This document specifies an Internet standards track protocol for the
|
||||||
|
Internet community, and requests discussion and suggestions for
|
||||||
|
improvements. Please refer to the current edition of the "Internet
|
||||||
|
Official Protocol Standards" (STD 1) for the standardization state
|
||||||
|
and status of this protocol. Distribution of this memo is unlimited.
|
||||||
|
|
||||||
|
1. Abstract
|
||||||
|
|
||||||
|
The Internet Message Access Protocol [IMAP4] requires a client to
|
||||||
|
poll the server for changes to the selected mailbox (new mail,
|
||||||
|
deletions). It's often more desirable to have the server transmit
|
||||||
|
updates to the client in real time. This allows a user to see new
|
||||||
|
mail immediately. It also helps some real-time applications based on
|
||||||
|
IMAP, which might otherwise need to poll extremely often (such as
|
||||||
|
every few seconds). (While the spec actually does allow a server to
|
||||||
|
push EXISTS responses aysynchronously, a client can't expect this
|
||||||
|
behaviour and must poll.)
|
||||||
|
|
||||||
|
This document specifies the syntax of an IDLE command, which will
|
||||||
|
allow a client to tell the server that it's ready to accept such
|
||||||
|
real-time updates.
|
||||||
|
|
||||||
|
2. Conventions Used in this Document
|
||||||
|
|
||||||
|
In examples, "C:" and "S:" indicate lines sent by the client and
|
||||||
|
server respectively.
|
||||||
|
|
||||||
|
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
|
||||||
|
in this document are to be interpreted as described in RFC 2060
|
||||||
|
[IMAP4].
|
||||||
|
|
||||||
|
3. Specification
|
||||||
|
|
||||||
|
IDLE Command
|
||||||
|
|
||||||
|
Arguments: none
|
||||||
|
|
||||||
|
Responses: continuation data will be requested; the client sends
|
||||||
|
the continuation data "DONE" to end the command
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Leiba Standards Track [Page 1]
|
||||||
|
|
||||||
|
RFC 2177 IMAP4 IDLE command June 1997
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Result: OK - IDLE completed after client sent "DONE"
|
||||||
|
NO - failure: the server will not allow the IDLE
|
||||||
|
command at this time
|
||||||
|
BAD - command unknown or arguments invalid
|
||||||
|
|
||||||
|
The IDLE command may be used with any IMAP4 server implementation
|
||||||
|
that returns "IDLE" as one of the supported capabilities to the
|
||||||
|
CAPABILITY command. If the server does not advertise the IDLE
|
||||||
|
capability, the client MUST NOT use the IDLE command and must poll
|
||||||
|
for mailbox updates. In particular, the client MUST continue to be
|
||||||
|
able to accept unsolicited untagged responses to ANY command, as
|
||||||
|
specified in the base IMAP specification.
|
||||||
|
|
||||||
|
The IDLE command is sent from the client to the server when the
|
||||||
|
client is ready to accept unsolicited mailbox update messages. The
|
||||||
|
server requests a response to the IDLE command using the continuation
|
||||||
|
("+") response. The IDLE command remains active until the client
|
||||||
|
responds to the continuation, and as long as an IDLE command is
|
||||||
|
active, the server is now free to send untagged EXISTS, EXPUNGE, and
|
||||||
|
other messages at any time.
|
||||||
|
|
||||||
|
The IDLE command is terminated by the receipt of a "DONE"
|
||||||
|
continuation from the client; such response satisfies the server's
|
||||||
|
continuation request. At that point, the server MAY send any
|
||||||
|
remaining queued untagged responses and then MUST immediately send
|
||||||
|
the tagged response to the IDLE command and prepare to process other
|
||||||
|
commands. As in the base specification, the processing of any new
|
||||||
|
command may cause the sending of unsolicited untagged responses,
|
||||||
|
subject to the ambiguity limitations. The client MUST NOT send a
|
||||||
|
command while the server is waiting for the DONE, since the server
|
||||||
|
will not be able to distinguish a command from a continuation.
|
||||||
|
|
||||||
|
The server MAY consider a client inactive if it has an IDLE command
|
||||||
|
running, and if such a server has an inactivity timeout it MAY log
|
||||||
|
the client off implicitly at the end of its timeout period. Because
|
||||||
|
of that, clients using IDLE are advised to terminate the IDLE and
|
||||||
|
re-issue it at least every 29 minutes to avoid being logged off.
|
||||||
|
This still allows a client to receive immediate mailbox updates even
|
||||||
|
though it need only "poll" at half hour intervals.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Leiba Standards Track [Page 2]
|
||||||
|
|
||||||
|
RFC 2177 IMAP4 IDLE command June 1997
|
||||||
|
|
||||||
|
|
||||||
|
Example: C: A001 SELECT INBOX
|
||||||
|
S: * FLAGS (Deleted Seen)
|
||||||
|
S: * 3 EXISTS
|
||||||
|
S: * 0 RECENT
|
||||||
|
S: * OK [UIDVALIDITY 1]
|
||||||
|
S: A001 OK SELECT completed
|
||||||
|
C: A002 IDLE
|
||||||
|
S: + idling
|
||||||
|
...time passes; new mail arrives...
|
||||||
|
S: * 4 EXISTS
|
||||||
|
C: DONE
|
||||||
|
S: A002 OK IDLE terminated
|
||||||
|
...another client expunges message 2 now...
|
||||||
|
C: A003 FETCH 4 ALL
|
||||||
|
S: * 4 FETCH (...)
|
||||||
|
S: A003 OK FETCH completed
|
||||||
|
C: A004 IDLE
|
||||||
|
S: * 2 EXPUNGE
|
||||||
|
S: * 3 EXISTS
|
||||||
|
S: + idling
|
||||||
|
...time passes; another client expunges message 3...
|
||||||
|
S: * 3 EXPUNGE
|
||||||
|
S: * 2 EXISTS
|
||||||
|
...time passes; new mail arrives...
|
||||||
|
S: * 3 EXISTS
|
||||||
|
C: DONE
|
||||||
|
S: A004 OK IDLE terminated
|
||||||
|
C: A005 FETCH 3 ALL
|
||||||
|
S: * 3 FETCH (...)
|
||||||
|
S: A005 OK FETCH completed
|
||||||
|
C: A006 IDLE
|
||||||
|
|
||||||
|
4. Formal Syntax
|
||||||
|
|
||||||
|
The following syntax specification uses the augmented Backus-Naur
|
||||||
|
Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4].
|
||||||
|
Non-terminals referenced but not defined below are as defined by
|
||||||
|
[IMAP4].
|
||||||
|
|
||||||
|
command_auth ::= append / create / delete / examine / list / lsub /
|
||||||
|
rename / select / status / subscribe / unsubscribe
|
||||||
|
/ idle
|
||||||
|
;; Valid only in Authenticated or Selected state
|
||||||
|
|
||||||
|
idle ::= "IDLE" CRLF "DONE"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Leiba Standards Track [Page 3]
|
||||||
|
|
||||||
|
RFC 2177 IMAP4 IDLE command June 1997
|
||||||
|
|
||||||
|
|
||||||
|
5. References
|
||||||
|
|
||||||
|
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version
|
||||||
|
4rev1", RFC 2060, December 1996.
|
||||||
|
|
||||||
|
6. Security Considerations
|
||||||
|
|
||||||
|
There are no known security issues with this extension.
|
||||||
|
|
||||||
|
7. Author's Address
|
||||||
|
|
||||||
|
Barry Leiba
|
||||||
|
IBM T.J. Watson Research Center
|
||||||
|
30 Saw Mill River Road
|
||||||
|
Hawthorne, NY 10532
|
||||||
|
|
||||||
|
Email: leiba@watson.ibm.com
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Leiba Standards Track [Page 4]
|
||||||
|
|
|
@ -102,6 +102,10 @@ async fn imap_main(acct: MailAccountConfig) -> Result<()> {
|
||||||
|
|
||||||
debug!("authentication successful!");
|
debug!("authentication successful!");
|
||||||
|
|
||||||
|
// let's just select INBOX for now, maybe have a config for default mailbox later?
|
||||||
|
debug!("selecting the INBOX mailbox");
|
||||||
|
authed.select("INBOX").await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
debug!("listing all emails...");
|
debug!("listing all emails...");
|
||||||
let folder_tree = authed.list().await?;
|
let folder_tree = authed.list().await?;
|
||||||
|
|
Loading…
Reference in a new issue