1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::settings::structs::Settings;
use lettre::{
  message::{header, Mailbox, MultiPart, SinglePart},
  transport::smtp::{
    authentication::Credentials,
    client::{Tls, TlsParameters},
    extension::ClientId,
  },
  Address,
  Message,
  SmtpTransport,
  Transport,
};
use std::str::FromStr;

pub fn send_email(
  subject: &str,
  to_email: &str,
  to_username: &str,
  html: &str,
) -> Result<(), String> {
  let email_config = Settings::get().email().ok_or("no_email_setup")?;
  let domain = Settings::get().hostname();

  let (smtp_server, smtp_port) = {
    let email_and_port = email_config.smtp_server.split(':').collect::<Vec<&str>>();
    (
      email_and_port[0],
      email_and_port[1]
        .parse::<u16>()
        .expect("email needs a port"),
    )
  };

  let email = Message::builder()
    .from(
      email_config
        .smtp_from_address
        .parse()
        .expect("email from address isn't valid"),
    )
    .to(Mailbox::new(
      Some(to_username.to_string()),
      Address::from_str(to_email).expect("email to address isn't valid"),
    ))
    .subject(subject)
    .multipart(
      MultiPart::mixed().multipart(
        MultiPart::alternative()
          .singlepart(
            SinglePart::builder()
              .header(header::ContentType::TEXT_PLAIN)
              .body(html.to_string()),
          )
          .multipart(
            MultiPart::related().singlepart(
              SinglePart::builder()
                .header(header::ContentType::TEXT_HTML)
                .body(html.to_string()),
            ),
          ),
      ),
    )
    .expect("email built incorrectly");

  // don't worry about 'dangeous'. it's just that leaving it at the default configuration
  // is bad.
  let mut builder = SmtpTransport::builder_dangerous(smtp_server).port(smtp_port);

  // Set the TLS
  if email_config.use_tls {
    let tls_config = TlsParameters::new(smtp_server.to_string()).expect("the TLS backend is happy");
    builder = builder.tls(Tls::Wrapper(tls_config));
  }

  // Set the creds if they exist
  if let (Some(username), Some(password)) = (email_config.smtp_login, email_config.smtp_password) {
    builder = builder.credentials(Credentials::new(username, password));
  }

  let mailer = builder.hello_name(ClientId::Domain(domain)).build();

  let result = mailer.send(&email);

  match result {
    Ok(_) => Ok(()),
    Err(e) => Err(e.to_string()),
  }
}