Unverified Commit 66172b86 authored by Vasili Novikov's avatar Vasili Novikov
Browse files

Fix email sending

parent 962cfd5c
Showing with 34 additions and 24 deletions
+34 -24
......@@ -15,3 +15,6 @@ trim_trailing_whitespace = false
[*.yml]
indent_size = 2
[*.toml]
indent_size = 2
......@@ -20,7 +20,7 @@ field_count = "0.1.1"
field_count_derive = "0.1.1"
hex = "0.4.3"
lazy_static = "1.4.0"
lettre = { version = "0.10.0-rc.3", default-features = false, features = ["rustls-tls", "builder", "smtp-transport"] }
lettre = { version = "0.10.0-rc.3", default-features = false, features = ["builder", "rustls-tls", "smtp-transport"] }
libc = "0.2.98"
log = "0.4.14"
percent-encoding = "2.1.0"
......
......@@ -107,7 +107,7 @@ pub struct CliOptions {
/// Running on loopback interface (127.0.0.1) means that only apps
/// from within the same computer will be able to access Pod.
/// This option might be used during development as an alternative to self-signed certificates.
#[structopt(short = "t", long)]
#[structopt(short = "t", long, env = "POD_NON_TLS")]
pub non_tls: bool,
/// Unsafe version of --non-tls that runs on a public network, e.g. "http://0.0.0.0".
......@@ -128,23 +128,23 @@ pub struct CliOptions {
/// Run server as a "SharedServer". See `/docs/SharedServer.md` documentation
/// for details on what it is, and how it works.
#[structopt(long)]
#[structopt(long, env)]
pub shared_server: bool,
/// SMTP relay server to use (advanced option).
#[structopt(long)]
#[structopt(long, env)]
pub email_smtp_relay: Option<String>,
/// SMTP relay server port to use (advanced option).
#[structopt(long)]
pub email_smtp_port: Option<u16>,
#[structopt(long, default_value = "465", env)]
pub email_smtp_port: u16,
/// SMTP relay server user (advanced option).
#[structopt(long)]
#[structopt(long, env)]
pub email_smtp_user: Option<String>,
/// SMTP relay server password (advanced option).
#[structopt(long)]
#[structopt(long, env)]
pub email_smtp_password: Option<String>,
}
......@@ -192,7 +192,7 @@ pub mod tests {
insecure_http_headers: false,
shared_server: false,
email_smtp_relay: None,
email_smtp_port: None,
email_smtp_port: 465,
email_smtp_user: None,
email_smtp_password: None,
}
......
......@@ -8,8 +8,8 @@ pub const FILES_DIR: &str = "./data/files";
/// (in future, the files should also be s3-uploaded).
pub const FILES_FINAL_SUBDIR: &str = "final";
pub const PLUGIN_EMAIL_SENDER: &str = "Memri plugin <noreply@memri.io>";
pub const PLUGIN_EMAIL_SUBJECT_PREFIX: &str = "Memri plugin notification: ";
pub const PLUGIN_EMAIL_FOOTER: &str = "This is an automated email, do not reply\
\
pub const PLUGIN_EMAIL_SUBJECT_PREFIX: &str = "Memri plugin message: ";
pub const PLUGIN_EMAIL_FOOTER: &str =
"This is an automated message from a Memri plugin, do not reply.
";
use crate::api_model::SendEmail;
use crate::command_line_interface::CliOptions;
use crate::constants::PLUGIN_EMAIL_FOOTER;
use crate::constants::PLUGIN_EMAIL_SENDER;
use crate::constants::PLUGIN_EMAIL_SUBJECT_PREFIX;
use crate::error::Result;
use lettre::message::Mailbox;
use lettre::transport::smtp::authentication::Credentials;
use lettre::Message;
use lettre::SmtpTransport;
use lettre::Transport;
pub fn send_email(email: SendEmail, cli: &CliOptions) -> Result<()> {
log::trace!("Starting to send email: {:?}", email);
match (
&cli.email_smtp_relay,
cli.email_smtp_port,
&cli.email_smtp_user,
&cli.email_smtp_password,
) {
(Some(relay), Some(port), Some(user), Some(password)) => {
let to: Mailbox = email.to.parse()?;
(Some(relay), Some(user), Some(password)) => {
let email = Message::builder()
.from(PLUGIN_EMAIL_SENDER.parse()?)
.to(to)
.from(format!("Memri plugin <{}>", user).parse()?)
.to(email.to.parse()?)
.subject(format!("{}{}", PLUGIN_EMAIL_SUBJECT_PREFIX, email.subject))
.body(format!("{}{}", PLUGIN_EMAIL_FOOTER, email.body))
.unwrap();
.body(format!("{}{}", PLUGIN_EMAIL_FOOTER, email.body))?;
let credentials: Credentials = Credentials::new(user.to_string(), password.to_string());
let server = SmtpTransport::relay(relay)?
.port(port)
.port(cli.email_smtp_port)
.credentials(credentials)
.timeout(Some(core::time::Duration::from_millis(5000)))
.build();
server.send(&email)?;
Ok(())
......
......@@ -85,6 +85,16 @@ impl From<lettre::address::AddressError> for Error {
}
}
impl From<lettre::error::Error> for Error {
fn from(err: lettre::error::Error) -> Error {
let msg = format!("Email error: {}", err);
Error {
code: StatusCode::BAD_REQUEST,
msg,
}
}
}
impl From<lettre::transport::smtp::Error> for Error {
fn from(err: lettre::transport::smtp::Error) -> Error {
let msg = format!("Email sending error: {}", err);
......
......@@ -197,7 +197,7 @@ pub async fn run_server(cli_options: CliOptions) {
.map(move |owner: String, body: Bytes| {
let cli = cli_options_arc_clone.deref();
let result = warp_endpoints::send_email(owner, init_db.deref(), body, cli);
let result = result.map(|result| warp::reply::json(&result));
let result = result.map(|()| warp::reply::json(&serde_json::json!({})));
respond_with_result(result)
});
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment