mirror of
https://git.alemi.dev/guestbook.rs.git
synced 2024-11-12 19:39:28 +01:00
feat: added crude email notifier
also default to console notifier enabled
This commit is contained in:
parent
53c84839b8
commit
6c6c0fd62b
5 changed files with 106 additions and 11 deletions
|
@ -25,11 +25,13 @@ axum = "0.6.20"
|
||||||
sqlx = { version = "0.7.3", features = ["runtime-tokio", "tls-rustls", "any"] }
|
sqlx = { version = "0.7.3", features = ["runtime-tokio", "tls-rustls", "any"] }
|
||||||
# notification providers
|
# notification providers
|
||||||
teloxide = { version = "0.12.2", features = ["macros"], optional = true }
|
teloxide = { version = "0.12.2", features = ["macros"], optional = true }
|
||||||
|
mail-send = { version = "0.4.6", optional = true }
|
||||||
|
tokio-rustls = { version = "0.25.0", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = [
|
||||||
"mysql", "sqlite", "postgres",
|
"mysql", "sqlite", "postgres",
|
||||||
"telegram",
|
"telegram", "email"
|
||||||
]
|
]
|
||||||
# db drivers
|
# db drivers
|
||||||
mysql = ["sqlx/mysql"]
|
mysql = ["sqlx/mysql"]
|
||||||
|
@ -37,3 +39,4 @@ sqlite = ["sqlx/sqlite"]
|
||||||
postgres = ["sqlx/postgres"]
|
postgres = ["sqlx/postgres"]
|
||||||
# notifier providers
|
# notifier providers
|
||||||
telegram = ["dep:teloxide"]
|
telegram = ["dep:teloxide"]
|
||||||
|
email = ["dep:mail-send", "dep:tokio-rustls"]
|
||||||
|
|
|
@ -17,20 +17,40 @@ pub struct ConfigOverrides {
|
||||||
pub date: bool,
|
pub date: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct ConfigNotifiers {
|
pub struct ConfigNotifiers {
|
||||||
pub providers: Vec<ConfigNotifierProvider>,
|
pub providers: Vec<NotifierProvider>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// by default enable console notifier
|
||||||
|
impl Default for ConfigNotifiers {
|
||||||
|
fn default() -> Self {
|
||||||
|
ConfigNotifiers {
|
||||||
|
providers: vec![NotifierProvider::Console],
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum ConfigNotifierProvider {
|
pub enum NotifierProvider {
|
||||||
ConsoleNotifier,
|
Console,
|
||||||
|
|
||||||
#[cfg(feature = "telegram")]
|
#[cfg(feature = "telegram")]
|
||||||
TelegramNotifier {
|
Telegram {
|
||||||
token: String,
|
token: String,
|
||||||
chat_id: i64,
|
chat_id: i64,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[cfg(feature = "email")]
|
||||||
|
Email {
|
||||||
|
server: String,
|
||||||
|
port: u16,
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
subject: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _true() -> bool { true }
|
fn _true() -> bool { true }
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -2,7 +2,7 @@ use std::{net::SocketAddr, io::Write};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use config::ConfigOverrides;
|
use config::ConfigOverrides;
|
||||||
|
|
||||||
use crate::{storage::StorageProvider, routes::Context, notifications::console::ConsoleTracingNotifier, config::{Config, ConfigNotifierProvider}};
|
use crate::{storage::StorageProvider, routes::Context, notifications::console::ConsoleTracingNotifier, config::{Config, NotifierProvider}};
|
||||||
|
|
||||||
mod notifications;
|
mod notifications;
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ async fn main() {
|
||||||
match args.action {
|
match args.action {
|
||||||
CliAction::Default => {
|
CliAction::Default => {
|
||||||
let mut cfg = Config::default();
|
let mut cfg = Config::default();
|
||||||
cfg.notifiers.providers.push(ConfigNotifierProvider::ConsoleNotifier);
|
cfg.notifiers.providers.push(NotifierProvider::Console);
|
||||||
#[cfg(feature = "telegram")]
|
#[cfg(feature = "telegram")]
|
||||||
cfg.notifiers.providers.push(ConfigNotifierProvider::TelegramNotifier { token: "asd".into(), chat_id: -1 });
|
cfg.notifiers.providers.push(NotifierProvider::Telegram { token: "asd".into(), chat_id: -1 });
|
||||||
println!("{}", toml::to_string(&cfg).unwrap());
|
println!("{}", toml::to_string(&cfg).unwrap());
|
||||||
},
|
},
|
||||||
CliAction::Review { batch } => {
|
CliAction::Review { batch } => {
|
||||||
|
@ -112,18 +112,31 @@ async fn main() {
|
||||||
|
|
||||||
for notifier in config.notifiers.providers {
|
for notifier in config.notifiers.providers {
|
||||||
match notifier {
|
match notifier {
|
||||||
ConfigNotifierProvider::ConsoleNotifier => {
|
NotifierProvider::Console => {
|
||||||
tracing::info!("registering console notifier");
|
tracing::info!("registering console notifier");
|
||||||
state.register(Box::new(ConsoleTracingNotifier {}));
|
state.register(Box::new(ConsoleTracingNotifier {}));
|
||||||
},
|
},
|
||||||
|
|
||||||
#[cfg(feature = "telegram")]
|
#[cfg(feature = "telegram")]
|
||||||
ConfigNotifierProvider::TelegramNotifier { token, chat_id } => {
|
NotifierProvider::Telegram { token, chat_id } => {
|
||||||
tracing::info!("registering telegram notifier for chat {}", chat_id);
|
tracing::info!("registering telegram notifier for chat {}", chat_id);
|
||||||
state.register(Box::new(
|
state.register(Box::new(
|
||||||
notifications::telegram::TGNotifier::new(&token, chat_id)
|
notifications::telegram::TGNotifier::new(&token, chat_id)
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[cfg(feature = "email")]
|
||||||
|
NotifierProvider::Email {
|
||||||
|
server, port, username, password, from, to, subject
|
||||||
|
} => {
|
||||||
|
tracing::info!("registering email notifier to {} on server {}:{} ('{}')", to, server, port, subject);
|
||||||
|
state.register(Box::new(
|
||||||
|
notifications::email::EmailNotifier::new(
|
||||||
|
&server, port, &username, &password, &from, &to, &subject
|
||||||
|
).await
|
||||||
|
));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
56
src/notifications/email.rs
Normal file
56
src/notifications/email.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use mail_send::{SmtpClientBuilder, SmtpClient, mail_builder::MessageBuilder};
|
||||||
|
use tokio::{sync::Mutex, net::TcpStream};
|
||||||
|
use tokio_rustls::client::TlsStream;
|
||||||
|
|
||||||
|
use crate::model::Page;
|
||||||
|
|
||||||
|
use super::NotificationProcessor;
|
||||||
|
|
||||||
|
pub struct EmailNotifier {
|
||||||
|
client: Mutex<SmtpClient<TlsStream<TcpStream>>>,
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
subject: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EmailNotifier {
|
||||||
|
pub async fn new(
|
||||||
|
server: &str,
|
||||||
|
port: u16,
|
||||||
|
username: &str,
|
||||||
|
password: &str,
|
||||||
|
from: &str,
|
||||||
|
to: &str,
|
||||||
|
subject: &str,
|
||||||
|
) -> Self {
|
||||||
|
let client = SmtpClientBuilder::new(server, port)
|
||||||
|
.implicit_tls(false)
|
||||||
|
.credentials((username, password))
|
||||||
|
.connect()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
EmailNotifier {
|
||||||
|
client: Mutex::new(client),
|
||||||
|
from: from.to_string(),
|
||||||
|
to: to.to_string(),
|
||||||
|
subject: subject.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl NotificationProcessor<Page> for EmailNotifier {
|
||||||
|
async fn process(&self, notification: &Page) {
|
||||||
|
let message = MessageBuilder::new()
|
||||||
|
.from((notification.author.as_str(), notification.contact.as_ref().unwrap_or(&self.from).as_str()))
|
||||||
|
.to(vec![("Guestbook", self.to.as_str())])
|
||||||
|
.subject(&self.subject)
|
||||||
|
.text_body(¬ification.body);
|
||||||
|
|
||||||
|
if let Err(e) = self.client.lock().await.send(message).await {
|
||||||
|
tracing::error!("could not send message via email: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
#[cfg(feature = "telegram")]
|
#[cfg(feature = "telegram")]
|
||||||
pub mod telegram;
|
pub mod telegram;
|
||||||
|
|
||||||
|
#[cfg(feature = "email")]
|
||||||
|
pub mod email;
|
||||||
|
|
||||||
pub mod console;
|
pub mod console;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue