diff --git a/mail2list/dockerfile b/mail2list/dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..92e90b0af4cbd85037a8681f3e72d884a90c59ed --- /dev/null +++ b/mail2list/dockerfile @@ -0,0 +1,15 @@ +# 下载环境对应的包 +# 配置对应的源 +FROM rust:1.31 +FROM enmotech/opengauss:2.1.0 +FROM node:14.19.1 +RUN npm i --registry=https://registry.npm.taobao.org + +RUN mkdir -p /app/mail2list/backend +COPY mail2list_backend/mail2list_web app/mail2list/backend/mail2list_web + + +EXPOSE 9999 + +RUN cargo install --path /app/mail2list/backend/mail2list_web +CMD ["mail2list_web"] diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/Cargo.toml b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/Cargo.toml index 6cf29020633cdff8f648eaef5e539e29618dbc27..87a95b66ca8973e4f5384b8b3f2b7508a482f846 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/Cargo.toml +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/Cargo.toml @@ -58,4 +58,4 @@ imap = "3.0.0-alpha.6" mailparse = "0.13.8" lettre = "0.10.0-rc.5" lettre_email = "0.9" -mime = "0.3.13" \ No newline at end of file +mime = "0.3.13" diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/config/config.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/config/config.rs index ac69e524d684262da2ade83f1c1e0c2054dbd6b2..838ef04022a4149f29a4fdab9125f4535ce74c04 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/config/config.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/config/config.rs @@ -7,15 +7,15 @@ pub struct ServerConfig{ #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct MailConfig{ - pub mine_email : String, - pub password : String, - pub smtp_server : String, - pub imap_server : String, - pub leave_email : String, - pub leave_email_password : String, - pub leave_smtp_server : String, - pub leave_imap_server : String, - pub leave_name : String, + pub mine_email : Vec, + pub password : Vec, + pub smtp_server : Vec, + pub imap_server : Vec, + pub leave_email : Vec, + pub leave_email_password : Vec, + pub leave_smtp_server : Vec, + pub leave_imap_server : Vec, + pub leave_name : Vec, } ///服务启动配置 diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/controller/archive_mail_list_controller.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/controller/archive_mail_list_controller.rs index 8aab3ab9a29acd8d2a167946c8768e54f773dac9..3ad13c0facdf846217a460256ad05f4d3737b98b 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/controller/archive_mail_list_controller.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/controller/archive_mail_list_controller.rs @@ -1,9 +1,4 @@ use crate::CONTEXT; - -pub async fn delete(imap_server: &str, mine_email :&str,smtp_server: &str, password :&str, name :&str) { - CONTEXT.subscribe_mail_list_service.delete(imap_server, mine_email, smtp_server,password, "退订成功","",name).await; -} - -pub async fn save(mine_email :&str,smtp_server: &str, password :&str, name :&str) { - CONTEXT.archive_mail_list_service.save_info(smtp_server, mine_email, password,name).await; +pub async fn save(mine_email :&str,imap_server: &str, smtp_server: &str,password :&str, name :&str) { + CONTEXT.archive_mail_list_service.save_info(imap_server, smtp_server,mine_email, password,name).await; } \ No newline at end of file diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/dto/subscribe_mail_list_dto.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/dto/subscribe_mail_list_dto.rs index e8849271ce9aa460ccc07c6824bb9d8fe577ca6a..aa5241f61dc25fcb8cf8315d93f05a9432a1e851 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/dto/subscribe_mail_list_dto.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/dto/subscribe_mail_list_dto.rs @@ -7,12 +7,14 @@ pub struct SubscribeMailListDTO { pub id: Option, pub name: Option, #[validate(email)] + pub user_email: Option, pub email: Option, pub username: Option, } impl_field_name_method!(SubscribeMailListDTO { id, name, + user_email, email, username }); @@ -21,6 +23,7 @@ impl Into for SubscribeMailListDTO { SubscribeMailList { id: self.id, name: self.name, + user_email: self.user_email, email: self.email, username: self.username } @@ -33,6 +36,7 @@ impl From for SubscribeMailListDTO { id: arg.id, name: arg.name, email: arg.email, + user_email: arg.user_email, username: arg.username, } } diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/entity/sys_entitys.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/entity/sys_entitys.rs index 5ae7c0617d194f82e7c558c70a711efef178c173..ecf69de4abaec5b78972baca7ba1f6a1f8a47131 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/entity/sys_entitys.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/entity/sys_entitys.rs @@ -3,6 +3,7 @@ pub struct SubscribeMailList { pub id: Option, pub name: Option, + pub user_email: Option, pub email: Option, pub username: Option, } @@ -10,6 +11,7 @@ impl_field_name_method!(SubscribeMailList { id, name, email, + user_email, username, }); diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/main.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/main.rs index c369ac78e368fc57c209ec493f13caf6b6458dc2..dfb9285e2080794ac60af447bec284806c8d3a6d 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/main.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/main.rs @@ -1,24 +1,43 @@ +use chrono::prelude::*; use mail2list_archive_unsubscribe::{ - controller::subscribe_mail_list_controller, - controller::archive_mail_list_controller, + controller::archive_mail_list_controller, controller::subscribe_mail_list_controller, MAIL2LIST_CONFIG, }; +extern crate chrono; +extern crate imap; - - -/** - *method:main - *desc:退订以及归档 需要长时间自动访问 因此单独提取出来一个程序 - *author:zhaorunqi - *email:348040933QQ.com - */ #[tokio::main] async fn main() { - //此处直接开始监控删除并且一直监控 - //单独提出来一个程序 单独运行 并且如果找到的话记得删除邮件 - loop{ - //subscribe_mail_list_controller::delete(&MAIL2LIST_CONFIG.email.leave_smtp_server,&MAIL2LIST_CONFIG.email.leave_email,&MAIL2LIST_CONFIG.email.leave_smtp_server,&MAIL2LIST_CONFIG.email.leave_email_password, &MAIL2LIST_CONFIG.email.leave_name).await; - archive_mail_list_controller::save(&MAIL2LIST_CONFIG.email.leave_email,&MAIL2LIST_CONFIG.email.leave_smtp_server,&MAIL2LIST_CONFIG.email.leave_email_password, &MAIL2LIST_CONFIG.email.leave_name).await; + loop { + let dt = Local::now(); + println!("dt: {}", dt); + tokio::spawn(async { + email().await; + true + }) + .await + .unwrap(); + } +} + +async fn email() { + let len = MAIL2LIST_CONFIG.email.leave_imap_server.len(); + for i in 0..len { + let save = archive_mail_list_controller::save( + &MAIL2LIST_CONFIG.email.mine_email[i], + &MAIL2LIST_CONFIG.email.imap_server[i], + &&MAIL2LIST_CONFIG.email.smtp_server[i], + &MAIL2LIST_CONFIG.email.password[i], + &MAIL2LIST_CONFIG.email.leave_name[i], + ); + let delete = subscribe_mail_list_controller::delete( + &MAIL2LIST_CONFIG.email.leave_imap_server[i], + &MAIL2LIST_CONFIG.email.leave_email[i], + &MAIL2LIST_CONFIG.email.leave_smtp_server[i], + &MAIL2LIST_CONFIG.email.leave_email_password[i], + &MAIL2LIST_CONFIG.email.leave_name[i], + ); + futures::join!(save, delete); } } diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/archive_mail_list_service.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/archive_mail_list_service.rs index de8aed1d95a31c86e55b113d940e7050901d2bde..f963c5eb84b913da4fb23603c89c209f3cfc944b 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/archive_mail_list_service.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/archive_mail_list_service.rs @@ -7,18 +7,27 @@ use crate::entity::sys_entitys::{ArchiveMailList, CommonField, SubscribeMailList use crate::request::ArchiveMailListQuery; use crate::service::crud_service::CrudService; use crate::RB; +use mail2list_common::utils::send_email::SendMail; use rbatis::crud::CRUD; use rbatis::wrapper::Wrapper; -use imap; use lettre::transport::smtp::authentication::Credentials; use lettre::{ - message::{Body,Attachment, MultiPart}, + message::{Attachment, Body, MultiPart}, Message, SmtpTransport, Transport, }; use mailparse::*; -use std::io::Write; use std::fs; +use std::io::Write; + + +use rand::distributions::Alphanumeric; +use rand::{thread_rng, Rng}; + +use mail2list_common::utils::timeout::Timeout; +use std::time::Duration; +use native_tls::TlsConnector; +use std::error::Error; /** *struct:ArchiveMailListService @@ -34,171 +43,206 @@ impl ArchiveMailListService { */ pub async fn save_info( &self, + imap_server: &str, smtp_server: &str, mine_email: &str, password: &str, name: &str, - ) -> imap::error::Result> { - let client = imap::ClientBuilder::new(smtp_server, 993).native_tls()?; + ) -> Result,Box> { + // let client = imap::ClientBuilder::new(imap_server, 993).native_tls()?; + let timeout = Duration::from_secs(5); + let tls = TlsConnector::builder().build()?; + let client = Timeout::connect_all_timeout((imap_server, 993), imap_server, &tls, timeout)?; - // the client we have here is unauthenticated. - // to do anything useful with the e-mails, we need to log in let mut imap_session = client.login(mine_email, password).map_err(|e| e.0)?; - // we want to fetch the first email in the INBOX mailbox let inbox = imap_session.select("INBOX")?; + let unseen = inbox.unseen; + match unseen { + Some(len) => { + for i in 0 as u32..len { + let messages = imap_session.fetch((inbox.exists - i).to_string(), "RFC822")?; + let message = if let Some(m) = messages.iter().next() { + m + } else { + return Ok(None); + }; - // let mut entity: ArchiveMailList = dto.into(); - for i in 0 as u32..inbox.exists { - // fetch message number 1 in this mailbox, along with its RFC822 field. - // RFC 822 dictates the format of the body of e-mails - let messages = imap_session.fetch((inbox.exists - i).to_string(), "RFC822")?; - let message = if let Some(m) = messages.iter().next() { - m - } else { - return Ok(None); - }; - - // extract the message's body - let body = message.body().expect("message did not have a body!"); - let body1 = std::str::from_utf8(body) - .expect("message was not valid utf-8") - .to_string(); - //println!("{}",body1); - - //此处的话增加两次 以此增加发件人 主题 日期 一次增加内容 - let parsed = parse_mail(body).unwrap(); - - //message_id - let message_id = parsed.headers.get_first_value("Message-ID").unwrap(); - println!("{}", message_id); - - //主题 - let subject = parsed.headers.get_first_value("Subject").unwrap(); - println!("{}", subject); - let subject1 = subject.clone(); - let subject2 = subject1.clone(); - - //from - let mail = parsed.headers.get_first_value("From").unwrap(); - let pos = mail.rfind("<").unwrap(); - let (_, lst) = mail.split_at(pos + 1); - let mut from_email = lst.to_string(); - from_email.pop(); - println!("{}", from_email); - let email = from_email.clone(); - - //Date - let date = dateparse(parsed.headers.get_first_value("Date").unwrap().as_str()).unwrap(); - println!("{}", date); - - //body - let mut body = dump(&parsed); - if body.ends_with(">") == true { - let pos = body.find("<").unwrap(); - let (_, body1) = body.split_at(pos); - body = body1.to_string(); - } - let body1 = body.clone(); - let body2 = body.clone(); - - println!("{}", body); - - //filename - //可能存在多个附件 将其名字通过隔一个空格隔开 在前端进行分割拿取 - let mut filename = String::new(); - for subpart in parsed.subparts { - if subpart.get_content_disposition().disposition == DispositionType::Attachment { - // it's an attachment - let filename_temp = subpart - .get_content_disposition() - .params - .get("filename") - .unwrap() + // extract the message's body + let body = message.body().expect("message did not have a body!"); + let body1 = std::str::from_utf8(body) + .expect("message was not valid utf-8") .to_string(); - filename += &filename_temp; - filename += &" ".to_string(); - } - } - println!("{}", filename); - let mut filename1 = Some(filename.clone()); - let filename3 = filename1.clone(); - let temp = filename3.unwrap(); - if temp == "" { - filename1 = None; - } - - let filename2 = filename.clone(); - - let mut archive_mail_list = ArchiveMailList { - name: Some(name.to_string()), - from_email: Some(from_email), - create_time: Some(date.to_string()), - subject: Some(subject1), - message_id: Some(message_id), - in_reply_to: None, - reference: None, - body: Some(body1), - id: None, - filename: filename1, - }; + //println!("{}",body1); - self.save(&mut archive_mail_list).await; + //此处的话增加两次 以此增加发件人 主题 日期 一次增加内容 + let parsed = parse_mail(body).unwrap(); - println!("{}",filename2); + //from + let mail = parsed.headers.get_first_value("From").unwrap(); + let pos = mail.rfind("<").unwrap(); + let (_, lst) = mail.split_at(pos + 1); + let mut from_email = lst.to_string(); + from_email.pop(); + println!("{}", from_email); + let user_email = from_email.clone(); - //转发 再进行转发的时候 其他都很好实现 但是对于存在多个附件 此时则需要判断一下 另外 其中要转发给的人也需要设置 - let wrapper = RB.new_wrapper().eq("name", name).ne("email", email); - let detail: Vec = RB.fetch_list_by_wrapper(wrapper).await.unwrap(); - for data in detail { - //找到了每个人邮箱 开始进行发送 - let email = data.email.unwrap(); - let mut multipart = MultiPart::alternative_plain_html( - String::from("Plaintext version of the body"), - String::from(&body2), - ); - if filename2 != "" { - let pos: Vec<&str> = filename2.split(" ").collect(); - for i in pos.into_iter() { - //此处拿到保存在本地的文件 - if i =="" { - break; + let wrapper = RB + .new_wrapper() + .eq("name", name) + .eq("user_email", from_email.clone()); + let detail: Option = + RB.fetch_by_wrapper(wrapper).await.unwrap(); + if detail.is_none() { + let mut subject = "请先订阅".to_string(); + subject += &name.clone(); + subject += "再进行回复"; + SendMail::send_email( + &from_email.clone(), + mine_email, + imap_server, + password, + subject.as_str(), + "", + ); + imap_session + .store(format!("{}", message.message), "+FLAGS (\\Seen)") + .unwrap(); + imap_session.expunge().unwrap(); + break; + } + //message_id + let message_id = parsed.headers.get_first_value("Message-ID").unwrap(); + println!("{}", message_id); + let message_id1 = message_id.clone(); + let message_id2 = message_id1.clone(); + //主题 + let subject = parsed.headers.get_first_value("Subject").unwrap(); + println!("{}", subject); + let subject1 = subject.clone(); + let subject2 = subject1.clone(); + //Date + let date = dateparse(parsed.headers.get_first_value("Date").unwrap().as_str()) + .unwrap(); + println!("{}", date); + //References + let reference = parsed.headers.get_first_value("References"); + let rand_string: String = thread_rng() + .sample_iter(&Alphanumeric) + .take(30) + .map(char::from) + .collect(); + //body + let mut body = dump(&parsed,rand_string.clone()); + if body.ends_with(">") == true { + let pos = body.find("<").unwrap(); + let (_, body1) = body.split_at(pos); + body = body1.to_string(); + } + let body1 = body.clone(); + let body2 = body.clone(); + println!("{}", body); + //filename + //可能存在多个附件 将其名字通过隔一个问号隔开 在前端进行分割拿取 + let mut filename = String::new(); + for subpart in parsed.subparts { + if subpart.get_content_disposition().disposition + == DispositionType::Attachment + { + // it's an attachment + let filename_temp = subpart + .get_content_disposition() + .params + .get("filename") + .unwrap() + .to_string(); + filename += &filename_temp; + filename += &"?".to_string(); } - let mut content = "E:/openEuler/task/test/".to_string(); - content += &i; - let attachment = fs::read(content).unwrap(); - let attachment_body = Body::new(attachment); - let attachment = Attachment::new(i.to_string()) - .body(attachment_body, "application/octet-stream".parse().unwrap()); // build `Attachment` here - multipart = multipart.singlepart(attachment); } - } - - let email = Message::builder() - .from(mine_email.parse().unwrap()) - .to(email.parse().unwrap()) - .subject(&subject2) - .multipart(multipart) - .unwrap(); - let creds = Credentials::new(mine_email.to_string(), password.to_string()); - - // Open a remote connection to gmail - let mailer = SmtpTransport::relay(smtp_server) - .unwrap() - .credentials(creds) - .build(); - - match mailer.send(&email) { - Ok(_) => println!("Email sent successfully!"), - Err(e) => panic!("Could not send email: {:?}", e), + println!("{}", filename); + let mut filename1 = Some(filename.clone()); + let filename3 = filename1.clone(); + let temp = filename3.unwrap(); + if temp == "" { + filename1 = None; + } + let filename2 = filename.clone(); + let mut archive_mail_list = ArchiveMailList { + name: Some(name.to_string()), + from_email: Some(from_email), + create_time: Some(date.to_string()), + subject: Some(subject1), + message_id: Some(message_id1), + in_reply_to: None, + reference: reference, + body: Some(body1), + id: None, + filename: filename1, + }; + self.save(&mut archive_mail_list).await; + println!("{}", filename2); + //转发 再进行转发的时候 其他都很好实现 但是对于存在多个附件 此时则需要判断一下 另外 其中要转发给的人也需要设置 + let wrapper = RB + .new_wrapper() + .eq("name", name) + .ne("user_email", user_email); + let details: Vec = + RB.fetch_list_by_wrapper(wrapper).await.unwrap(); + for data in details { + //找到了每个人邮箱 开始进行发送 + let email = data.user_email.unwrap(); + println!("{}",email); + let mut multipart = MultiPart::alternative_plain_html( + String::from("Plaintext version of the body"), + String::from(&body2), + ); + if filename2 != "" { + let pos: Vec<&str> = filename2.split("?").collect(); + for i in pos.into_iter() { + //此处拿到保存在本地的文件 + if i == "" { + break; + } + let mut content = "target/".to_string(); + content += &rand_string.clone(); + content += &i; + let attachment = fs::read(content).unwrap(); + let attachment_body = Body::new(attachment); + let attachment = Attachment::new(i.to_string()).body( + attachment_body, + "application/octet-stream".parse().unwrap(), + ); // build `Attachment` here + multipart = multipart.singlepart(attachment); + } + } + let email = Message::builder() + .from(mine_email.parse().unwrap()) + .to(email.parse().unwrap()) + .subject(&subject2) + .references(String::from(&message_id2)) + .multipart(multipart) + .unwrap(); + let creds = Credentials::new(mine_email.to_string(), password.to_string()); + // Open a remote connection to gmail + let mailer = SmtpTransport::relay(smtp_server) + .unwrap() + .credentials(creds) + .build(); + match mailer.send(&email) { + Ok(_) => println!("Email sent successfully!"), + Err(e) => panic!("Could not send email: {:?}", e), + } + } + imap_session + .store(format!("{}", message.message), "+FLAGS (\\Seen)") + .unwrap(); + imap_session.expunge().unwrap(); } } + None => {} + }; - imap_session - .store(format!("{}", message.message), "+FLAGS (\\Deleted)") - .unwrap(); - imap_session.expunge().unwrap(); - } // be nice to the server and log out imap_session.logout()?; @@ -206,7 +250,7 @@ impl ArchiveMailListService { } } -pub fn dump(pm: &mailparse::ParsedMail) -> String { +pub fn dump(pm: &mailparse::ParsedMail, rand_string : String) -> String { //接下来是文章内容 文字部分将会存储在body中 进行展示 附件将会保存在云服务器端 //这里的话我们直接将整个body追加存储在数据中 然后在数据库层面进行判断 if pm.ctype.mimetype.starts_with("text/") { @@ -226,8 +270,9 @@ pub fn dump(pm: &mailparse::ParsedMail) -> String { .unwrap() .to_string(); let data = pm.get_body_raw().unwrap(); - let mut path = "E:/openEuler/task/test/".to_string(); + let mut path = "target/".to_string(); //此处增加一个随机数 避免文件重合 + path += &rand_string.clone(); path += &filename; let mut file = std::fs::File::create(path).expect("create failed"); //println!("文件创建成功:{:?}",file); @@ -246,7 +291,7 @@ pub fn dump(pm: &mailparse::ParsedMail) -> String { let mut all_body = String::new(); for s in &pm.subparts { // println!(">> Subpart {} <<", c); - let body = dump(s); + let body = dump(s,rand_string.clone()); all_body += &body; c = c + 1; } diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/crud_service.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/crud_service.rs index a7742e251a6cfbb2988f3fcc196145301eb58c03..70bfb905578ea09bae746dfaab3e744add1be300 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/crud_service.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/crud_service.rs @@ -39,8 +39,8 @@ where return Ok(vo); } - async fn get_email(&self, email: String, name: String) -> Result { - let wrapper = RB.new_wrapper().eq("name", name).eq("email",email); + async fn get_user_email(&self, user_email: String, name: String) -> Result { + let wrapper = RB.new_wrapper().eq("name", name).eq("user_email",user_email); let detail: Entity = RB.fetch_by_wrapper(wrapper).await?; let vo = Dto::from(detail); return Ok(vo); @@ -108,6 +108,11 @@ where async fn del_by_column(&self, column: &str, column_value: &str) { RB.remove_by_column::(column, column_value).await; } + + async fn del_user_email(&self, user_email: String, email: String) { + let wrapper = RB.new_wrapper().eq("user_email", user_email).eq("email",email); + RB.remove_by_wrapper::(wrapper).await; + } /** * 批量删除实体 逻辑删除 */ diff --git a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/subscribe_mail_list_service.rs b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/subscribe_mail_list_service.rs index 76260e7b9c16ef9eb7f851f2263bd143a5907ccb..6f99d5eff3df0039798a579a25cd1318cb3d284f 100644 --- a/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/subscribe_mail_list_service.rs +++ b/mail2list/mail2list_backend/mail2list_archive_unsubscribe/src/service/subscribe_mail_list_service.rs @@ -5,62 +5,95 @@ use crate::entity::sys_entitys::{CommonField, SubscribeMailList}; use crate::request::SubscribeMailListQuery; use crate::service::crud_service::CrudService; use crate::RB; -use mail2list_common::utils::send_email::SendMail; -use rbatis::wrapper::Wrapper; -use imap; +use mail2list_common::utils::{search::Search, send_email::SendMail}; use mailparse::*; +use rbatis::wrapper::Wrapper; + +use mail2list_common::utils::timeout::Timeout; +use std::time::Duration; +use native_tls::TlsConnector; +use std::error::Error; pub struct SubscribeMailListService {} impl SubscribeMailListService { - /** *退订 */ - pub async fn delete(&self, imap_server: &str, mine_email :&str,smtp_server: &str, password :&str, subject :&str, body :&str, name :&str) -> imap::error::Result> { - let client = imap::ClientBuilder::new(imap_server, 993).native_tls()?; - let mut imap_session = client - .login(mine_email, password) - .map_err(|e| e.0)?; - imap_session.select("INBOX")?; - let mut i = 1; - loop { - let i1 = i.to_string(); - let messages = imap_session.fetch(i1, "RFC822.HEADER")?; - let message = if let Some(m) = messages.iter().next() { - m - } else { - return Ok(None); + pub async fn delete( + &self, + imap_server: &str, + mine_email: &str, + smtp_server: &str, + password: &str, + subject: &str, + body: &str, + name: &str, + ) -> Result,Box> { + let timeout = Duration::from_secs(5); + let tls = TlsConnector::builder().build()?; + let client = Timeout::connect_all_timeout((imap_server, 993), imap_server, &tls, timeout)?; + let mut imap_session = client.login(mine_email, password).map_err(|e| e.0)?; + let inbox = imap_session.select("INBOX")?; + let unseen = inbox.unseen; + match unseen { + Some(len) => { + for i in 0 as u32..len { + let messages = + imap_session.fetch((inbox.exists - i).to_string(), "RFC822.HEADER")?; + let message = if let Some(m) = messages.iter().next() { + m + } else { + return Ok(None); + }; + let header = message.header().expect("message did not have a subject!"); + let parsed = parse_mail(header).unwrap(); + let mail = parsed.headers.get_first_value("From").unwrap(); + let pos = mail.rfind("<").unwrap(); + let (_, lst) = mail.split_at(pos + 1); + let mut user_email = lst.to_string(); + user_email.pop(); + let user_email1 = user_email.clone(); + let flag = self.get_user_email(user_email1, name.to_string()).await; + //找到此用户,则删除 + if flag.is_ok() { + let user_email2 = user_email.clone(); + let email = flag.unwrap().email.unwrap(); + let index = Search::search( + MAIL2LIST_CONFIG.email.mine_email.clone(), + email.clone(), + ); + SendMail::send_email( + &user_email2, + &MAIL2LIST_CONFIG.email.leave_email[index], + &MAIL2LIST_CONFIG.email.leave_smtp_server[index], + &MAIL2LIST_CONFIG.email.leave_email_password[index], + subject, + body, + ); + self.del_user_email(user_email2, email.clone()).await; + imap_session + .store(format!("{}", message.message), "+FLAGS (\\Seen)") + .unwrap(); + imap_session.expunge().unwrap(); + } else { + imap_session + .store(format!("{}", message.message), "+FLAGS (\\Seen)") + .unwrap(); + imap_session.expunge().unwrap(); + } + // //找不到 则继续遍历 直到遍历完所有邮箱 + // if user_email.is_empty() { + // break; + // } + } + } + None => {} }; - let header = message.header().expect("message did not have a subject!"); - let parsed = parse_mail(header).unwrap(); - let mail = parsed.headers.get_first_value("From").unwrap(); - let pos = mail.rfind("<").unwrap(); - let (_, lst) = mail.split_at(pos + 1); - let mut email = lst.to_string(); - email.pop(); - let email1 = email.clone(); - let flag = self.get_email(email1,name.to_string()).await; - //找到此用户,则删除 - if flag.is_ok() { - let email2 = email.clone(); - SendMail::send_email(&email2,&MAIL2LIST_CONFIG.email.leave_email,&MAIL2LIST_CONFIG.email.leave_smtp_server,&MAIL2LIST_CONFIG.email.leave_email_password,subject,body); - self.del_by_column("email",&email2).await; - imap_session.store(format!("{}", message.message), "+FLAGS (\\Deleted)").unwrap(); - imap_session.expunge().unwrap(); - }else { - imap_session.store(format!("{}", message.message), "+FLAGS (\\Deleted)").unwrap(); - imap_session.expunge().unwrap(); - } - //找不到 则继续遍历 直到遍历完所有邮箱 - i = i + 1; - if email.is_empty() { - break; - } - } - // be nice to the server and log out - imap_session.logout()?; - Ok(Some(true)) + + // be nice to the server and log out + imap_session.logout()?; + Ok(Some(true)) } } @@ -79,4 +112,4 @@ impl CrudService, target: String) -> usize { + let mut left: usize = 0; + let mut right: usize = nums.len(); + while left < right { + let mid = (left + right) / 2; + if nums[mid] < target { + left = mid + 1; + } else if nums[mid] > target { + right = mid; + } else { + return mid as usize; + } + } + 0 + } +} diff --git a/mail2list/mail2list_backend/mail2list_common/src/utils/send_email.rs b/mail2list/mail2list_backend/mail2list_common/src/utils/send_email.rs index 947a4c8049a7bb517d134fe1ea48e32991cbb652..8a8bb115a04bb173ee1b8984e1f97ffcb63735cf 100644 --- a/mail2list/mail2list_backend/mail2list_common/src/utils/send_email.rs +++ b/mail2list/mail2list_backend/mail2list_common/src/utils/send_email.rs @@ -2,34 +2,38 @@ extern crate lettre; extern crate lettre_email; extern crate mime; -use lettre_email::Email; use lettre::smtp::authentication::Credentials; use lettre::{SmtpClient, Transport}; +use lettre_email::Email; -pub struct SendMail{} +pub struct SendMail {} impl SendMail { - pub fn send_email(email_receiver: &str, mine_email :&str,smtp_server: &str, password :&str, subject :&str, body :&str) { + pub fn send_email( + email_receiver: &str, + mine_email: &str, + smtp_server: &str, + password: &str, + subject: &str, + body: &str, + ) { let email_receiver = email_receiver; - let mine_email = mine_email; + let mine_email = mine_email; let smtp_server = smtp_server; let password = password; //需要生成应用专用密码 let email = Email::builder() - .to(email_receiver) - .from(mine_email) - .subject(subject) - .text(body) - .build() - .unwrap(); - let creds = Credentials::new( - mine_email.to_string(), - password.to_string(), - ); + .to(email_receiver) + .from(mine_email) + .subject(subject) + .text(body) + .build() + .unwrap(); + let creds = Credentials::new(mine_email.to_string(), password.to_string()); // Open connection to Gmail let mut mailer = SmtpClient::new_simple(smtp_server) - .unwrap() - .credentials(creds) - .transport(); + .unwrap() + .credentials(creds) + .transport(); // Send the email let result = mailer.send(email.into()); if result.is_ok() { @@ -41,4 +45,4 @@ impl SendMail { print!("{:?}", result); mailer.close(); } -} \ No newline at end of file +} diff --git a/mail2list/mail2list_backend/mail2list_common/src/utils/timeout.rs b/mail2list/mail2list_backend/mail2list_common/src/utils/timeout.rs new file mode 100644 index 0000000000000000000000000000000000000000..518fbfe2cf63b2b5e4cd926fb1ef1e9bbfb7bd6f --- /dev/null +++ b/mail2list/mail2list_backend/mail2list_common/src/utils/timeout.rs @@ -0,0 +1,66 @@ +extern crate imap; +extern crate native_tls; + +use imap::Client; +use native_tls::TlsConnector; +use native_tls::TlsStream; +use std::error::Error; +use std::fmt; +use std::net::{SocketAddr, TcpStream, ToSocketAddrs}; +use std::time::Duration; + +pub struct Timeout{} + +impl Timeout { + // resolve address and try to connect to all in order + pub fn connect_all_timeout>( + addr: A, + domain: S, + ssl_connector: &TlsConnector, + timeout: Duration, + ) -> Result>, Box> { + let addrs = addr.to_socket_addrs()?; + + for addr in addrs { + match connect_timeout(&addr, &domain, ssl_connector, timeout) { + Ok(client) => return Ok(client), + Err(error) => eprintln!("couldn't connect to {}: {}", addr, error), + } + } + + Err(Box::new(TimeoutError)) + } + +} + +pub fn connect_timeout>( + addr: &SocketAddr, + domain: S, + ssl_connector: &TlsConnector, + timeout: Duration, +) -> Result>, Box> { + // the timeout is actually used with the initial TcpStream + let tcp_stream = TcpStream::connect_timeout(addr, timeout)?; + + let tls_stream = TlsConnector::connect(ssl_connector, domain.as_ref(), tcp_stream)?; + + let mut client = Client::new(tls_stream); + + // don't forget to wait for the IMAP protocol server greeting ;) + client.read_greeting()?; + + Ok(client) +} + +// very simple timeout error; instead of printing the errors immediately like in +// `connect_all_timeout`, you may want to collect and return them +#[derive(Debug)] +struct TimeoutError; + +impl fmt::Display for TimeoutError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "all addresses failed to connect") + } +} + +impl Error for TimeoutError {} \ No newline at end of file diff --git a/mail2list/mail2list_backend/mail2list_web/application.yml b/mail2list/mail2list_backend/mail2list_web/application.yml index 0dd3912d6d42e99061989a04ca23212db9f2f000..80577144fd5eb0a8ca117c8e66a6ba4f69890608 100644 --- a/mail2list/mail2list_backend/mail2list_web/application.yml +++ b/mail2list/mail2list_backend/mail2list_web/application.yml @@ -7,7 +7,7 @@ server: host: "0.0.0.0" port: "9999" #数据库地址 -database_url: "********************************" +database_url: "postgresql://agree:Bigdata123@47.94.142.147:5432/mail2list" #逻辑删除字段 logic_column: "del" logic_un_deleted: 0 @@ -24,16 +24,15 @@ log_rolling_type: "KeepNum(20)" log_level: "info" email: - mine_email: "********************************" - smtp_server: "********************************" - password: "********************************" - imap_server: "********************************" + #此处应该是一个数组 密码以及服务等都应该是一个数组 来对应多个服务 + mine_email: ["529978097@qq.com","180859181@qq.com"] + smtp_server: ["smtp.qq.com","smtp.qq.com"] + password: ["sbvsrwyvunaibjef","evbdadwthgcdcbcf"] + imap_server: ["imap.qq.com","imap.qq.com"] #一个退订邮箱管理一个社区 - leave_email : "********************************" - leave_email_password : "********************************" - leave_name: "********************************" - leave_smtp_server: "********************************" - leave_imap_server: "********************************" - - + leave_email : ["529978097@qq.com","180859181@qq.com"] + leave_email_password : ["sbvsrwyvunaibjef","evbdadwthgcdcbcf"] + leave_name: ["A-Tune","rust"] + leave_smtp_server: ["smtp.qq.com","smtp.qq.com"] + leave_imap_server: ["imap.qq.com","imap.qq.com"] diff --git a/mail2list/mail2list_backend/mail2list_web/src/config/config.rs b/mail2list/mail2list_backend/mail2list_web/src/config/config.rs index ac69e524d684262da2ade83f1c1e0c2054dbd6b2..838ef04022a4149f29a4fdab9125f4535ce74c04 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/config/config.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/config/config.rs @@ -7,15 +7,15 @@ pub struct ServerConfig{ #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct MailConfig{ - pub mine_email : String, - pub password : String, - pub smtp_server : String, - pub imap_server : String, - pub leave_email : String, - pub leave_email_password : String, - pub leave_smtp_server : String, - pub leave_imap_server : String, - pub leave_name : String, + pub mine_email : Vec, + pub password : Vec, + pub smtp_server : Vec, + pub imap_server : Vec, + pub leave_email : Vec, + pub leave_email_password : Vec, + pub leave_smtp_server : Vec, + pub leave_imap_server : Vec, + pub leave_name : Vec, } ///服务启动配置 diff --git a/mail2list/mail2list_backend/mail2list_web/src/controller/archive_mail_list_controller.rs b/mail2list/mail2list_backend/mail2list_web/src/controller/archive_mail_list_controller.rs index aacd3beb3c42dda6b3a0620a6628470ccc0c3d21..447e3c6e4b23d8b29e28ccd3c4b619a487f2706e 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/controller/archive_mail_list_controller.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/controller/archive_mail_list_controller.rs @@ -1,6 +1,6 @@ use crate::REQUEST_CONTEXT; -use crate::{request::ArchiveMailListQuery,service::crud_service::CrudService, CONTEXT}; -use axum::extract::{Path, Query}; +use crate::{service::crud_service::CrudService, CONTEXT}; +use axum::extract::{Path}; use axum::response::IntoResponse; use mail2list_common::RespVO; @@ -12,9 +12,8 @@ use mail2list_common::RespVO; *desc:用户查询 *author:zhaorunqi */ -pub async fn list(arg: Option>) -> impl IntoResponse { - let arg = arg.unwrap(); - let vo = CONTEXT.archive_mail_list_service.list_archive(&arg).await; +pub async fn list(Path(name): Path) -> impl IntoResponse { + let vo = CONTEXT.archive_mail_list_service.list_archive(name).await; RespVO::from_result(&vo).resp_json() } /** @@ -22,8 +21,8 @@ pub async fn list(arg: Option>) -> impl IntoResponse *desc:查询 *author:zhaorunqi */ -pub async fn get_by_id(Path(id): Path) -> impl IntoResponse { - let vo = CONTEXT.archive_mail_list_service.get(id).await; +pub async fn get_by_message_id(Path(message_id): Path) -> impl IntoResponse { + let vo = CONTEXT.archive_mail_list_service.get_message_list_by_message_id(message_id).await; RespVO::from_result(&vo).resp_json() } diff --git a/mail2list/mail2list_backend/mail2list_web/src/controller/subscribe_mail_list_controller.rs b/mail2list/mail2list_backend/mail2list_web/src/controller/subscribe_mail_list_controller.rs index d46dd7bd5564f0d3b8dbbaeed920aca57cae438b..9ca4c58c9002cf22420d5ab94eb535a767e8261f 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/controller/subscribe_mail_list_controller.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/controller/subscribe_mail_list_controller.rs @@ -12,18 +12,6 @@ use mail2list_common::RespVO; *desc:保存 *author:zhaorunqi */ -// pub async fn save(Json(arg): Json) -> impl IntoResponse { -// let context = CONTAINER.get::(); -// let user = arg; -// if let Err(e) = user.validate() { -// return RespVO::<()>::from_error(&Error::E(e.to_string())).resp_json(); -// } - -// context.sys_user_service.save_info(user).await; - -// return RespVO::from(&"保存成功".to_string()).resp_json(); -// } - pub async fn list(arg: Option>) -> impl IntoResponse { let arg = arg.unwrap(); let vo = CONTEXT.subscribe_mail_list_service.list(&arg).await; @@ -33,12 +21,8 @@ pub async fn list(arg: Option>) -> impl IntoRespon pub async fn save(Json(arg): Json) -> impl IntoResponse { let flag = CONTEXT.subscribe_mail_list_service.save_info(arg).await; if flag == true { - RespVO::from(&"邮件已发送,请查看邮箱并回复".to_string()).resp_json() + RespVO::from(&"订阅成功".to_string()).resp_json() } else { RespVO::from(&"用户已订阅".to_string()).resp_json() } -} - -pub async fn delete(imap_server: &str, mine_email :&str,smtp_server: &str, password :&str, name :&str) { - CONTEXT.subscribe_mail_list_service.delete(imap_server, mine_email, smtp_server,password, "退订成功","",name).await; } \ No newline at end of file diff --git a/mail2list/mail2list_backend/mail2list_web/src/dao/mapper.rs b/mail2list/mail2list_backend/mail2list_web/src/dao/mapper.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ff4d5509868109ebdf8d568526ee99ae2064a0cf 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/dao/mapper.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/dao/mapper.rs @@ -0,0 +1,13 @@ +use crate::entity::sys_entitys::ArchiveMailList; +use rbatis::rbatis::Rbatis; + +//查询用户所有菜单 +#[py_sql(" select p.id,p.name,p.from_email,p.create_time,p.subject,p.body,p.message_id,p.in_reply_to,p.reference,adf.create_time + from archive_mail_list p inner join + archive_mail_list adf on p.reference like CONCAT('%', adf.message_id, '%') + where adf.message_id = #{message_id}")] +pub async fn get_message_list_by_message_id(rb: &Rbatis,message_id: &str) -> Option> {} + +#[py_sql("select id,name,from_email,create_time,subject,body,message_id,in_reply_to,reference from archive_mail_list + where reference is NULL and name=#{name} order by create_time desc")] + pub async fn get_archive_list(rb: &Rbatis,name: &str) -> Option> {} diff --git a/mail2list/mail2list_backend/mail2list_web/src/dao/mod.rs b/mail2list/mail2list_backend/mail2list_web/src/dao/mod.rs index 3607aab27d49a9190e19a9ad385feec30e092eb1..514bb3d781d82d939092b787c0223284815d7bf8 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/dao/mod.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/dao/mod.rs @@ -2,6 +2,7 @@ use crate::MAIL2LIST_CONFIG; use rbatis::rbatis::Rbatis; pub mod interceptor; +pub mod mapper; use interceptor::*; ///实例化 rbatis orm 连接池 diff --git a/mail2list/mail2list_backend/mail2list_web/src/dto/subscribe_mail_list_dto.rs b/mail2list/mail2list_backend/mail2list_web/src/dto/subscribe_mail_list_dto.rs index e8849271ce9aa460ccc07c6824bb9d8fe577ca6a..c6e64c9ed8af98307bb60e4f2009de57113fec60 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/dto/subscribe_mail_list_dto.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/dto/subscribe_mail_list_dto.rs @@ -7,6 +7,7 @@ pub struct SubscribeMailListDTO { pub id: Option, pub name: Option, #[validate(email)] + pub user_email: Option, pub email: Option, pub username: Option, } @@ -14,6 +15,7 @@ impl_field_name_method!(SubscribeMailListDTO { id, name, email, + user_email, username }); impl Into for SubscribeMailListDTO { @@ -22,6 +24,7 @@ impl Into for SubscribeMailListDTO { id: self.id, name: self.name, email: self.email, + user_email: self.user_email, username: self.username } } @@ -33,6 +36,7 @@ impl From for SubscribeMailListDTO { id: arg.id, name: arg.name, email: arg.email, + user_email: arg.user_email, username: arg.username, } } diff --git a/mail2list/mail2list_backend/mail2list_web/src/entity/sys_entitys.rs b/mail2list/mail2list_backend/mail2list_web/src/entity/sys_entitys.rs index 892f73e3566413141e4a7003e0576142df974fa2..15877b0cff3ee3d5c924cb3ab8222855e5ae6e45 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/entity/sys_entitys.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/entity/sys_entitys.rs @@ -34,12 +34,14 @@ impl_field_name_method!(MailList { pub struct SubscribeMailList { pub id: Option, pub name: Option, + pub user_email: Option, pub email: Option, pub username: Option, } impl_field_name_method!(SubscribeMailList { id, name, + user_email, email, username, }); diff --git a/mail2list/mail2list_backend/mail2list_web/src/request/mod.rs b/mail2list/mail2list_backend/mail2list_web/src/request/mod.rs index 92fd18e8a4de0fa2fe87ffccef354dedfde800d8..61be298a32fd21452aed29ed0086e0b241126354 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/request/mod.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/request/mod.rs @@ -8,4 +8,5 @@ pub struct RequestModel { pub username: String, pub agency_code: String, pub product_code: String, + pub message_id: String, } diff --git a/mail2list/mail2list_backend/mail2list_web/src/request/request_model.rs b/mail2list/mail2list_backend/mail2list_web/src/request/request_model.rs index 61eaf4ed981da5d13eecabe75dc1002c6a142221..f2a845ec288066293274ac538ef8a226e9795316 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/request/request_model.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/request/request_model.rs @@ -21,4 +21,6 @@ pub struct SubscribeMailListQuery { #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ArchiveMailListQuery { pub ids: Option>, + pub message_id: Option, + pub name: Option, } \ No newline at end of file diff --git a/mail2list/mail2list_backend/mail2list_web/src/routers/maillist.rs b/mail2list/mail2list_backend/mail2list_web/src/routers/maillist.rs index a9bb4fac106ccd5cb459f2bdd9dcaa0824d2f375..0f38c6f69ea27917624238c3dab98845f11e6d93 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/routers/maillist.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/routers/maillist.rs @@ -18,5 +18,6 @@ pub fn routers() -> Router { "/menu/subscribe", get(subscribe_mail_list_controller::list).post(subscribe_mail_list_controller::save) ) - .route("/archive/list", get(archive_mail_list_controller::list)) + .route("/archive/list/:name", get(archive_mail_list_controller::list)) + .route("/archive/getListByMessageId/:message_id", get(archive_mail_list_controller::get_by_message_id)) } diff --git a/mail2list/mail2list_backend/mail2list_web/src/service/archive_mail_list_service.rs b/mail2list/mail2list_backend/mail2list_web/src/service/archive_mail_list_service.rs index e6a5a4aa65f8df06813418c60887c0465afc6920..5ac06c57345f21f745f8c0b9b84265d644294f7c 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/service/archive_mail_list_service.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/service/archive_mail_list_service.rs @@ -1,11 +1,11 @@ -use std::collections::HashMap; - +use crate::dao::mapper::{get_message_list_by_message_id,get_archive_list}; use crate::dto::archive_mail_list_dto::ArchiveMailListDTO; use crate::entity::sys_entitys::{CommonField, ArchiveMailList}; use crate::request::ArchiveMailListQuery; use crate::service::crud_service::CrudService; use crate::{RB}; use rbatis::wrapper::Wrapper; +use mail2list_common::error::Result; /** *struct:ArchiveMailListService @@ -17,13 +17,30 @@ pub struct ArchiveMailListService {} impl ArchiveMailListService { - fn build(&self, menus: Vec) -> Vec { - let mut result = HashMap::with_capacity(menus.capacity()); - let data = vec![]; - for x in menus { - result.insert(x.id.clone().unwrap_or_default(), x); + pub async fn get_message_list_by_message_id(&self,message_id: String) -> Result> { + let one = self.get_message_id(message_id.clone()).await.unwrap(); + let result = get_message_list_by_message_id(&RB,message_id.as_str()).await.unwrap(); + let mut vec = vec![]; + vec.push(ArchiveMailListDTO::from(one)); + for r in result.unwrap() { + let r1 = r.clone(); + vec.push(ArchiveMailListDTO::from(r)); + let message_id = r1.message_id.unwrap(); + let result = get_message_list_by_message_id(&RB,message_id.as_str()).await.unwrap(); + for r2 in result.unwrap() { + vec.push(ArchiveMailListDTO::from(r2)); + } + } + Ok(vec) + } + + pub async fn list_archive(&self, name: String) -> Result> { + let result = get_archive_list(&RB,name.as_str()).await.unwrap(); + let mut vec = vec![]; + for r in result.unwrap() { + vec.push(ArchiveMailListDTO::from(r)); } - data + Ok(vec) } } impl Default for ArchiveMailListService { diff --git a/mail2list/mail2list_backend/mail2list_web/src/service/crud_service.rs b/mail2list/mail2list_backend/mail2list_web/src/service/crud_service.rs index 0cb0f03d8b020dc67c159f157de35f7cecdee617..9233c217093dd1a87e6ed894bec3cf242c5dd97e 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/service/crud_service.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/service/crud_service.rs @@ -1,10 +1,8 @@ -use crate::entity::pagedata::PageData; use crate::entity::sys_entitys::CommonField; use crate::{RB, REQUEST_CONTEXT}; use async_trait::async_trait; use mail2list_common::error::Result; use rbatis::crud::{CRUDTable, Skip, CRUD}; -use rbatis::plugin::page::{Page, PageRequest}; use rbatis::wrapper::Wrapper; use serde::de::DeserializeOwned; use serde::Serialize; @@ -46,9 +44,9 @@ where Ok(vos) } - async fn list_archive(&self, arg: &Params) -> Result> { + async fn list_archive(&self, arg: &Params, name: &str) -> Result> { //构建查询条件 - let wrapper = Self::get_wrapper(arg).is_null("in_reply_to").order_by(false,&["create_time"]); + let wrapper = Self::get_wrapper(arg).eq("name",name).is_null("reference").order_by(false,&["create_time"]); //执行查询 let list: Vec = RB.fetch_list_by_wrapper(wrapper).await?; let mut vos = vec![]; @@ -80,6 +78,14 @@ where return Ok(vo); } + async fn get_message_id(&self, message_id: String) -> Result { + let wrapper = RB.new_wrapper().eq("message_id", message_id); + let detail: Entity = RB.fetch_by_wrapper(wrapper).await?; + let vo = Dto::from(detail); + return Ok(vo); + } + + async fn get_email(&self, email: String, name: String) -> Result { let wrapper = RB.new_wrapper().eq("name", name).eq("email",email); let detail: Entity = RB.fetch_by_wrapper(wrapper).await?; diff --git a/mail2list/mail2list_backend/mail2list_web/src/service/subscribe_mail_list_service.rs b/mail2list/mail2list_backend/mail2list_web/src/service/subscribe_mail_list_service.rs index f314e8635fdab76659652472a6b8f1a1c27e70a7..dfcadb687387b52803dc59c6f3ce430351720f7e 100644 --- a/mail2list/mail2list_backend/mail2list_web/src/service/subscribe_mail_list_service.rs +++ b/mail2list/mail2list_backend/mail2list_web/src/service/subscribe_mail_list_service.rs @@ -5,13 +5,10 @@ use crate::entity::sys_entitys::{CommonField, SubscribeMailList}; use crate::request::SubscribeMailListQuery; use crate::service::crud_service::CrudService; use crate::RB; -use mail2list_common::utils::receive_mail::ReceiveMail; -use mail2list_common::utils::send_email::SendMail; +use mail2list_common::utils::{receive_mail::ReceiveMail, send_email::SendMail, search::Search}; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use rbatis::wrapper::Wrapper; -use imap; -use mailparse::*; /** *struct:SubscribeMailListService @@ -31,16 +28,17 @@ impl SubscribeMailListService { .take(30) .map(char::from) .collect(); - let email = dto.email.clone(); - let email1 = email.unwrap(); + let user_email = dto.user_email.clone(); + let email1 = user_email.unwrap(); let email2 = email1.clone(); + let email = dto.email.clone().unwrap(); + let index = Search::search(MAIL2LIST_CONFIG.email.mine_email.clone(),email); let username = dto.username.clone(); - let username1 = "".to_string(); + let username1 = String::new(); match username { Some(username1) => println!("username is true"), None => println!("username is empty"), }; - // let username1 = username.unwrap(); let name = dto.name.clone(); let name1 = name.unwrap(); let mut subject = "confirm+".to_string(); @@ -48,14 +46,14 @@ impl SubscribeMailListService { let mut body = "邮箱订阅确认\n您好,这是openeuler.org的邮件列表服务。\n我们收到来自以下邮箱的注册请求:\n\r".to_string(); body += &email2; body += &"\n在开始使用本站的邮件列表服务之前,请确认这是您的邮箱。你可以通过回复此消息来进行确认,请保持回信的主题不变。\n若您不想注册该邮箱,请忽略此消息。若您怀疑自己被恶意订阅了该列表或有其他任何疑问,请联系:\n\r".to_string(); - body += &MAIL2LIST_CONFIG.email.mine_email; + body += &MAIL2LIST_CONFIG.email.mine_email[index]; let mut success_body = "欢迎使用".to_string(); success_body += &name1; success_body += &"邮件列表!\n要通过此列表交流,请发送电子邮件至:\n\r".to_string(); - success_body += &MAIL2LIST_CONFIG.email.mine_email; + success_body += &MAIL2LIST_CONFIG.email.mine_email[index]; success_body += &"\n\n取消订阅或调整选项请发送电子邮件至:\n\r".to_string(); - success_body += &MAIL2LIST_CONFIG.email.leave_email; + success_body += &MAIL2LIST_CONFIG.email.leave_email[index]; let flag = self.get_email(email2, name1).await; if flag.is_err() { @@ -63,29 +61,28 @@ impl SubscribeMailListService { //发送邮箱 SendMail::send_email( email1.as_str(), - MAIL2LIST_CONFIG.email.mine_email.as_str(), - MAIL2LIST_CONFIG.email.smtp_server.as_str(), - MAIL2LIST_CONFIG.email.password.as_str(), + MAIL2LIST_CONFIG.email.mine_email[index].as_str(), + MAIL2LIST_CONFIG.email.smtp_server[index].as_str(), + MAIL2LIST_CONFIG.email.password[index].as_str(), subject.as_str(), body.as_str(), ); //接收邮件 此处要判断是否接收到 要是没有收到则一直等待 直到收到 此时我们可以启动其他服务 loop { let flag = ReceiveMail::receive_mail( - MAIL2LIST_CONFIG.email.imap_server.as_str(), + MAIL2LIST_CONFIG.email.imap_server[index].as_str(), email1.as_str(), - MAIL2LIST_CONFIG.email.mine_email.as_str(), - MAIL2LIST_CONFIG.email.smtp_server.as_str(), - MAIL2LIST_CONFIG.email.password.as_str(), + MAIL2LIST_CONFIG.email.mine_email[index].as_str(), + MAIL2LIST_CONFIG.email.smtp_server[index].as_str(), + MAIL2LIST_CONFIG.email.password[index].as_str(), subject.as_str(), success_body.as_str(), ); match flag { - Ok(flag) => { - if flag == true { - break; - } + Ok(flag) if flag == true => { + break; } + Ok(flag) => {} Err(err) => panic!("Problem receive the mail: {:?}", err), }; } @@ -96,53 +93,6 @@ impl SubscribeMailListService { return false; } - - pub async fn delete(&self, imap_server: &str, mine_email :&str,smtp_server: &str, password :&str, subject :&str, body :&str, name :&str) -> imap::error::Result> { - let client = imap::ClientBuilder::new(imap_server, 993).native_tls()?; - // the client we have here is unauthenticated. - // to do anything useful with the e-mails, we need to log in - let mut imap_session = client - .login(mine_email, password) - .map_err(|e| e.0)?; - // we want to fetch the first email in the INBOX mailbox - imap_session.select("INBOX")?; - // fetch message number 1 in this mailbox, along with its RFC822 field. - // RFC 822 dictates the format of the body of e-mails - let mut i = 1; - loop { - let i1 = i.to_string(); - let messages = imap_session.fetch(i1, "RFC822.HEADER")?; - let message = if let Some(m) = messages.iter().next() { - m - } else { - return Ok(None); - }; - // extract the message's body - let header = message.header().expect("message did not have a subject!"); - let parsed = parse_mail(header).unwrap(); - let mail = parsed.headers.get_first_value("From").unwrap(); - let pos = mail.rfind("<").unwrap(); - let (_, lst) = mail.split_at(pos + 1); - let mut email = lst.to_string(); - email.pop(); - let email1 = email.clone(); - let flag = self.get_email(email1,name.to_string()).await; - //找到此用户,则删除 - if flag.is_ok() { - let email2 = email.clone(); - SendMail::send_email(&email2,&MAIL2LIST_CONFIG.email.leave_email,&MAIL2LIST_CONFIG.email.leave_smtp_server,&MAIL2LIST_CONFIG.email.leave_email_password,subject,body); - self.del_by_column("email",&email2).await; - } - //找不到 则继续遍历 直到遍历完所有邮箱 - i = i + 1; - if email.is_empty() { - break; - } - } - // be nice to the server and log out - imap_session.logout()?; - Ok(Some(true)) - } } impl Default for SubscribeMailListService { diff --git a/mail2list/vue-mail2list-web/src/components/pages/archive/index.vue b/mail2list/vue-mail2list-web/src/components/pages/archive/index.vue index b1d899d049d1f4c535145f4464d11e7f74e096a0..71829bbadb9a71940f5872c4f1f9cd81f2035400 100644 --- a/mail2list/vue-mail2list-web/src/components/pages/archive/index.vue +++ b/mail2list/vue-mail2list-web/src/components/pages/archive/index.vue @@ -19,10 +19,12 @@ -
+ - + More --> - More - -
  • - - Reply - + More