Add archive-http crate

Closes  #3
pull/1/head
Manos Pitsidianakis 2022-05-08 02:51:25 +03:00
parent b401a52130
commit 2f939cb104
18 changed files with 462 additions and 91 deletions

222
Cargo.lock generated
View File

@ -25,7 +25,7 @@ checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"once_cell", "once_cell",
"version_check", "version_check 0.9.4",
] ]
[[package]] [[package]]
@ -37,6 +37,50 @@ dependencies = [
"winapi", "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]] [[package]]
name = "async-channel" name = "async-channel"
version = "1.6.1" version = "1.6.1"
@ -145,9 +189,9 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -494,7 +538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"version_check", "version_check 0.9.4",
] ]
[[package]] [[package]]
@ -624,9 +668,9 @@ version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -666,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [ dependencies = [
"typenum", "typenum",
"version_check", "version_check 0.9.4",
] ]
[[package]] [[package]]
@ -800,6 +844,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "humansize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.18" version = "0.14.18"
@ -898,6 +948,7 @@ version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14"
dependencies = [ dependencies = [
"cc",
"pkg-config", "pkg-config",
"vcpkg", "vcpkg",
] ]
@ -930,7 +981,7 @@ dependencies = [
"base64", "base64",
"either", "either",
"log", "log",
"nom", "nom 7.1.1",
"ternop", "ternop",
] ]
@ -963,7 +1014,7 @@ dependencies = [
"serde_json", "serde_json",
"stderrlog", "stderrlog",
"tempfile", "tempfile",
"toml", "toml 0.5.9",
"xdg", "xdg",
] ]
@ -1009,7 +1060,7 @@ dependencies = [
"libloading", "libloading",
"native-tls", "native-tls",
"nix", "nix",
"nom", "nom 7.1.1",
"serde", "serde",
"serde_derive", "serde_derive",
"smallvec", "smallvec",
@ -1089,6 +1140,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "mpot-archives"
version = "0.1.0"
dependencies = [
"askama",
"mailpot",
"percent-encoding",
"tokio",
"warp",
]
[[package]] [[package]]
name = "multipart" name = "multipart"
version = "0.18.0" version = "0.18.0"
@ -1137,6 +1199,16 @@ dependencies = [
"memoffset", "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]] [[package]]
name = "nom" name = "nom"
version = "7.1.1" version = "7.1.1"
@ -1289,9 +1361,9 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -1338,10 +1410,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [ dependencies = [
"proc-macro-error-attr", "proc-macro-error-attr",
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
"version_check", "version_check 0.9.4",
] ]
[[package]] [[package]]
@ -1350,9 +1422,18 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"version_check", "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]] [[package]]
@ -1361,7 +1442,7 @@ version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid 0.2.3",
] ]
[[package]] [[package]]
@ -1370,13 +1451,22 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 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]] [[package]]
name = "quote" name = "quote"
version = "1.0.18" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
] ]
[[package]] [[package]]
@ -1583,9 +1673,9 @@ version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -1747,9 +1837,20 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "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]] [[package]]
@ -1758,9 +1859,9 @@ version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"unicode-xid", "unicode-xid 0.2.3",
] ]
[[package]] [[package]]
@ -1816,9 +1917,9 @@ version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -1881,9 +1982,9 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -1938,6 +2039,15 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "toml"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.9" version = "0.5.9"
@ -1972,9 +2082,9 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
] ]
[[package]] [[package]]
@ -2032,7 +2142,7 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [ dependencies = [
"version_check", "version_check 0.9.4",
] ]
[[package]] [[package]]
@ -2062,6 +2172,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.3" version = "0.2.3"
@ -2115,6 +2231,12 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.4" version = "0.9.4"
@ -2198,9 +2320,9 @@ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
"log", "log",
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -2210,7 +2332,7 @@ version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
dependencies = [ dependencies = [
"quote", "quote 1.0.18",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
] ]
@ -2220,9 +2342,9 @@ version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2 1.0.37",
"quote", "quote 1.0.18",
"syn", "syn 1.0.92",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@ -3,4 +3,5 @@ members = [
"core", "core",
"cli", "cli",
"rest-http", "rest-http",
"archive-http",
] ]

View File

@ -0,0 +1,23 @@
[package]
name = "mpot-archives"
version = "0.1.0"
authors = ["Manos Pitsidianakis <el13635@mail.ntua.gr>"]
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"

View File

@ -0,0 +1,5 @@
# mailpot REST http server
```shell
cargo run --bin mpot-http
```

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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<MailingList>,
posts: Vec<DbVal<Post>>,
body: &'a str,
}
#[derive(Template)]
#[template(path = "post.html")]
struct PostTemplate<'a> {
title: &'a str,
list: &'a DbVal<MailingList>,
post: DbVal<Post>,
body: &'a str,
from: &'a str,
to: &'a str,
subject: &'a str,
in_reply_to: Option<String>,
references: Vec<String>,
}
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::<Vec<String>>(),
};
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;
}

View File

View File

@ -0,0 +1,3 @@
</body>
</html>

View File

@ -0,0 +1,11 @@
<html>
<head>
<title>{{ title }}</title>
{% include "css.html" %}
</head>
<body>
<div>
<h1>{{ title }}</h1>
</div>
{% include "menu.html" %}
<hr />

View File

@ -0,0 +1,8 @@
{% include "header.html" %}
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
{% include "footer.html" %}

