insert mail into the database
This commit is contained in:
parent
4be9e6e1e8
commit
eb880e1b92
7 changed files with 61 additions and 26 deletions
|
@ -171,20 +171,25 @@ fn build_msg_att_static(pair: Pair<Rule>) -> AttributeValue {
|
|||
Rule::msg_att_static_rfc822_size => AttributeValue::Rfc822Size(build_number(unwrap1(pair))),
|
||||
Rule::msg_att_static_envelope => AttributeValue::Envelope(build_envelope(unwrap1(pair))),
|
||||
// TODO: do this
|
||||
Rule::msg_att_static_body_structure => AttributeValue::BodySection {
|
||||
Rule::msg_att_static_body_structure => AttributeValue::BodySection(BodySection {
|
||||
section: None,
|
||||
index: None,
|
||||
data: None,
|
||||
},
|
||||
}),
|
||||
Rule::msg_att_static_body_section => {
|
||||
let mut pairs = pair.into_inner();
|
||||
let section = None;
|
||||
let index = None;
|
||||
let data = None;
|
||||
AttributeValue::BodySection {
|
||||
pairs.next();
|
||||
let index = match pairs.peek().unwrap().as_rule() {
|
||||
Rule::number => Some(build_number(unwrap1(pairs.next().unwrap()))),
|
||||
_ => None,
|
||||
};
|
||||
let data = Some(pairs.next().unwrap().as_str().to_owned());
|
||||
AttributeValue::BodySection(BodySection {
|
||||
section,
|
||||
index,
|
||||
data,
|
||||
}
|
||||
})
|
||||
}
|
||||
Rule::msg_att_static_uid => AttributeValue::Uid(build_number(unwrap1(unwrap1(pair)))),
|
||||
_ => parse_fail!("{:#?}", pair),
|
||||
|
|
|
@ -75,8 +75,6 @@ mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
|||
mailbox_data_search = { ^"SEARCH" ~ (sp ~ nz_number)* }
|
||||
mailbox_list = { mailbox_list_flags ~ sp ~ mailbox_list_string ~ sp ~ mailbox }
|
||||
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
||||
// TODO: technically this should only be 1 quoted char
|
||||
// mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
||||
mailbox_list_string = ${ nstring }
|
||||
mbx_list_flags = { (mbx_list_oflag ~ sp)* ~ mbx_list_sflag ~ (sp ~ mbx_list_oflag)* | mbx_list_oflag ~ (sp ~ mbx_list_oflag)* }
|
||||
mbx_list_oflag = { "\\NoInferiors" | flag_extension }
|
||||
|
@ -92,8 +90,8 @@ 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_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_structure | msg_att_static_body_section | msg_att_static_uid }
|
||||
msg_att_static_body_structure = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
||||
msg_att_static_body_section = { ^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring }
|
||||
msg_att_static_body_structure = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
||||
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
||||
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
||||
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
||||
|
@ -112,12 +110,12 @@ resp_status = { (^"OK" | ^"NO" | ^"BAD") }
|
|||
resp_text = { ("[" ~ resp_text_code ~ "]" ~ sp)? ~ text }
|
||||
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_other = { (atom ~ (sp ~ resp_text_code_atom)?) }
|
||||
resp_text_code_permanentflags = { ^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")" }
|
||||
resp_text_code_readwrite = { ^"READ-WRITE" }
|
||||
resp_text_code_uidvalidity = { ^"UIDVALIDITY" ~ sp ~ nz_number }
|
||||
resp_text_code_uidnext = { ^"UIDNEXT" ~ sp ~ nz_number }
|
||||
resp_text_code_uidvalidity = { ^"UIDVALIDITY" ~ 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_data = { "*" ~ sp ~ (resp_cond_state | resp_cond_bye | mailbox_data | message_data | capability_data) ~ crlf }
|
||||
response_done = { response_tagged | response_fatal }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Structs and enums that have to do with responses.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
|
@ -72,11 +73,7 @@ pub enum UidSetMember {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum AttributeValue {
|
||||
BodySection {
|
||||
section: Option<SectionPath>,
|
||||
index: Option<u32>,
|
||||
data: Option<String>,
|
||||
},
|
||||
BodySection(BodySection),
|
||||
BodyStructure(BodyStructure),
|
||||
Envelope(Envelope),
|
||||
Flags(Vec<MailboxFlag>),
|
||||
|
@ -89,6 +86,25 @@ pub enum AttributeValue {
|
|||
Uid(u32),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct BodySection {
|
||||
pub section: Option<SectionPath>,
|
||||
pub index: Option<u32>,
|
||||
pub data: Option<String>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for BodySection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"BodySection(section={:?} index={:?} data=<{}>",
|
||||
self.section,
|
||||
self.index,
|
||||
self.data.as_ref().map(|s| s.len()).unwrap_or(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum BodyStructure {
|
||||
Basic {
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
CREATE TABLE IF NOT EXISTS "accounts" (
|
||||
"id" INTEGER PRIMARY KEY,
|
||||
"name" TEXT PRIMARY KEY,
|
||||
-- hash of the account details, used to check if accounts have changed
|
||||
"checksum" TEXT,
|
||||
"name" TEXT NOT NULL
|
||||
"checksum" TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "mail" (
|
||||
"id" INTEGER PRIMARY KEY,
|
||||
"account_id" INTEGER,
|
||||
"account" TEXT,
|
||||
"folder" TEXT,
|
||||
"uid" INTEGER,
|
||||
|
||||
FOREIGN KEY ("account_id") REFERENCES "accounts" ("id")
|
||||
"uid" INTEGER
|
||||
);
|
||||
|
|
|
@ -80,7 +80,7 @@ pub async fn sync_main(
|
|||
.await?;
|
||||
while let Some((uid, attrs)) = fetched.next().await {
|
||||
debug!("- {} : {:?}", uid, attrs);
|
||||
mail_store.store_email();
|
||||
mail_store.store_email(&acct_name, &folder, uid).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,5 +46,24 @@ impl MailStore {
|
|||
pub fn get_new_uids(&self, exists: u32) {}
|
||||
|
||||
/// Stores the given email
|
||||
pub fn store_email(&self) {}
|
||||
pub async fn store_email(
|
||||
&self,
|
||||
acct: impl AsRef<str>,
|
||||
folder: impl AsRef<str>,
|
||||
uid: u32,
|
||||
) -> Result<()> {
|
||||
let id = sqlx::query(STORE_EMAIL_SQL)
|
||||
.bind(acct.as_ref())
|
||||
.bind(folder.as_ref())
|
||||
.bind(uid)
|
||||
.execute(&self.pool)
|
||||
.await?
|
||||
.last_insert_rowid();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const STORE_EMAIL_SQL: &str = r#"
|
||||
INSERT INTO "mail" (account, folder, uid)
|
||||
VALUES (?, ?, ?)
|
||||
"#;
|
||||
|
|
|
@ -133,7 +133,7 @@ fn setup_logger(log_file: Option<impl AsRef<Path>>) -> Result<()> {
|
|||
message
|
||||
))
|
||||
})
|
||||
.level(log::LevelFilter::Trace);
|
||||
.level(log::LevelFilter::Debug);
|
||||
if let Some(log_file) = log_file {
|
||||
logger = logger.chain(fern::log_file(log_file)?);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue