Add error queue for unhandled emails
parent
b6ac161fb3
commit
43e100917b
|
@ -99,6 +99,35 @@ enum Command {
|
|||
#[structopt(long)]
|
||||
dry_run: bool,
|
||||
},
|
||||
/// Mail that has not been handled properly end up in the error queue.
|
||||
ErrorQueue {
|
||||
#[structopt(subcommand)]
|
||||
cmd: ErrorQueueCommand,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
enum ErrorQueueCommand {
|
||||
/// List.
|
||||
List,
|
||||
/// Print entry in RFC5322 or JSON format.
|
||||
Print {
|
||||
/// index of entry.
|
||||
#[structopt(long)]
|
||||
index: Vec<i64>,
|
||||
/// JSON format.
|
||||
#[structopt(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Delete entry and print it in stdout.
|
||||
Delete {
|
||||
/// index of entry.
|
||||
#[structopt(long)]
|
||||
index: Vec<i64>,
|
||||
/// Do not print in stdout.
|
||||
#[structopt(long)]
|
||||
quiet: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
@ -533,6 +562,66 @@ fn run_app(opt: Opt) -> Result<()> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ErrorQueue { cmd } => match cmd {
|
||||
ErrorQueueCommand::List => {
|
||||
let db = Database::open_or_create_db()?;
|
||||
let errors = db.error_queue()?;
|
||||
if errors.is_empty() {
|
||||
println!("Error queue is empty.");
|
||||
} else {
|
||||
for e in errors {
|
||||
println!(
|
||||
"- {} {} {} {} {}",
|
||||
e["pk"],
|
||||
e["datetime"],
|
||||
e["from_address"],
|
||||
e["to_address"],
|
||||
e["subject"]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ErrorQueueCommand::Print { index, json } => {
|
||||
let db = Database::open_or_create_db()?;
|
||||
let mut errors = db.error_queue()?;
|
||||
if !index.is_empty() {
|
||||
errors.retain(|el| index.contains(&el.pk()));
|
||||
}
|
||||
if errors.is_empty() {
|
||||
println!("Error queue is empty.");
|
||||
} else {
|
||||
for e in errors {
|
||||
if json {
|
||||
println!("{:#}", e);
|
||||
} else {
|
||||
println!("{}", e["message"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ErrorQueueCommand::Delete { index, quiet } => {
|
||||
let mut db = Database::open_or_create_db()?;
|
||||
let mut errors = db.error_queue()?;
|
||||
if !index.is_empty() {
|
||||
errors.retain(|el| index.contains(&el.pk()));
|
||||
}
|
||||
if errors.is_empty() {
|
||||
if !quiet {
|
||||
println!("Error queue is empty.");
|
||||
}
|
||||
} else {
|
||||
if !quiet {
|
||||
println!("Deleting error queue elements {:?}", &index);
|
||||
}
|
||||
db.delete_from_error_queue(index)?;
|
||||
if !quiet {
|
||||
for e in errors {
|
||||
println!("{}", e["message"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -34,6 +34,9 @@ pub struct Database {
|
|||
pub connection: DbConnection,
|
||||
}
|
||||
|
||||
mod error_queue;
|
||||
pub use error_queue::*;
|
||||
|
||||
impl Database {
|
||||
pub fn db_path() -> Result<PathBuf> {
|
||||
let mut config_path = None;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This file is part of mailpot
|
||||
*
|
||||
* Copyright 2020 - Manos Pitsidianakis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use super::*;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
impl Database {
|
||||
pub fn error_queue(&self) -> Result<Vec<DbVal<Value>>> {
|
||||
let mut stmt = self.connection.prepare("SELECT * FROM error_queue;")?;
|
||||
let error_iter = stmt.query_map([], |row| {
|
||||
let pk = row.get::<_, i64>("pk")?;
|
||||
Ok(DbVal(
|
||||
json!({
|
||||
"pk" : pk,
|
||||
"to_address": row.get::<_, String>("to_address")?,
|
||||
"from_address": row.get::<_, String>("from_address")?,
|
||||
"subject": row.get::<_, String>("subject")?,
|
||||
"message_id": row.get::<_, String>("message_id")?,
|
||||
"message": row.get::<_, String>("message")?,
|
||||
"timestamp": row.get::<_, String>("timestamp")?,
|
||||
"datetime": row.get::<_, String>("datetime")?,
|
||||
}),
|
||||
pk,
|
||||
))
|
||||
})?;
|
||||
|
||||
let mut ret = vec![];
|
||||
for error in error_iter {
|
||||
let error = error?;
|
||||
ret.push(error);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn delete_from_error_queue(&mut self, index: Vec<i64>) -> Result<()> {
|
||||
let tx = self.connection.transaction()?;
|
||||
|
||||
if index.is_empty() {
|
||||
tx.execute("DELETE FROM error_queue;", [])?;
|
||||
} else {
|
||||
for i in index {
|
||||
tx.execute(
|
||||
"DELETE FROM error_queue WHERE pk = ?;",
|
||||
rusqlite::params![i],
|
||||
)?;
|
||||
}
|
||||
};
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -82,6 +82,17 @@ CREATE TABLE IF NOT EXISTS post_event (
|
|||
FOREIGN KEY (post) REFERENCES post(pk) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS error_queue (
|
||||
pk INTEGER PRIMARY KEY NOT NULL,
|
||||
to_address TEXT NOT NULL,
|
||||
from_address TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
message_id TEXT NOT NULL,
|
||||
message BLOB NOT NULL,
|
||||
timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
|
||||
datetime TEXT NOT NULL DEFAULT (datetime())
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS post_listpk_idx ON post(list);
|
||||
CREATE INDEX IF NOT EXISTS post_msgid_idx ON post(message_id);
|
||||
CREATE INDEX IF NOT EXISTS mailing_lists_idx ON mailing_lists(id);
|
||||
|
|
|
@ -86,6 +86,17 @@ CREATE TABLE IF NOT EXISTS post_event (
|
|||
FOREIGN KEY (post) REFERENCES post(pk) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS error_queue (
|
||||
pk INTEGER PRIMARY KEY NOT NULL,
|
||||
to_address TEXT NOT NULL,
|
||||
from_address TEXT NOT NULL,
|
||||
subject TEXT NOT NULL,
|
||||
message_id TEXT NOT NULL,
|
||||
message BLOB NOT NULL,
|
||||
timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
|
||||
datetime TEXT NOT NULL DEFAULT (datetime())
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS post_listpk_idx ON post(list);
|
||||
CREATE INDEX IF NOT EXISTS post_msgid_idx ON post(message_id);
|
||||
CREATE INDEX IF NOT EXISTS mailing_lists_idx ON mailing_lists(id);
|
||||
|
|
Loading…
Reference in New Issue