From 2f939cb1046a2acf6258130838c1ce6ff2d231fa Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 8 May 2022 02:51:25 +0300 Subject: [PATCH] Add archive-http crate Closes #3 --- Cargo.lock | 222 ++++++++++++++++++++++------- Cargo.toml | 1 + archive-http/Cargo.toml | 23 +++ archive-http/README.md | 5 + archive-http/src/main.rs | 111 +++++++++++++++ archive-http/templates/css.html | 0 archive-http/templates/footer.html | 3 + archive-http/templates/header.html | 11 ++ archive-http/templates/index.html | 8 ++ archive-http/templates/list.html | 14 ++ archive-http/templates/menu.html | 0 archive-http/templates/post.html | 10 ++ cli/src/main.rs | 3 + core/Cargo.toml | 2 +- core/src/db.rs | 117 ++++++++++----- core/src/models.rs | 17 +++ core/src/schema.sql | 3 +- core/src/schema.sql.m4 | 3 +- 18 files changed, 462 insertions(+), 91 deletions(-) create mode 100644 archive-http/Cargo.toml create mode 100644 archive-http/README.md create mode 100644 archive-http/src/main.rs create mode 100644 archive-http/templates/css.html create mode 100644 archive-http/templates/footer.html create mode 100644 archive-http/templates/header.html create mode 100644 archive-http/templates/index.html create mode 100644 archive-http/templates/list.html create mode 100644 archive-http/templates/menu.html create mode 100644 archive-http/templates/post.html diff --git a/Cargo.lock b/Cargo.lock index 01afcbe..7474983 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom", "once_cell", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -37,6 +37,50 @@ dependencies = [ "winapi", ] +[[package]] +name = "askama" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dc2a4b6d7f812d2b13d251ae792caecebd635d6401761162d4b71d5ebe1a010" +dependencies = [ + "askama_derive", + "askama_escape", + "askama_shared", +] + +[[package]] +name = "askama_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ee2fff0f22ad5d215cace1227cd036c28e81e26206763bb837b6d0e766c87d" +dependencies = [ + "askama_shared", + "nom 4.2.3", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "askama_escape" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0de942230b5beedaa9e1d64df5b76fa1c97002e4c7982897be899cccf40621d" + +[[package]] +name = "askama_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6dfa6b6d254fd066a8bbed9a8f913123e3f701db89216ad4f0aff04ad87718c" +dependencies = [ + "askama_escape", + "humansize", + "num-traits", + "serde", + "serde_derive", + "toml 0.4.10", +] + [[package]] name = "async-channel" version = "1.6.1" @@ -145,9 +189,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -494,7 +538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ "backtrace", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -624,9 +668,9 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -666,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -800,6 +844,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humansize" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" + [[package]] name = "hyper" version = "0.14.18" @@ -898,6 +948,7 @@ version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" dependencies = [ + "cc", "pkg-config", "vcpkg", ] @@ -930,7 +981,7 @@ dependencies = [ "base64", "either", "log", - "nom", + "nom 7.1.1", "ternop", ] @@ -963,7 +1014,7 @@ dependencies = [ "serde_json", "stderrlog", "tempfile", - "toml", + "toml 0.5.9", "xdg", ] @@ -1009,7 +1060,7 @@ dependencies = [ "libloading", "native-tls", "nix", - "nom", + "nom 7.1.1", "serde", "serde_derive", "smallvec", @@ -1089,6 +1140,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "mpot-archives" +version = "0.1.0" +dependencies = [ + "askama", + "mailpot", + "percent-encoding", + "tokio", + "warp", +] + [[package]] name = "multipart" version = "0.18.0" @@ -1137,6 +1199,16 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check 0.1.5", +] + [[package]] name = "nom" version = "7.1.1" @@ -1289,9 +1361,9 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1338,10 +1410,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", + "version_check 0.9.4", ] [[package]] @@ -1350,9 +1422,18 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "proc-macro2 1.0.37", + "quote 1.0.18", + "version_check 0.9.4", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", ] [[package]] @@ -1361,7 +1442,7 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.3", ] [[package]] @@ -1370,13 +1451,22 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.37", ] [[package]] @@ -1583,9 +1673,9 @@ version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1747,9 +1837,20 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", ] [[package]] @@ -1758,9 +1859,9 @@ version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.37", + "quote 1.0.18", + "unicode-xid 0.2.3", ] [[package]] @@ -1816,9 +1917,9 @@ version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1881,9 +1982,9 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -1938,6 +2039,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.5.9" @@ -1972,9 +2082,9 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", ] [[package]] @@ -2032,7 +2142,7 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check", + "version_check 0.9.4", ] [[package]] @@ -2062,6 +2172,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.3" @@ -2115,6 +2231,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.4" @@ -2198,9 +2320,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-shared", ] @@ -2210,7 +2332,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote", + "quote 1.0.18", "wasm-bindgen-macro-support", ] @@ -2220,9 +2342,9 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.37", + "quote 1.0.18", + "syn 1.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index fd216ce..c867f8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,5 @@ members = [ "core", "cli", "rest-http", + "archive-http", ] diff --git a/archive-http/Cargo.toml b/archive-http/Cargo.toml new file mode 100644 index 0000000..5e855d3 --- /dev/null +++ b/archive-http/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "mpot-archives" +version = "0.1.0" +authors = ["Manos Pitsidianakis "] +edition = "2018" +license = "LICENSE" +readme = "README.md" +description = "mailing list manager" +repository = "https://github.com/meli/mailpot" +keywords = ["mail", "mailing-lists" ] +categories = ["email"] +default-run = "mpot-archives" + +[[bin]] +name = "mpot-archives" +path = "src/main.rs" + +[dependencies] +mailpot = { version = "0.1.0", path = "../core" } +tokio = { version = "1", features = ["full"] } +askama = "0.8" +warp = "0.3" +percent-encoding = "2.1" diff --git a/archive-http/README.md b/archive-http/README.md new file mode 100644 index 0000000..63a4750 --- /dev/null +++ b/archive-http/README.md @@ -0,0 +1,5 @@ +# mailpot REST http server + +```shell +cargo run --bin mpot-http +``` diff --git a/archive-http/src/main.rs b/archive-http/src/main.rs new file mode 100644 index 0000000..9e8ae59 --- /dev/null +++ b/archive-http/src/main.rs @@ -0,0 +1,111 @@ +/* + * 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 . + */ + +extern crate mailpot; + +pub use mailpot::config::*; +pub use mailpot::db::*; +pub use mailpot::errors::*; +pub use mailpot::models::*; +pub use mailpot::*; + +use askama::Template; +use percent_encoding::percent_decode_str; +use warp::reject; + +#[derive(Template)] +#[template(path = "list.html")] +struct ListTemplate<'a> { + title: &'a str, + list: &'a DbVal, + posts: Vec>, + body: &'a str, +} + +#[derive(Template)] +#[template(path = "post.html")] +struct PostTemplate<'a> { + title: &'a str, + list: &'a DbVal, + post: DbVal, + body: &'a str, + from: &'a str, + to: &'a str, + subject: &'a str, + in_reply_to: Option, + references: Vec, +} + +use warp::Filter; +#[tokio::main] +async fn main() { + let list_handler = warp::path!("lists" / i64).map(|list_pk: i64| { + let db = Database::open_or_create_db().unwrap(); + let list = db.get_list(list_pk).unwrap().unwrap(); + let posts = db.list_posts(list_pk, None).unwrap(); + let template = ListTemplate { + title: &list.name, + list: &list, + posts, + body: &list.description.clone().unwrap_or_default(), + }; + let res = template.render().unwrap(); + Ok(warp::reply::html(res)) + }); + let post_handler = + warp::path!("list" / i64 / String).map(|list_pk: i64, message_id: String| { + let message_id = percent_decode_str(&message_id).decode_utf8().unwrap(); + let db = Database::open_or_create_db().unwrap(); + let list = db.get_list(list_pk).unwrap().unwrap(); + let posts = db.list_posts(list_pk, None).unwrap(); + let post = posts + .into_iter() + .find(|p| message_id.contains(&p.message_id)) + .unwrap(); + let envelope = melib::Envelope::from_bytes(post.message.as_slice(), None) + .expect("Could not parse mail"); + let body = envelope.body_bytes(post.message.as_slice()); + let body_text = body.text(); + let template = PostTemplate { + title: &list.name, + list: &list, + post, + body: &body_text, + from: &envelope.field_from_to_string(), + to: &envelope.field_to_to_string(), + subject: &envelope.subject(), + in_reply_to: envelope.in_reply_to_display().map(|r| r.to_string()), + references: envelope + .references() + .into_iter() + .map(|m| m.to_string()) + .collect::>(), + }; + let res = template.render().unwrap(); + Ok(warp::reply::html(res)) + }); + let routes = warp::get().and(list_handler).or(post_handler); + + // Note that composing filters for many routes may increase compile times (because it uses a lot of generics). + // If you wish to use dynamic dispatch instead and speed up compile times while + // making it slightly slower at runtime, you can use Filter::boxed(). + + eprintln!("Running at 127.0.0.1:3030"); + warp::serve(routes).run(([127, 0, 0, 1], 3030)).await; +} diff --git a/archive-http/templates/css.html b/archive-http/templates/css.html new file mode 100644 index 0000000..e69de29 diff --git a/archive-http/templates/footer.html b/archive-http/templates/footer.html new file mode 100644 index 0000000..3a4f73d --- /dev/null +++ b/archive-http/templates/footer.html @@ -0,0 +1,3 @@ + + + diff --git a/archive-http/templates/header.html b/archive-http/templates/header.html new file mode 100644 index 0000000..3b70a86 --- /dev/null +++ b/archive-http/templates/header.html @@ -0,0 +1,11 @@ + + + {{ title }} + {% include "css.html" %} + + +
+

