smtp: retry immediately if connection is stale

This commit is contained in:
link2xt
2022-01-22 11:56:36 +00:00
parent 05a3c0c89b
commit f7f899f0a4
4 changed files with 52 additions and 9 deletions

View File

@@ -48,6 +48,7 @@
- allow removing quotes on existing drafts (#2950)
- update provider database (11 Jan 2022) #2959
- python: allow timeout for internal configure tracker API #2967
- Replace `SendMsgToSmtp` jobs which stored outgoing messages in blobdir with `smtp` SQL table #2939 #2966
### Fixed
- Fix: Make `add_parts()` not early-exit #2879

View File

@@ -318,7 +318,7 @@ impl Job {
return Status::RetryLater;
}
let status = smtp_send(context, recipients, body, smtp, msg_id, 0).await;
let status = smtp_send(context, &recipients, &body, smtp, msg_id, 0).await;
if matches!(status, Status::Finished(Ok(_))) {
// Remove additional SendMdn jobs we have aggregated into this one.
job_try!(kill_ids(context, &additional_job_ids).await);

View File

@@ -225,10 +225,16 @@ impl Smtp {
}
}
/// Tries to send a message.
///
/// Returns Status::Finished if sending the message should not be retried anymore,
/// Status::RetryLater if sending should be postponed and Status::RetryNow if it is suspected that
/// temporary failure is caused by stale connection, in which case a second attempt to send the
/// same message may be done immediately.
pub(crate) async fn smtp_send(
context: &Context,
recipients: Vec<async_smtp::EmailAddress>,
message: String,
recipients: &[async_smtp::EmailAddress],
message: &str,
smtp: &mut Smtp,
msg_id: MsgId,
rowid: i64,
@@ -241,7 +247,7 @@ pub(crate) async fn smtp_send(
smtp.connectivity.set_working(context).await;
let send_result = smtp
.send(context, recipients, message.into_bytes(), rowid)
.send(context, recipients, message.as_bytes(), rowid)
.await;
smtp.last_send_error = send_result.as_ref().err().map(|e| e.to_string());
@@ -362,7 +368,7 @@ pub(crate) async fn send_msg_to_smtp(
.await
.context("SMTP connection failure")
{
smtp.last_send_error = Some(format!("SMTP connection failure: {:#}", err));
smtp.last_send_error = Some(format!("{:#}", err));
return Err(err);
}
@@ -392,7 +398,43 @@ pub(crate) async fn send_msg_to_smtp(
)
.collect::<Vec<_>>();
let status = smtp_send(context, recipients_list, body, smtp, msg_id, rowid).await;
let status = match smtp_send(
context,
&recipients_list,
body.as_str(),
smtp,
msg_id,
rowid,
)
.await
{
Status::RetryNow => {
// Do a single retry immediately without increasing retry counter in case of stale
// connection.
info!(context, "Doing immediate retry to send message.");
// smtp_send just closed stale SMTP connection, reconnect and try again.
if let Err(err) = smtp
.connect_configured(context)
.await
.context("failed to reopen stale SMTP connection")
{
smtp.last_send_error = Some(format!("{:#}", err));
return Err(err);
}
smtp_send(
context,
&recipients_list,
body.as_str(),
smtp,
msg_id,
rowid,
)
.await
}
status => status,
};
match status {
Status::Finished(res) => {
if res.is_ok() {

View File

@@ -28,8 +28,8 @@ impl Smtp {
pub async fn send(
&mut self,
context: &Context,
recipients: Vec<EmailAddress>,
message: Vec<u8>,
recipients: &[EmailAddress],
message: &[u8],
rowid: i64,
) -> Result<()> {
let message_len_bytes = message.len();
@@ -53,7 +53,7 @@ impl Smtp {
let mail = SendableEmail::new(
envelope,
rowid.to_string(), // only used for internal logging
&message,
message,
);
if let Some(ref mut transport) = self.transport {