| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -10,15 +10,18 @@ cfg_if! { if #[cfg(feature = "ssr")] {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use crate::backend::get_pool;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use crate::error::AppError;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use log::info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use log::error;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use crate::config::Mailing;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use crate::config::MailTransport;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use crate::backend::data::ResSumWithItems;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::message::Message as LettreMessage;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::{AsyncSmtpTransport, AsyncFileTransport, AsyncTransport, Tokio1Executor};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::{FileTransport, SmtpTransport, Transport};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::transport::smtp::client::{Tls, TlsParameters};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::transport::smtp::authentication::Credentials;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use lettre::transport::smtp::extension::ClientId;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use std::ops::Add;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use std::sync::mpsc::Sender;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    use std::sync::mpsc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    pub async fn message_for_type(msg_type: &MessageType, pool: &PgPool) -> Result<Message, Error> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Ok(query_as::<_, Message>("SELECT * FROM message WHERE msg_type = $1")
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -100,13 +103,26 @@ cfg_if! { if #[cfg(feature = "ssr")] {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    impl Mailing {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pub async fn send_mail(&self, msg: MailMessage) -> Result<(), AppError> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            match self.transport() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    #[derive(Clone)]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    enum MailerType {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Smtp(SmtpTransport),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        File(String)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    #[derive(Clone)]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    pub struct Mailer {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        transport: MailerType,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        from: String,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        sender: Option<Sender<MailMessage>>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    impl Mailer {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pub fn new(config: &Mailing) -> Self {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            match config.transport() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                MailTransport::Smtp => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let tls = if let Some(t) = self.accept_all_certs() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let tls = if let Some(t) = config.accept_all_certs() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        if t {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            let tls = TlsParameters::builder(self.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            let tls = TlsParameters::builder(config.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            .dangerous_accept_invalid_certs(true)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            .dangerous_accept_invalid_hostnames(true);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        Some(tls.build().expect("Cannot build TLS params"))
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -116,8 +132,8 @@ cfg_if! { if #[cfg(feature = "ssr")] {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if self.tls().unwrap_or(false) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let transport = AsyncSmtpTransport::<Tokio1Executor>::starttls_relay(&self.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if config.tls().unwrap_or(false) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let transport = SmtpTransport::starttls_relay(&config.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            .expect("Cannot create SMTP mail transport");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        if let Some(t) = tls {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport.tls(Tls::Required(t))
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -125,7 +141,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let transport = AsyncSmtpTransport::<Tokio1Executor>::relay(&self.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let transport = SmtpTransport::relay(&config.server().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            .expect("Cannot create SMTP mail transport");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        if let Some(t) = tls {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport.tls(Tls::Wrapper(t))
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -133,30 +149,85 @@ cfg_if! { if #[cfg(feature = "ssr")] {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if let Some(p) = self.port() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if let Some(p) = config.port() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport.port(p)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if let Some(hello) = self.hello_name() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let transport = if let Some(hello) = config.hello_name() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport.hello_name(ClientId::Domain(hello.to_string()))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if self.user().is_some() && self.password().is_some() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let cred = Credentials::new(self.user().clone().unwrap(), self.password().clone().unwrap());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport.credentials(cred).build().send(msg.build_mail(self.from().to_string())?).await?;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if config.user().is_some() && config.password().is_some() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        let cred = Credentials::new(config.user().clone().unwrap(), config.password().clone().unwrap());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        Self {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport: MailerType::Smtp(transport.credentials(cred).build()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            from: config.from().to_string(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            sender: None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport.build().send(msg.build_mail(self.from().to_string())?).await?;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        Self {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            transport: MailerType::Smtp(transport.build()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            from: config.from().to_string(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            sender: None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                MailTransport::File => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    AsyncFileTransport::<Tokio1Executor>::new(self.path().clone().unwrap_or_default())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        .send(msg.build_mail(self.from().to_string())?).await?;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    Self {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        transport: MailerType::File(config.path().clone().unwrap_or("".to_string())),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        from: config.from().to_string(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        sender: None
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        fn send(&self, msg: &MailMessage) -> Result<(), AppError> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            let to_send = msg.build_mail(self.from.clone())?;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            match &self.transport {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                MailerType::Smtp(s) => {s.send(&to_send)?;},
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                MailerType::File(s) => {FileTransport::new(s).send(&to_send)?;}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Ok(())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pub fn start_sender(&mut self) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            let (tx, rx) = mpsc::channel::<MailMessage>();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.sender = Some(tx);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            let mailer = self.clone();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            std::thread::spawn(move || {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                loop {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let msg = rx.recv();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if let Err(e) = msg {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        error!("Mailer error: {}", e.to_string());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    let msg = msg.unwrap();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if let Err(e) = mailer.send(&msg) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        error!("Mail send error: {}", e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        info!("Mail message for: {} has been successfully sent", msg.to);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            info!("Mail sender started");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        pub fn send_mail(&self, msg: MailMessage) -> Result<(), AppError> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if let Err(e) = self.sender.as_ref().expect("Sender not started").send(msg) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                error!("Mail queue error: {}", e);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                Err(AppError::MailSendError(e.to_string()))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                info!("Message queued for send");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                Ok(())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |