Resultify Smtp::send

This commit is contained in:
Alexander Krotov
2019-11-29 16:08:37 +01:00
committed by Floris Bruynooghe
parent 20ce5f6967
commit 14287b12ae
2 changed files with 34 additions and 13 deletions

View File

@@ -20,6 +20,7 @@ use crate::message::MsgId;
use crate::message::{self, Message, MessageState}; use crate::message::{self, Message, MessageState};
use crate::mimefactory::{vec_contains_lowercase, Loaded, MimeFactory}; use crate::mimefactory::{vec_contains_lowercase, Loaded, MimeFactory};
use crate::param::*; use crate::param::*;
use crate::smtp::SmtpError;
use crate::sql; use crate::sql;
// results in ~3 weeks for the last backoff timespan // results in ~3 weeks for the last backoff timespan
@@ -184,11 +185,22 @@ impl Job {
// otherwise might send it twice. // otherwise might send it twice.
let mut smtp = context.smtp.lock().unwrap(); let mut smtp = context.smtp.lock().unwrap();
match smtp.send(context, recipients_list, body, self.job_id) { match smtp.send(context, recipients_list, body, self.job_id) {
Err(err) => { Err(SmtpError::SendError(err)) => {
// Remote error, retry later.
smtp.disconnect(); smtp.disconnect();
warn!(context, "smtp failed: {}", err); info!(context, "SMTP failed to send: {}", err);
self.try_again_later(TryAgain::AtOnce, Some(err.to_string())); self.try_again_later(TryAgain::AtOnce, Some(err.to_string()));
} }
Err(SmtpError::EnvelopeError(err)) => {
// Local error, job is invalid, do not retry.
smtp.disconnect();
warn!(context, "SMTP job is invalid: {}", err);
}
Err(SmtpError::NoTransport) => {
// Should never happen.
// It does not even make sense to disconnect here.
error!(context, "SMTP job failed because SMTP has no transport");
}
Ok(()) => { Ok(()) => {
// smtp success, update db ASAP, then delete smtp file // smtp success, update db ASAP, then delete smtp file
if 0 != self.foreign_id { if 0 != self.foreign_id {

View File

@@ -1,6 +1,8 @@
use lettre::smtp::client::net::*; use lettre::smtp::client::net::*;
use lettre::*; use lettre::*;
use failure::Fail;
use crate::constants::*; use crate::constants::*;
use crate::context::Context; use crate::context::Context;
use crate::error::Error; use crate::error::Error;
@@ -17,6 +19,16 @@ pub struct Smtp {
from: Option<EmailAddress>, from: Option<EmailAddress>,
} }
#[derive(Debug, Fail)]
pub enum SmtpError {
#[fail(display = "Envelope error: {}", _0)]
EnvelopeError(lettre::error::Error),
#[fail(display = "Send error: {}", _0)]
SendError(lettre::smtp::error::Error),
#[fail(display = "SMTP has no transport")]
NoTransport,
}
impl Smtp { impl Smtp {
/// Create a new Smtp instances. /// Create a new Smtp instances.
pub fn new() -> Self { pub fn new() -> Self {
@@ -144,7 +156,7 @@ impl Smtp {
recipients: Vec<EmailAddress>, recipients: Vec<EmailAddress>,
message: Vec<u8>, message: Vec<u8>,
job_id: u32, job_id: u32,
) -> Result<(), Error> { ) -> Result<(), SmtpError> {
let message_len = message.len(); let message_len = message.len();
let recipients_display = recipients let recipients_display = recipients
@@ -155,10 +167,8 @@ impl Smtp {
if let Some(ref mut transport) = self.transport { if let Some(ref mut transport) = self.transport {
let envelope = match Envelope::new(self.from.clone(), recipients) { let envelope = match Envelope::new(self.from.clone(), recipients) {
Ok(env) => env, Ok(envelope) => envelope,
Err(err) => { Err(e) => return Err(SmtpError::EnvelopeError(e)),
bail!("{}", err);
}
}; };
let mail = SendableEmail::new( let mail = SendableEmail::new(
envelope, envelope,
@@ -175,15 +185,14 @@ impl Smtp {
self.transport_connected = true; self.transport_connected = true;
Ok(()) Ok(())
} }
Err(err) => { Err(err) => return Err(SmtpError::SendError(err)),
bail!("SMTP failed len={}: error: {}", message_len, err);
}
} }
} else { } else {
bail!( warn!(
"uh? SMTP has no transport, failed to send to {:?}", context,
recipients_display "uh? SMTP has no transport, failed to send to {}", recipients_display
); );
return Err(SmtpError::NoTransport);
} }
} }
} }