View File

@ -0,0 +1,14 @@
{% include "header.html" %}
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
<h2>Posts</h2>
<ul>
{% for post in posts %}
<li><a href="/list/{{post.list}}/{{ post.message_id }}">{{ post.address }} {{ post.datetime }} {{ post.message_id }}</a></li>
{% endfor %}
</ul>
</div>
</div>
{% include "footer.html" %}

View File

View File

@ -0,0 +1,10 @@
{% include "header.html" %}
<div class="entry">
<h1>{{subject}}</h1>
<div class="body">
<pre>
{{body}}
</pre>
</div>
</div>
{% include "footer.html" %}

View File

@ -452,6 +452,9 @@ fn run_app(opt: Opt) -> Result<()> {
std::io::stdin().read_to_string(&mut input)?; std::io::stdin().read_to_string(&mut input)?;
match Envelope::from_bytes(input.as_bytes(), None) { match Envelope::from_bytes(input.as_bytes(), None) {
Ok(env) => { Ok(env) => {
if opt.debug {
std::dbg!(&env);
}
let db = Database::open_or_create_db()?; let db = Database::open_or_create_db()?;
db.post(&env, input.as_bytes(), dry_run)?; db.post(&env, input.as_bytes(), dry_run)?;
} }

View File

@ -15,7 +15,7 @@ chrono = { version = "^0.4", features = ["serde", ] }
error-chain = "0.12.4" 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"], path="../../meli/melib", branch = "master" }
melib = { version = "*", default-features = false, features = ["smtp", "unicode_algorithms"], git="https://github.com/meli/meli", 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 = { version = "^1", features = ["derive", ]}
serde_json = "^1" serde_json = "^1"
toml = "^0.5" toml = "^0.5"

View File

@ -142,6 +142,39 @@ impl Database {
Ok(ret) Ok(ret)
} }
pub fn list_posts(
&self,
list_pk: i64,
date_range: Option<(String, String)>,
) -> Result<Vec<DbVal<Post>>> {
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<()> { pub fn update_list(&self, _change_set: MailingListChangeset) -> Result<()> {
/* /*
diesel::update(mailing_lists::table) diesel::update(mailing_lists::table)
@ -416,13 +449,20 @@ impl Database {
} }
pub fn insert_post(&self, list_pk: i64, message: &[u8], env: &Envelope) -> Result<i64> { pub fn insert_post(&self, list_pk: i64, message: &[u8], env: &Envelope) -> Result<i64> {
let address = env.from()[0].to_string(); let address = env.from()[0].get_email();
let message_id = env.message_id_display(); let message_id = env.message_id_display();
let mut stmt = self.connection.prepare( 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( 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| { |row| {
let pk: i64 = row.get("pk")?; let pk: i64 = row.get("pk")?;
Ok(pk) Ok(pk)
@ -530,51 +570,52 @@ impl Database {
trace!("result {:#?}", result); trace!("result {:#?}", result);
let Post { bytes, action, .. } = post; let Post { bytes, action, .. } = post;
match configuration.send_mail { match action {
crate::config::SendMail::Smtp(ref smtp_conf) => { PostAction::Accept => {
let smtp_conf = smtp_conf.clone(); let _post_pk = self.insert_post(list_ctx.list.pk, raw, env)?;
use melib::futures; for job in list_ctx.scheduled_jobs.iter() {
use melib::smol; if let crate::mail::MailJob::Send { recipients } = job {
use melib::smtp::*; if !recipients.is_empty() {
let mut conn = smol::future::block_on(smol::spawn( trace!("recipients: {:?}", &recipients);
SmtpConnection::new_connection(smtp_conf.clone()),
))?; match &configuration.send_mail {
match action { crate::config::SendMail::Smtp(ref smtp_conf) => {
PostAction::Accept => { let smtp_conf = smtp_conf.clone();
let _post_pk = self.insert_post(list_ctx.list.pk, raw, env)?; use melib::futures;
for job in list_ctx.scheduled_jobs.iter() { use melib::smol;
if let crate::mail::MailJob::Send { recipients } = job { use melib::smtp::*;
if !recipients.is_empty() { let mut conn = smol::future::block_on(smol::spawn(
trace!("recipients: {:?}", &recipients); SmtpConnection::new_connection(smtp_conf.clone()),
))?;
futures::executor::block_on(conn.mail_transaction( futures::executor::block_on(conn.mail_transaction(
&String::from_utf8_lossy(&bytes), &String::from_utf8_lossy(&bytes),
Some(recipients), 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 */
} }
_ => {}
} }
} }

View File

@ -240,3 +240,20 @@ pub struct NewListPost<'s> {
pub message_id: &'s str, pub message_id: &'s str,
pub message: &'s [u8], 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<u8>,
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)
}
}

View File

@ -58,7 +58,8 @@ CREATE TABLE IF NOT EXISTS post (
address TEXT NOT NULL, address TEXT NOT NULL,
message_id TEXT NOT NULL, message_id TEXT NOT NULL,
message BLOB 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 ( CREATE TABLE IF NOT EXISTS post_event (

View File

@ -62,7 +62,8 @@ CREATE TABLE IF NOT EXISTS post (
address TEXT NOT NULL, address TEXT NOT NULL,
message_id TEXT NOT NULL, message_id TEXT NOT NULL,
message BLOB 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 ( CREATE TABLE IF NOT EXISTS post_event (