add mail
This commit is contained in:
		
							
								
								
									
										216
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										216
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -333,6 +333,16 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "cipher"
 | 
			
		||||
version = "0.4.4"
 | 
			
		||||
@@ -366,6 +376,16 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "core-foundation-sys"
 | 
			
		||||
version = "0.8.6"
 | 
			
		||||
@@ -554,6 +574,22 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "encoding_rs"
 | 
			
		||||
version = "0.8.33"
 | 
			
		||||
@@ -664,6 +700,21 @@ version = "1.0.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
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]]
 | 
			
		||||
name = "form_urlencoded"
 | 
			
		||||
version = "1.2.1"
 | 
			
		||||
@@ -948,6 +999,17 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "http"
 | 
			
		||||
version = "0.2.11"
 | 
			
		||||
@@ -1186,6 +1248,31 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "libc"
 | 
			
		||||
version = "0.2.151"
 | 
			
		||||
@@ -1246,6 +1333,12 @@ dependencies = [
 | 
			
		||||
 "tracing-subscriber",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "match_cfg"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "matchers"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
@@ -1333,6 +1426,24 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "nix"
 | 
			
		||||
version = "0.27.1"
 | 
			
		||||
@@ -1471,6 +1582,50 @@ version = "0.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
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]]
 | 
			
		||||
name = "overload"
 | 
			
		||||
version = "0.1.1"
 | 
			
		||||
@@ -1732,6 +1887,15 @@ dependencies = [
 | 
			
		||||
 "yansi",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "psm"
 | 
			
		||||
version = "0.1.21"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pure-rust-locales"
 | 
			
		||||
version = "0.7.0"
 | 
			
		||||
@@ -1747,6 +1911,12 @@ dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quoted_printable"
 | 
			
		||||
version = "0.5.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rand"
 | 
			
		||||
version = "0.8.5"
 | 
			
		||||
@@ -1968,6 +2138,7 @@ dependencies = [
 | 
			
		||||
 "env_logger",
 | 
			
		||||
 "futures",
 | 
			
		||||
 "ics",
 | 
			
		||||
 "lettre",
 | 
			
		||||
 "log",
 | 
			
		||||
 "rocket",
 | 
			
		||||
 "rocket_dyn_templates",
 | 
			
		||||
@@ -2067,6 +2238,15 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "scoped-tls"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
@@ -2089,6 +2269,29 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "serde"
 | 
			
		||||
version = "1.0.193"
 | 
			
		||||
@@ -2473,6 +2676,19 @@ dependencies = [
 | 
			
		||||
 "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]]
 | 
			
		||||
name = "state"
 | 
			
		||||
version = "0.6.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -22,3 +22,5 @@ chrono-tz = "0.8"
 | 
			
		||||
tera =  { version = "1.18", features = ["date-locale"], optional = true}
 | 
			
		||||
ics = "0.5"
 | 
			
		||||
futures = "0.3"
 | 
			
		||||
lettre = "0.11"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,3 +2,4 @@
 | 
			
		||||
secret_key = "/NtVGizglEoyoxBLzsRDWTy4oAG1qDw4J4O+CWJSv+fypD7W9sam8hUY4j90EZsbZk8wEradS5zBoWtWKi3k8w=="
 | 
			
		||||
rss_key = "rss-key-for-ci"
 | 
			
		||||
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 logbook;
 | 
			
		||||
pub mod logtype;
 | 
			
		||||
pub mod mail;
 | 
			
		||||
pub mod planned_event;
 | 
			
		||||
pub mod role;
 | 
			
		||||
pub mod rower;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,4 +14,32 @@ impl Role {
 | 
			
		||||
            .await
 | 
			
		||||
            .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 mail;
 | 
			
		||||
pub mod planned_event;
 | 
			
		||||
pub mod user;
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +29,7 @@ pub fn routes() -> Vec<Route> {
 | 
			
		||||
    let mut ret = Vec::new();
 | 
			
		||||
    ret.append(&mut user::routes());
 | 
			
		||||
    ret.append(&mut boat::routes());
 | 
			
		||||
    ret.append(&mut mail::routes());
 | 
			
		||||
    ret.append(&mut planned_event::routes());
 | 
			
		||||
    ret.append(&mut routes![rss, show_rss]);
 | 
			
		||||
    ret
 | 
			
		||||
 
 | 
			
		||||
@@ -206,6 +206,7 @@ fn unauthorized_error() -> Redirect {
 | 
			
		||||
#[serde(crate = "rocket::serde")]
 | 
			
		||||
pub struct Config {
 | 
			
		||||
    rss_key: String,
 | 
			
		||||
    smtp_pw: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 %}
 | 
			
		||||
		Reference in New Issue
	
	Block a user