Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions server/api/src/resource/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ pub async fn get_note(

let copy_note = note.clone();
tokio::spawn(async move {
send_email(&copy_note).await.unwrap();
if let Err(err) = send_email(&copy_note).await {
eprintln!("Error while sending email: {}", err);
}
});
}
}
Expand Down Expand Up @@ -288,7 +290,9 @@ pub async fn delete_note(
);

tokio::spawn(async move {
send_email(&note).await.unwrap();
if let Err(err) = send_email(&note).await {
eprintln!("Error while sending email: {}", err);
}
});
}

Expand Down
86 changes: 57 additions & 29 deletions server/api/src/utils/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,61 @@ pub async fn check_csrf_token(captcha: CsrfToken, state: &State<AppState>) -> Op
}

pub async fn send_email(note: &note::Model) -> anyhow::Result<bool> {
let host = env::var("SMTP_HOST").expect("SMTP_HOST is not set in .env file");
let port = env::var("SMTP_PORT").expect("SMTP_PORT is not set in .env file");
let user = env::var("SMTP_USER").expect("SMTP_USER is not set in .env file");
let pass = env::var("SMTP_PASS").expect("SMTP_PASS is not set in .env file");

let email = Message::builder()
.from(format!("Privnote <{}>", user).parse().unwrap())
.to(note.notify_email.as_ref().unwrap().parse().unwrap())
.subject("Your Privnote has been read")
.header(ContentType::TEXT_PLAIN)
.body(format!("privnote has been read: {}", note.id))
.unwrap();

let creds = Credentials::new(user.to_owned(), pass.to_owned());

// Open a remote connection to gmail
let mailer = SmtpTransport::relay(host.as_str())
.unwrap()
.credentials(creds)
.port(port.parse::<u16>().unwrap())
.build();

println!("Sending email to: {}", note.notify_email.as_ref().unwrap());

// Send the email
match mailer.send(&email) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
let host = env::var("SMTP_HOST").expect("SMTP_HOST is not set in .env file");
let port = env::var("SMTP_PORT").expect("SMTP_PORT is not set in .env file");
let user = env::var("SMTP_USER").expect("SMTP_USER is not set in .env file");
let pass = env::var("SMTP_PASS").expect("SMTP_PASS is not set in .env file");

println!("SMTP Config: {}:{}", host, port);
println!("SMTP User: {}", user);
println!("SMTP Pass length: {}", pass.len());

let email = Message::builder()
.from(format!("Privnote <{}>", user).parse().unwrap())
.to(note.notify_email.as_ref().unwrap().parse().unwrap())
.subject("Your Privnote has been read")
.header(ContentType::TEXT_PLAIN)
.body(format!("privnote has been read: {}", note.id))
.unwrap();

let creds = Credentials::new(user.to_owned(), pass.to_owned());

// Настройка TLS: STARTTLS для 587, implicit TLS (wrapper) для 465
use lettre::transport::smtp::client::{Tls, TlsParameters};
let tls_params = TlsParameters::builder(host.clone()).build().unwrap();
let tls_mode = if port == "465" { "implicit" } else { "starttls" };
println!("TLS mode: {}", tls_mode);
println!("Building SMTP transport...");

let mailer = match port.as_str() {
"465" => {
SmtpTransport::relay(host.as_str())
.unwrap()
.credentials(creds)
.port(465)
.tls(Tls::Wrapper(tls_params))
.build()
}
_ => {
SmtpTransport::starttls_relay(host.as_str())
.unwrap()
.credentials(creds)
.port(port.parse::<u16>().unwrap())
.build()
}
};

println!("SMTP transport built successfully");
println!("Sending email to: {}", note.notify_email.as_ref().unwrap());

match mailer.send(&email) {
Ok(_) => {
println!("Email sent successfully");
Ok(true)
}
Err(e) => {
println!("Failed to send email: {:?}", e);
Err(e.into())
}
}
}