add mail #108
216
Cargo.lock
generated
216
Cargo.lock
generated
@ -333,6 +333,16 @@ dependencies = [
|
|||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chumsky"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"stacker",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cipher"
|
name = "cipher"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -366,6 +376,16 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
@ -554,6 +574,22 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email-encoding"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email_address"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
@ -664,6 +700,21 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -948,6 +999,17 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hostname"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"match_cfg",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@ -1186,6 +1248,31 @@ dependencies = [
|
|||||||
"spin 0.5.2",
|
"spin 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lettre"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a48c2e9831b370bc2d7233c2620298c45f3a158ed6b4b8d7416b2ada5a268fd8"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"chumsky",
|
||||||
|
"email-encoding",
|
||||||
|
"email_address",
|
||||||
|
"fastrand",
|
||||||
|
"futures-util",
|
||||||
|
"hostname",
|
||||||
|
"httpdate",
|
||||||
|
"idna",
|
||||||
|
"mime",
|
||||||
|
"native-tls",
|
||||||
|
"nom",
|
||||||
|
"once_cell",
|
||||||
|
"quoted_printable",
|
||||||
|
"socket2",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.151"
|
version = "0.2.151"
|
||||||
@ -1246,6 +1333,12 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "match_cfg"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -1333,6 +1426,24 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.27.1"
|
version = "0.27.1"
|
||||||
@ -1471,6 +1582,50 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.62"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.42",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1732,6 +1887,15 @@ dependencies = [
|
|||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psm"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pure-rust-locales"
|
name = "pure-rust-locales"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -1747,6 +1911,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quoted_printable"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -1968,6 +2138,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"futures",
|
"futures",
|
||||||
"ics",
|
"ics",
|
||||||
|
"lettre",
|
||||||
"log",
|
"log",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_dyn_templates",
|
"rocket_dyn_templates",
|
||||||
@ -2067,6 +2238,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -2089,6 +2269,29 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.193"
|
version = "1.0.193"
|
||||||
@ -2473,6 +2676,19 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stacker"
|
||||||
|
version = "0.1.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"psm",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "state"
|
name = "state"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -22,3 +22,5 @@ chrono-tz = "0.8"
|
|||||||
tera = { version = "1.18", features = ["date-locale"], optional = true}
|
tera = { version = "1.18", features = ["date-locale"], optional = true}
|
||||||
ics = "0.5"
|
ics = "0.5"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
lettre = "0.11"
|
||||||
|
|
||||||
|
@ -2,3 +2,4 @@
|
|||||||
secret_key = "/NtVGizglEoyoxBLzsRDWTy4oAG1qDw4J4O+CWJSv+fypD7W9sam8hUY4j90EZsbZk8wEradS5zBoWtWKi3k8w=="
|
secret_key = "/NtVGizglEoyoxBLzsRDWTy4oAG1qDw4J4O+CWJSv+fypD7W9sam8hUY4j90EZsbZk8wEradS5zBoWtWKi3k8w=="
|
||||||
rss_key = "rss-key-for-ci"
|
rss_key = "rss-key-for-ci"
|
||||||
limits = { file = "10 MiB", data-form = "10 MiB"}
|
limits = { file = "10 MiB", data-form = "10 MiB"}
|
||||||
|
smtp_pw = "8kIjlLH79Ky6D3jQ"
|
||||||
|
65
src/model/mail.rs
Normal file
65
src/model/mail.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use lettre::{
|
||||||
|
message::{
|
||||||
|
header::{self, ContentType},
|
||||||
|
MultiPart, SinglePart,
|
||||||
|
},
|
||||||
|
transport::smtp::authentication::Credentials,
|
||||||
|
Message, SmtpTransport, Transport,
|
||||||
|
};
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
use crate::tera::admin::mail::MailToSend;
|
||||||
|
|
||||||
|
use super::role::Role;
|
||||||
|
|
||||||
|
pub struct Mail {}
|
||||||
|
|
||||||
|
impl Mail {
|
||||||
|
pub async fn send(db: &SqlitePool, data: MailToSend<'_>, smtp_pw: String) -> bool {
|
||||||
|
let mut email = Message::builder()
|
||||||
|
.from(
|
||||||
|
"ASKÖ Ruderverein Donau Linz <no-reply@rudernlinz.at>"
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.reply_to(
|
||||||
|
"ASKÖ Ruderverein Donau Linz <info@rudernlinz.at>"
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.to("ASKÖ Ruderverein Donau Linz <no-reply@rudernlinz.at>"
|
||||||
|
.parse()
|
||||||
|
.unwrap());
|
||||||
|
let role = Role::find_by_id(db, data.role_id).await.unwrap();
|
||||||
|
for rec in role.mails_from_role(db).await {
|
||||||
|
let splitted = rec.split(',');
|
||||||
|
for single_rec in splitted {
|
||||||
|
email = email.bcc(single_rec.parse().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle attachments
|
||||||
|
|
||||||
|
let email = email
|
||||||
|
.subject(data.subject)
|
||||||
|
.header(ContentType::TEXT_PLAIN)
|
||||||
|
.body(String::from(data.body))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let creds = Credentials::new("no-reply@rudernlinz.at".to_owned(), smtp_pw);
|
||||||
|
|
||||||
|
let mailer = SmtpTransport::relay("mail.your-server.de")
|
||||||
|
.unwrap()
|
||||||
|
.credentials(creds)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Send the email
|
||||||
|
match mailer.send(&email) {
|
||||||
|
Ok(_) => return true,
|
||||||
|
Err(e) => println!("{:?}", e.source()),
|
||||||
|
};
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ pub mod location;
|
|||||||
pub mod log;
|
pub mod log;
|
||||||
pub mod logbook;
|
pub mod logbook;
|
||||||
pub mod logtype;
|
pub mod logtype;
|
||||||
|
pub mod mail;
|
||||||
pub mod planned_event;
|
pub mod planned_event;
|
||||||
pub mod role;
|
pub mod role;
|
||||||
pub mod rower;
|
pub mod rower;
|
||||||
|
@ -14,4 +14,32 @@ impl Role {
|
|||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn find_by_id(db: &SqlitePool, name: i32) -> Option<Self> {
|
||||||
|
sqlx::query_as!(
|
||||||
|
Self,
|
||||||
|
"
|
||||||
|
SELECT id, name
|
||||||
|
FROM role
|
||||||
|
WHERE id like ?
|
||||||
|
",
|
||||||
|
name
|
||||||
|
)
|
||||||
|
.fetch_one(db)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn mails_from_role(&self, db: &SqlitePool) -> Vec<String> {
|
||||||
|
let query = format!(
|
||||||
|
"SELECT u.mail
|
||||||
|
FROM user u
|
||||||
|
JOIN user_role ur ON u.id = ur.user_id
|
||||||
|
JOIN role r ON ur.role_id = r.id
|
||||||
|
WHERE r.id = {}",
|
||||||
|
self.id
|
||||||
|
);
|
||||||
|
|
||||||
|
sqlx::query_scalar(&query).fetch_all(db).await.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
64
src/tera/admin/mail.rs
Normal file
64
src/tera/admin/mail.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use rocket::form::Form;
|
||||||
|
use rocket::fs::TempFile;
|
||||||
|
use rocket::response::{Flash, Redirect};
|
||||||
|
use rocket::{get, request::FlashMessage, routes, Route, State};
|
||||||
|
use rocket::{post, FromForm};
|
||||||
|
use rocket_dyn_templates::{tera::Context, Template};
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
use crate::model::mail::Mail;
|
||||||
|
use crate::model::role::Role;
|
||||||
|
use crate::model::user::AdminUser;
|
||||||
|
use crate::model::user::UserWithRoles;
|
||||||
|
use crate::tera::Config;
|
||||||
|
|
||||||
|
#[get("/mail")]
|
||||||
|
async fn index(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
admin: AdminUser,
|
||||||
|
flash: Option<FlashMessage<'_>>,
|
||||||
|
) -> Template {
|
||||||
|
let mut context = Context::new();
|
||||||
|
if let Some(msg) = flash {
|
||||||
|
context.insert("flash", &msg.into_inner());
|
||||||
|
}
|
||||||
|
let roles = Role::all(db).await;
|
||||||
|
|
||||||
|
context.insert(
|
||||||
|
"loggedin_user",
|
||||||
|
&UserWithRoles::from_user(admin.user, db).await,
|
||||||
|
);
|
||||||
|
context.insert("roles", &roles);
|
||||||
|
|
||||||
|
Template::render("admin/mail", context.into_json())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm, Debug)]
|
||||||
|
pub struct MailToSend<'a> {
|
||||||
|
pub(crate) role_id: i32,
|
||||||
|
pub(crate) subject: String,
|
||||||
|
pub(crate) body: String,
|
||||||
|
pub(crate) files: Vec<TempFile<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/mail", data = "<data>")]
|
||||||
|
async fn update(
|
||||||
|
db: &State<SqlitePool>,
|
||||||
|
data: Form<MailToSend<'_>>,
|
||||||
|
config: &State<Config>,
|
||||||
|
_admin: AdminUser,
|
||||||
|
) -> Flash<Redirect> {
|
||||||
|
let d = data.into_inner();
|
||||||
|
if Mail::send(db, d, config.smtp_pw.clone()).await {
|
||||||
|
return Flash::success(Redirect::to("/admin/mail"), "Mail versendet");
|
||||||
|
} else {
|
||||||
|
return Flash::error(Redirect::to("/admin/mail"), "Fehler");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn routes() -> Vec<Route> {
|
||||||
|
routes![index, update]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {}
|
@ -7,6 +7,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub mod boat;
|
pub mod boat;
|
||||||
|
pub mod mail;
|
||||||
pub mod planned_event;
|
pub mod planned_event;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ pub fn routes() -> Vec<Route> {
|
|||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
ret.append(&mut user::routes());
|
ret.append(&mut user::routes());
|
||||||
ret.append(&mut boat::routes());
|
ret.append(&mut boat::routes());
|
||||||
|
ret.append(&mut mail::routes());
|
||||||
ret.append(&mut planned_event::routes());
|
ret.append(&mut planned_event::routes());
|
||||||
ret.append(&mut routes![rss, show_rss]);
|
ret.append(&mut routes![rss, show_rss]);
|
||||||
ret
|
ret
|
||||||
|
@ -206,6 +206,7 @@ fn unauthorized_error() -> Redirect {
|
|||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
rss_key: String,
|
rss_key: String,
|
||||||
|
smtp_pw: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(rocket: Rocket<Build>) -> Rocket<Build> {
|
pub fn config(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
|
27
templates/admin/mail.html.tera
Normal file
27
templates/admin/mail.html.tera
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{% import "includes/macros" as macros %}
|
||||||
|
{% import "includes/forms/boat" as boat %}
|
||||||
|
|
||||||
|
{% extends "base" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if flash %}
|
||||||
|
{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="max-w-screen-lg w-full">
|
||||||
|
<h1 class="h1">Mail</h1>
|
||||||
|
<form action="/admin/mail" method="post" enctype="multipart/form-data">
|
||||||
|
<select name="role_id">
|
||||||
|
{% for role in roles %}
|
||||||
|
<option value="{{ role.id }}">{{ role.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<input type="text" name="subject" />
|
||||||
|
<textarea name="body" rows="4" cols="50"></textarea>
|
||||||
|
<input type="file" name="files" multiple />
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
Loading…
Reference in New Issue
Block a user