{{ title }}

+
+ {% include "menu.html" %} +
diff --git a/archive-http/templates/index.html b/archive-http/templates/index.html new file mode 100644 index 0000000..ca60f33 --- /dev/null +++ b/archive-http/templates/index.html @@ -0,0 +1,8 @@ +{% include "header.html" %} +
+

{{title}}

+
+ {{body}} +
+
+{% include "footer.html" %} diff --git a/archive-http/templates/list.html b/archive-http/templates/list.html new file mode 100644 index 0000000..3a431ef --- /dev/null +++ b/archive-http/templates/list.html @@ -0,0 +1,14 @@ +{% include "header.html" %} +
+

{{title}}

+
+ {{body}} +

Posts

+ +
+
+{% include "footer.html" %} diff --git a/archive-http/templates/menu.html b/archive-http/templates/menu.html new file mode 100644 index 0000000..e69de29 diff --git a/archive-http/templates/post.html b/archive-http/templates/post.html new file mode 100644 index 0000000..3902aa2 --- /dev/null +++ b/archive-http/templates/post.html @@ -0,0 +1,10 @@ +{% include "header.html" %} +
+

{{subject}}

+
+
+        {{body}}
+      
+
+
+{% include "footer.html" %} diff --git a/cli/src/main.rs b/cli/src/main.rs index 7e8a9a0..8c4be63 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -452,6 +452,9 @@ fn run_app(opt: Opt) -> Result<()> { std::io::stdin().read_to_string(&mut input)?; match Envelope::from_bytes(input.as_bytes(), None) { Ok(env) => { + if opt.debug { + std::dbg!(&env); + } let db = Database::open_or_create_db()?; db.post(&env, input.as_bytes(), dry_run)?; } diff --git a/core/Cargo.toml b/core/Cargo.toml index 3e2704a..056a58a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -15,7 +15,7 @@ chrono = { version = "^0.4", features = ["serde", ] } error-chain = "0.12.4" #melib = { version = "*", default-features = false, features = ["smtp", "unicode_algorithms"], path="../../meli/melib", branch = "master" } melib = { version = "*", default-features = false, features = ["smtp", "unicode_algorithms"], git="https://github.com/meli/meli", branch = "master" } -rusqlite = {version = "^0.27" } +rusqlite = {version = "^0.27", features = ["bundled"] } serde = { version = "^1", features = ["derive", ]} serde_json = "^1" toml = "^0.5" diff --git a/core/src/db.rs b/core/src/db.rs index 0e571b1..1a3dbdd 100644 --- a/core/src/db.rs +++ b/core/src/db.rs @@ -142,6 +142,39 @@ impl Database { Ok(ret) } + pub fn list_posts( + &self, + list_pk: i64, + date_range: Option<(String, String)>, + ) -> Result>> { + let mut stmt = self + .connection + .prepare("SELECT * FROM post WHERE list = ?;")?; + let iter = stmt.query_map(rusqlite::params![&list_pk,], |row| { + let pk = row.get("pk")?; + Ok(DbVal( + Post { + pk, + list: row.get("list")?, + address: row.get("address")?, + message_id: row.get("message_id")?, + message: row.get("message")?, + timestamp: row.get("timestamp")?, + datetime: row.get("datetime")?, + }, + pk, + )) + })?; + let mut ret = vec![]; + for post in iter { + let post = post?; + ret.push(post); + } + + trace!("list_posts {:?}.", &ret); + Ok(ret) + } + pub fn update_list(&self, _change_set: MailingListChangeset) -> Result<()> { /* diesel::update(mailing_lists::table) @@ -416,13 +449,20 @@ impl Database { } pub fn insert_post(&self, list_pk: i64, message: &[u8], env: &Envelope) -> Result { - let address = env.from()[0].to_string(); + let address = env.from()[0].get_email(); let message_id = env.message_id_display(); let mut stmt = self.connection.prepare( - "INSERT INTO post(list, address, message_id, message) VALUES(?, ?, ?, ?) RETURNING pk;", + "INSERT INTO post(list, address, message_id, message, datetime, timestamp) VALUES(?, ?, ?, ?, ?, ?) RETURNING pk;", )?; let pk = stmt.query_row( - rusqlite::params![&list_pk, &address, &message_id, &message], + rusqlite::params![ + &list_pk, + &address, + &message_id, + &message, + &env.date, + &env.timestamp + ], |row| { let pk: i64 = row.get("pk")?; Ok(pk) @@ -530,51 +570,52 @@ impl Database { trace!("result {:#?}", result); let Post { bytes, action, .. } = post; - match configuration.send_mail { - crate::config::SendMail::Smtp(ref smtp_conf) => { - let smtp_conf = smtp_conf.clone(); - use melib::futures; - use melib::smol; - use melib::smtp::*; - let mut conn = smol::future::block_on(smol::spawn( - SmtpConnection::new_connection(smtp_conf.clone()), - ))?; - match action { - PostAction::Accept => { - let _post_pk = self.insert_post(list_ctx.list.pk, raw, env)?; - for job in list_ctx.scheduled_jobs.iter() { - if let crate::mail::MailJob::Send { recipients } = job { - if !recipients.is_empty() { - trace!("recipients: {:?}", &recipients); + match action { + PostAction::Accept => { + let _post_pk = self.insert_post(list_ctx.list.pk, raw, env)?; + for job in list_ctx.scheduled_jobs.iter() { + if let crate::mail::MailJob::Send { recipients } = job { + if !recipients.is_empty() { + trace!("recipients: {:?}", &recipients); + + match &configuration.send_mail { + crate::config::SendMail::Smtp(ref smtp_conf) => { + let smtp_conf = smtp_conf.clone(); + use melib::futures; + use melib::smol; + use melib::smtp::*; + let mut conn = smol::future::block_on(smol::spawn( + SmtpConnection::new_connection(smtp_conf.clone()), + ))?; futures::executor::block_on(conn.mail_transaction( &String::from_utf8_lossy(&bytes), Some(recipients), ))?; - } else { - trace!("list has no recipients"); } + _ => {} } + } else { + trace!("list has no recipients"); } - /* - FIXME Save digest metadata in database */ - } - PostAction::Reject { reason } => { - /* FIXME - Notify submitter */ - trace!("PostAction::Reject {{ reason: {} }}", reason); - //futures::executor::block_on(conn.mail_transaction(&post.bytes, b)).unwrap(); - return Err(crate::ErrorKind::PostRejected(reason).into()); - } - PostAction::Defer { reason } => { - trace!("PostAction::Defer {{ reason: {} }}", reason); - /* - FIXME Notify submitter - * - FIXME Save in database */ - } - PostAction::Hold => { - trace!("PostAction::Hold"); - /* FIXME - Save in database */ } } + /* - FIXME Save digest metadata in database */ + } + PostAction::Reject { reason } => { + /* FIXME - Notify submitter */ + trace!("PostAction::Reject {{ reason: {} }}", reason); + //futures::executor::block_on(conn.mail_transaction(&post.bytes, b)).unwrap(); + return Err(crate::ErrorKind::PostRejected(reason).into()); + } + PostAction::Defer { reason } => { + trace!("PostAction::Defer {{ reason: {} }}", reason); + /* - FIXME Notify submitter + * - FIXME Save in database */ + } + PostAction::Hold => { + trace!("PostAction::Hold"); + /* FIXME - Save in database */ } - _ => {} } } diff --git a/core/src/models.rs b/core/src/models.rs index 1f33a0e..afabf15 100644 --- a/core/src/models.rs +++ b/core/src/models.rs @@ -240,3 +240,20 @@ pub struct NewListPost<'s> { pub message_id: &'s str, pub message: &'s [u8], } + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +pub struct Post { + pub pk: i64, + pub list: i64, + pub address: String, + pub message_id: String, + pub message: Vec, + pub timestamp: u64, + pub datetime: String, +} + +impl std::fmt::Display for Post { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{:?}", self) + } +} diff --git a/core/src/schema.sql b/core/src/schema.sql index 81d200b..4ceaa3a 100644 --- a/core/src/schema.sql +++ b/core/src/schema.sql @@ -58,7 +58,8 @@ CREATE TABLE IF NOT EXISTS post ( address TEXT NOT NULL, message_id TEXT NOT NULL, message BLOB NOT NULL, - FOREIGN KEY (list, address) REFERENCES membership(list, address) ON DELETE CASCADE + timestamp INTEGER NOT NULL DEFAULT (unixepoch()), + datetime TEXT NOT NULL DEFAULT (datetime()) ); CREATE TABLE IF NOT EXISTS post_event ( diff --git a/core/src/schema.sql.m4 b/core/src/schema.sql.m4 index 344e8a0..76c6cfa 100644 --- a/core/src/schema.sql.m4 +++ b/core/src/schema.sql.m4 @@ -62,7 +62,8 @@ CREATE TABLE IF NOT EXISTS post ( address TEXT NOT NULL, message_id TEXT NOT NULL, message BLOB NOT NULL, - FOREIGN KEY (list, address) REFERENCES membership(list, address) ON DELETE CASCADE + timestamp INTEGER NOT NULL DEFAULT (unixepoch()), + datetime TEXT NOT NULL DEFAULT (datetime()) ); CREATE TABLE IF NOT EXISTS post_event (