7620f854a7 2024-05-21 1: use anyhow::Result;
7620f854a7 2024-05-21 2: use async_std::task;
7620f854a7 2024-05-21 3: //use async_trait::async_trait;
7620f854a7 2024-05-21 4: //use futures::io::AsyncRead;
7620f854a7 2024-05-21 5: //use mail_parser::Message;
7620f854a7 2024-05-21 6: use samotop::{
7620f854a7 2024-05-21 7: mail::{
7620f854a7 2024-05-21 8: Builder,
7620f854a7 2024-05-21 9: DebugService,
7620f854a7 2024-05-21 10: MailDir,
7620f854a7 2024-05-21 11: Name
7620f854a7 2024-05-21 12: },
7620f854a7 2024-05-21 13: smtp::Prudence,
7620f854a7 2024-05-21 14: };
7620f854a7 2024-05-21 15: use telegram_bot::{
7620f854a7 2024-05-21 16: Api,
7620f854a7 2024-05-21 17: ParseMode,
7620f854a7 2024-05-21 18: SendMessage,
7620f854a7 2024-05-21 19: UserId,
7620f854a7 2024-05-21 20: };
7620f854a7 2024-05-21 21:
7620f854a7 2024-05-21 22: use std::{
7620f854a7 2024-05-21 23: borrow::Cow,
7620f854a7 2024-05-21 24: collections::HashMap,
7620f854a7 2024-05-21 25: io::Read,
7620f854a7 2024-05-21 26: path::{
7620f854a7 2024-05-21 27: Path,
7620f854a7 2024-05-21 28: PathBuf
7620f854a7 2024-05-21 29: },
7620f854a7 2024-05-21 30: time::Duration,
7620f854a7 2024-05-21 31: vec::Vec,
7620f854a7 2024-05-21 32: };
7620f854a7 2024-05-21 33:
7620f854a7 2024-05-21 34:
7620f854a7 2024-05-21 35: fn relay_mails(maildir: &Path, core: &Core) -> Result<()> {
7620f854a7 2024-05-21 36: use mail_parser::*;
7620f854a7 2024-05-21 37:
7620f854a7 2024-05-21 38: let new_dir = maildir.join("new");
7620f854a7 2024-05-21 39:
7620f854a7 2024-05-21 40: std::fs::create_dir_all(&new_dir)?;
7620f854a7 2024-05-21 41:
7620f854a7 2024-05-21 42: let files = std::fs::read_dir(new_dir)?;
7620f854a7 2024-05-21 43: for file in files {
7620f854a7 2024-05-21 44: dbg!(&file);
7620f854a7 2024-05-21 45: let file = file?;
7620f854a7 2024-05-21 46: let mut buf = Vec::new();
7620f854a7 2024-05-21 47: std::fs::File::open(file.path())?.read_to_end(&mut buf)?;
7620f854a7 2024-05-21 48:
7620f854a7 2024-05-21 49: task::block_on(async move {
7620f854a7 2024-05-21 50: match MessageParser::default().parse(&buf[..]) {
7620f854a7 2024-05-21 51: Some(mail) => {
7620f854a7 2024-05-21 52: /*
7620f854a7 2024-05-21 53: dbg!(&mail);
7620f854a7 2024-05-21 54: let to = match mail.to() {
7620f854a7 2024-05-21 55: Some(mail) => mail.into_list().into_iter().map(|a| a.address.unwrap()).collect(),
7620f854a7 2024-05-21 56: None => match mail.header("X-Samotop-To").unwrap() {
7620f854a7 2024-05-21 57: mail_parser::HeaderValue::Address(addr) => addr.address.unwrap(),
7620f854a7 2024-05-21 58: },
7620f854a7 2024-05-21 59: };
7620f854a7 2024-05-21 60: dbg!(&to);
7620f854a7 2024-05-21 61: */
7620f854a7 2024-05-21 62: },
7620f854a7 2024-05-21 63: None => { core.debug("None mail.").await.unwrap(); },
7620f854a7 2024-05-21 64: //send_to_sendgrid(mail, sendgrid_api_key).await;
7620f854a7 2024-05-21 65: };
7620f854a7 2024-05-21 66: });
7620f854a7 2024-05-21 67:
7620f854a7 2024-05-21 68: std::fs::remove_file(file.path())?;
7620f854a7 2024-05-21 69: }
7620f854a7 2024-05-21 70: Ok(())
7620f854a7 2024-05-21 71: }
7620f854a7 2024-05-21 72:
7620f854a7 2024-05-21 73: fn my_prudence() -> Prudence {
7620f854a7 2024-05-21 74: Prudence::default().with_read_timeout(Duration::from_secs(60)).with_banner_delay(Duration::from_secs(1))
7620f854a7 2024-05-21 75: }
7620f854a7 2024-05-21 76:
7620f854a7 2024-05-21 77: pub struct Core {
7620f854a7 2024-05-21 78: default: UserId,
7620f854a7 2024-05-21 79: tg: Api,
7620f854a7 2024-05-21 80: recipients: HashMap<String, UserId>,
7620f854a7 2024-05-21 81: }
7620f854a7 2024-05-21 82:
7620f854a7 2024-05-21 83: impl Core {
7620f854a7 2024-05-21 84: pub fn new(settings: &config::Config) -> Result<Core> {
7620f854a7 2024-05-21 85: let api_key = settings.get_string("api_key").unwrap();
7620f854a7 2024-05-21 86: let tg = Api::new(api_key);
7620f854a7 2024-05-21 87: let default_recipient = settings.get_string("default")?;
7620f854a7 2024-05-21 88: let recipients: HashMap<String, UserId> = settings.get_table("recipients")?.into_iter().map(|(a, b)| (a, UserId::new(b.into_int().unwrap()))).collect();
7620f854a7 2024-05-21 89: let default = recipients[&default_recipient];
7620f854a7 2024-05-21 90:
7620f854a7 2024-05-21 91: Ok(Core {
7620f854a7 2024-05-21 92: default,
7620f854a7 2024-05-21 93: tg,
7620f854a7 2024-05-21 94: recipients,
7620f854a7 2024-05-21 95: })
7620f854a7 2024-05-21 96: }
7620f854a7 2024-05-21 97:
7620f854a7 2024-05-21 98: pub async fn debug<'b, S>(&self, msg: S) -> Result<()>
7620f854a7 2024-05-21 99: where S: Into<Cow<'b, str>> {
7620f854a7 2024-05-21 100: self.tg.send(SendMessage::new(self.default, msg)
7620f854a7 2024-05-21 101: .parse_mode(ParseMode::Markdown)).await?;
7620f854a7 2024-05-21 102: Ok(())
7620f854a7 2024-05-21 103: }
7620f854a7 2024-05-21 104:
7620f854a7 2024-05-21 105: pub async fn send<'b, S>(&self, to: String, msg: S) -> Result<()>
7620f854a7 2024-05-21 106: where S: Into<Cow<'b, str>> {
7620f854a7 2024-05-21 107: self.tg.send(SendMessage::new(self.recipients[&to], msg)
7620f854a7 2024-05-21 108: .parse_mode(ParseMode::Markdown)).await?;
7620f854a7 2024-05-21 109: Ok(())
7620f854a7 2024-05-21 110: }
7620f854a7 2024-05-21 111: }
7620f854a7 2024-05-21 112:
7620f854a7 2024-05-21 113: #[async_std::main]
7620f854a7 2024-05-21 114: async fn main() {
7620f854a7 2024-05-21 115: let settings: config::Config = config::Config::builder()
7620f854a7 2024-05-21 116: .add_source(config::File::with_name("smtp2tg.toml"))
7620f854a7 2024-05-21 117: .build().unwrap();
7620f854a7 2024-05-21 118:
7620f854a7 2024-05-21 119: let core = Core::new(&settings).unwrap();
7620f854a7 2024-05-21 120: let maildir: PathBuf = settings.get_string("maildir").unwrap().into();
7620f854a7 2024-05-21 121: let addr = "./smtp2tg.sock";
7620f854a7 2024-05-21 122: let listen_on = settings.get_string("listen_on").unwrap();
7620f854a7 2024-05-21 123: let sink = Builder + Name::new("smtp2tg") + DebugService +
7620f854a7 2024-05-21 124: samotop::smtp::Esmtp.with(samotop::smtp::SmtpParser) + my_prudence() +
7620f854a7 2024-05-21 125: MailDir::new(maildir.clone()).unwrap();
7620f854a7 2024-05-21 126:
7620f854a7 2024-05-21 127: task::spawn(async move {
7620f854a7 2024-05-21 128: loop {
7620f854a7 2024-05-21 129: task::sleep(Duration::from_secs(5)).await;
7620f854a7 2024-05-21 130: relay_mails(&maildir, &core).unwrap();
7620f854a7 2024-05-21 131: }
7620f854a7 2024-05-21 132: });
7620f854a7 2024-05-21 133:
7620f854a7 2024-05-21 134: match listen_on.as_str() {
7620f854a7 2024-05-21 135: "socket" => samotop::server::UnixServer::on("./smtp2tg.sock")
7620f854a7 2024-05-21 136: .serve(sink.build()).await.unwrap(),
7620f854a7 2024-05-21 137: _ => samotop::server::TcpServer::on(listen_on)
7620f854a7 2024-05-21 138: .serve(sink.build()).await.unwrap(),
7620f854a7 2024-05-21 139: };
7620f854a7 2024-05-21 140: /*
7620f854a7 2024-05-21 141: task::block_on(async {
7620f854a7 2024-05-21 142: let be = MyBackend;
7620f854a7 2024-05-21 143:
7620f854a7 2024-05-21 144: //let mut s = Server::new(be);
7620f854a7 2024-05-21 145:
7620f854a7 2024-05-21 146: s.addr = "127.0.0.1:2525".to_string();
7620f854a7 2024-05-21 147: s.domain = "localhost".to_string();
7620f854a7 2024-05-21 148: s.read_timeout = std::time::Duration::from_secs(10);
7620f854a7 2024-05-21 149: s.write_timeout = std::time::Duration::from_secs(10);
7620f854a7 2024-05-21 150: s.max_message_bytes = 10 * 1024 * 1024;
7620f854a7 2024-05-21 151: s.max_recipients = 50;
7620f854a7 2024-05-21 152: s.max_line_length = 1000;
7620f854a7 2024-05-21 153: s.allow_insecure_auth = true;
7620f854a7 2024-05-21 154:
7620f854a7 2024-05-21 155: println!("Starting server on {}", s.addr);
7620f854a7 2024-05-21 156: match s.listen_and_serve().await {
7620f854a7 2024-05-21 157: Ok(_) => println!("Server stopped"),
7620f854a7 2024-05-21 158: Err(e) => println!("Server error: {}", e),
7620f854a7 2024-05-21 159: }
7620f854a7 2024-05-21 160: Ok(())
7620f854a7 2024-05-21 161: })
7620f854a7 2024-05-21 162: */
7620f854a7 2024-05-21 163: }