insert mail into the database

This commit is contained in:
Michael Zhang 2021-03-25 07:14:05 -05:00
parent 4be9e6e1e8
commit eb880e1b92
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
7 changed files with 61 additions and 26 deletions

View file

@ -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),

View file

@ -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 }

View file

@ -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 {

View file

@ -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")
); );

View file

@ -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?;
} }
} }
} }

View file

@ -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 (?, ?, ?)
"#;

View file

@ -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)?);
} }