Better error-handling, emails for not-attending, language strings for JS errors

This commit contains the following changes:
* Better error handling: Previously, there was no proper handling in
  of email-related errors. Now, all error messages are caught and the
  user gets a nice landing page. The script will always try to contact
  the organizers of the wedding with information on the error.
* Emails for not-attending: This commit adds the possibility to send
  seperate emails to guests that attend and guests that cannot attend.
* Language strings for JavaScript errors: Previously, all JS errors were
  in Dutch. Now, they are configurable.
This commit is contained in:
2019-09-04 01:27:43 +02:00
parent 454175755a
commit ac77c9064a
4 changed files with 191 additions and 32 deletions

View File

@@ -102,7 +102,8 @@ fn validate_name(name: &String) -> bool {
fn validate_email(email: &String) -> bool {
// Check if the emailaddress is valid
Regex::new(r"^[a-zA-Z0-9\.\-]+@[a-zA-Z0-9\-]+\.[a-zA-Z]+$").unwrap().is_match(email)
// This function is not completely correct: emailregex.com
Regex::new(r"^[a-zA-Z0-9\.\-_]+@[a-zA-Z0-9\-\.]+\.[a-zA-Z]+$").unwrap().is_match(email)
}
fn strip_tld(url: &str) -> Option<String> {
@@ -121,7 +122,7 @@ fn strip_tld(url: &str) -> Option<String> {
fn send_email(to_name: &String, to_address: &String,
subject: &String, message: &String,
attachment: Option<&String>, settings: &State<Settings>) {
attachment: Option<&String>, settings: &State<Settings>) -> Result<(), String> {
// Load HJSON config
let email_credentials = &settings.email_credentials;
@@ -166,10 +167,17 @@ fn send_email(to_name: &String, to_address: &String,
// Configure expected authentication mechanism
.authentication_mechanism(Mechanism::Plain).transport();
let result = mailer.send(email.into());
assert!(result.is_ok());
match mailer.send(email.into()) {
Ok(_x) => {
mailer.close();
return Ok(());
},
Err(e) => {
mailer.close();
return Err(e.to_string());
}
};
mailer.close();
}
//////////////////////////
@@ -181,9 +189,12 @@ fn submit_task (host: HostHeader,
user_input: Option<Form<OwnedUserInput>>,
client_addr: &ClientRealAddr,
ip_epoch: State<Mutex<HashMap<String, u64>>>) -> Redirect {
// Create struct with all language strings
let language_strings = lang_strings(host, &settings);
let result : Result<(), String>;
match user_input {
Some(x) => {
// Check input for anything strange or something that does not look like
@@ -219,15 +230,25 @@ fn submit_task (host: HostHeader,
}
};
send_email(&x.name,
&x.email,
&language_strings.email.subject,
&strfmt(&language_strings.email.message, &vars).unwrap(),
Some(&language_strings.email.attachment),
&settings);
}
else {
return Redirect::to("404");
if x.guests > 0 {
// Send email about attendaning wedding
result = send_email(&x.name,
&x.email,
&language_strings.attending_email.subject,
&strfmt(&language_strings.attending_email.message, &vars).unwrap(),
Some(&language_strings.attending_email.attachment),
&settings);
} else {
// Send email about not attending wedding
result = send_email(&x.name,
&x.email,
&language_strings.not_attending_email.subject,
&strfmt(&language_strings.not_attending_email.message, &vars).unwrap(),
None,
&settings);
}
} else {
result = Err("Validate e-mail or name went wrong.".to_string());
}
// Send a message to the sender's e-mailaddres to inform about
@@ -238,9 +259,6 @@ fn submit_task (host: HostHeader,
let mut rsvp_subject = String::new();
let mut rsvp_message = String::new();
rsvp_subject.push_str(&x.name);
rsvp_subject.push_str(" just responded to your event!");
rsvp_message.push_str("Name: ");
rsvp_message.push_str(&x.name);
rsvp_message.push_str("<br />Emailaddress: ");
@@ -250,10 +268,43 @@ fn submit_task (host: HostHeader,
rsvp_message.push_str("<br />Message:<br /><br />");
rsvp_message.push_str(&x.message);
send_email(&smtp_name, &smtp_username, &rsvp_subject, &rsvp_message, None, &settings);
Redirect::to(format!("/thanks/{}", urlencoding::encode(&x.name)))
// Create subject and add error message (if necessary)
let mut error = false;
rsvp_subject.push_str(&x.name);
match result {
Ok(_x) => {
rsvp_subject.push_str(" just responded to your event!");
},
Err(e) => {
rsvp_subject.push_str(" just responded to your event! (ERROR)");
rsvp_message.push_str("<br />Error message:<br />");
rsvp_message.push_str(&e);
error = true;
}
};
// Also check if e-mail to the organisation didn't go through!
match send_email(&smtp_name,
&smtp_username,
&rsvp_subject,
&rsvp_message,
None,
&settings) {
Ok(_x) => {},
Err(_e) => {
return Redirect::to("email-issue");
}
};
// Redirect to thank you page or to error page
if error {
return Redirect::to("email-issue");
} else {
return Redirect::to(format!("/thanks/{}", urlencoding::encode(&x.name)));
}
}
None => Redirect::to("404")
None => Redirect::to("email-issue")
}
}
@@ -274,6 +325,15 @@ fn thanks(name: String, host:HostHeader, settings: State<Settings>) -> Template
message : language_strings.thanks.message.clone()})
}
#[get("/email-issue")]
fn email_issue(host:HostHeader, settings: State<Settings>) -> Template {
// Create struct with all language strings
let language_strings = lang_strings(host, &settings).clone();
// Create template with appropriate strings
Template::render("message", &language_strings.email_issue)
}
#[get("/spam")]
fn spam(host:HostHeader, settings: State<Settings>) -> Template {
// Create struct with all language strings
@@ -314,6 +374,7 @@ fn main() {
.mount("/", routes![index])
.mount("/", routes![thanks])
.mount("/", routes![spam])
.mount("/", routes![email_issue])
.mount("/", routes![submit_task])
.mount("/css", StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/css")))
.mount("/js", StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/js")))