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_rfc822_size => AttributeValue::Rfc822Size(build_number(unwrap1(pair))),
|
||||||
Rule::msg_att_static_envelope => AttributeValue::Envelope(build_envelope(unwrap1(pair))),
|
Rule::msg_att_static_envelope => AttributeValue::Envelope(build_envelope(unwrap1(pair))),
|
||||||
// TODO: do this
|
// TODO: do this
|
||||||
Rule::msg_att_static_body_structure => AttributeValue::BodySection {
|
Rule::msg_att_static_body_structure => AttributeValue::BodySection(BodySection {
|
||||||
section: None,
|
section: None,
|
||||||
index: None,
|
index: None,
|
||||||
data: None,
|
data: None,
|
||||||
},
|
}),
|
||||||
Rule::msg_att_static_body_section => {
|
Rule::msg_att_static_body_section => {
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
let section = None;
|
let section = None;
|
||||||
let index = None;
|
pairs.next();
|
||||||
let data = None;
|
let index = match pairs.peek().unwrap().as_rule() {
|
||||||
AttributeValue::BodySection {
|
Rule::number => Some(build_number(unwrap1(pairs.next().unwrap()))),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let data = Some(pairs.next().unwrap().as_str().to_owned());
|
||||||
|
AttributeValue::BodySection(BodySection {
|
||||||
section,
|
section,
|
||||||
index,
|
index,
|
||||||
data,
|
data,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
Rule::msg_att_static_uid => AttributeValue::Uid(build_number(unwrap1(unwrap1(pair)))),
|
Rule::msg_att_static_uid => AttributeValue::Uid(build_number(unwrap1(unwrap1(pair)))),
|
||||||
_ => parse_fail!("{:#?}", pair),
|
_ => parse_fail!("{:#?}", pair),
|
||||||
|
|
|
@ -75,8 +75,6 @@ mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
||||||
mailbox_data_search = { ^"SEARCH" ~ (sp ~ nz_number)* }
|
mailbox_data_search = { ^"SEARCH" ~ (sp ~ nz_number)* }
|
||||||
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* ~ ")" }
|
||||||
// TODO: technically this should only be 1 quoted char
|
|
||||||
// mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
|
||||||
mailbox_list_string = ${ nstring }
|
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_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 }
|
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_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_structure | msg_att_static_body_section | msg_att_static_uid }
|
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_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_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 }
|
||||||
|
@ -112,12 +110,12 @@ 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" | 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 = { ^"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_other = { (atom ~ (sp ~ resp_text_code_atom)?) }
|
||||||
resp_text_code_permanentflags = { ^"PERMANENTFLAGS" ~ sp ~ "(" ~ (flag_perm ~ (sp ~ flag_perm)*)? ~ ")" }
|
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_uidnext = { ^"UIDNEXT" ~ 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_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 }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Structs and enums that have to do with responses.
|
//! Structs and enums that have to do with responses.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
@ -72,11 +73,7 @@ pub enum UidSetMember {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum AttributeValue {
|
pub enum AttributeValue {
|
||||||
BodySection {
|
BodySection(BodySection),
|
||||||
section: Option<SectionPath>,
|
|
||||||
index: Option<u32>,
|
|
||||||
data: Option<String>,
|
|
||||||
},
|
|
||||||
BodyStructure(BodyStructure),
|
BodyStructure(BodyStructure),
|
||||||
Envelope(Envelope),
|
Envelope(Envelope),
|
||||||
Flags(Vec<MailboxFlag>),
|
Flags(Vec<MailboxFlag>),
|
||||||
|
@ -89,6 +86,25 @@ pub enum AttributeValue {
|
||||||
Uid(u32),
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum BodyStructure {
|
pub enum BodyStructure {
|
||||||
Basic {
|
Basic {
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
CREATE TABLE IF NOT EXISTS "accounts" (
|
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
|
-- hash of the account details, used to check if accounts have changed
|
||||||
"checksum" TEXT,
|
"checksum" TEXT
|
||||||
"name" TEXT NOT NULL
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "mail" (
|
CREATE TABLE IF NOT EXISTS "mail" (
|
||||||
"id" INTEGER PRIMARY KEY,
|
"id" INTEGER PRIMARY KEY,
|
||||||
"account_id" INTEGER,
|
"account" TEXT,
|
||||||
"folder" TEXT,
|
"folder" TEXT,
|
||||||
"uid" INTEGER,
|
"uid" INTEGER
|
||||||
|
|
||||||
FOREIGN KEY ("account_id") REFERENCES "accounts" ("id")
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -80,7 +80,7 @@ pub async fn sync_main(
|
||||||
.await?;
|
.await?;
|
||||||
while let Some((uid, attrs)) = fetched.next().await {
|
while let Some((uid, attrs)) = fetched.next().await {
|
||||||
debug!("- {} : {:?}", uid, attrs);
|
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) {}
|
pub fn get_new_uids(&self, exists: u32) {}
|
||||||
|
|
||||||
/// Stores the given email
|
/// 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
|
message
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.level(log::LevelFilter::Trace);
|
.level(log::LevelFilter::Debug);
|
||||||
if let Some(log_file) = log_file {
|
if let Some(log_file) = log_file {
|
||||||
logger = logger.chain(fern::log_file(log_file)?);
|
logger = logger.chain(fern::log_file(log_file)?);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue