mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +03:00
smtp: retry immediately if connection is stale
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
- allow removing quotes on existing drafts (#2950)
|
- allow removing quotes on existing drafts (#2950)
|
||||||
- update provider database (11 Jan 2022) #2959
|
- update provider database (11 Jan 2022) #2959
|
||||||
- python: allow timeout for internal configure tracker API #2967
|
- 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
|
### Fixed
|
||||||
- Fix: Make `add_parts()` not early-exit #2879
|
- Fix: Make `add_parts()` not early-exit #2879
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ impl Job {
|
|||||||
return Status::RetryLater;
|
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(_))) {
|
if matches!(status, Status::Finished(Ok(_))) {
|
||||||
// Remove additional SendMdn jobs we have aggregated into this one.
|
// Remove additional SendMdn jobs we have aggregated into this one.
|
||||||
job_try!(kill_ids(context, &additional_job_ids).await);
|
job_try!(kill_ids(context, &additional_job_ids).await);
|
||||||
|
|||||||
52
src/smtp.rs
52
src/smtp.rs
@@ -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(
|
pub(crate) async fn smtp_send(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
recipients: Vec<async_smtp::EmailAddress>,
|
recipients: &[async_smtp::EmailAddress],
|
||||||
message: String,
|
message: &str,
|
||||||
smtp: &mut Smtp,
|
smtp: &mut Smtp,
|
||||||
msg_id: MsgId,
|
msg_id: MsgId,
|
||||||
rowid: i64,
|
rowid: i64,
|
||||||
@@ -241,7 +247,7 @@ pub(crate) async fn smtp_send(
|
|||||||
smtp.connectivity.set_working(context).await;
|
smtp.connectivity.set_working(context).await;
|
||||||
|
|
||||||
let send_result = smtp
|
let send_result = smtp
|
||||||
.send(context, recipients, message.into_bytes(), rowid)
|
.send(context, recipients, message.as_bytes(), rowid)
|
||||||
.await;
|
.await;
|
||||||
smtp.last_send_error = send_result.as_ref().err().map(|e| e.to_string());
|
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
|
.await
|
||||||
.context("SMTP connection failure")
|
.context("SMTP connection failure")
|
||||||
{
|
{
|
||||||
smtp.last_send_error = Some(format!("SMTP connection failure: {:#}", err));
|
smtp.last_send_error = Some(format!("{:#}", err));
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +398,43 @@ pub(crate) async fn send_msg_to_smtp(
|
|||||||
)
|
)
|
||||||
.collect::<Vec<_>>();
|
.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 {
|
match status {
|
||||||
Status::Finished(res) => {
|
Status::Finished(res) => {
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ impl Smtp {
|
|||||||
pub async fn send(
|
pub async fn send(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
recipients: Vec<EmailAddress>,
|
recipients: &[EmailAddress],
|
||||||
message: Vec<u8>,
|
message: &[u8],
|
||||||
rowid: i64,
|
rowid: i64,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let message_len_bytes = message.len();
|
let message_len_bytes = message.len();
|
||||||
@@ -53,7 +53,7 @@ impl Smtp {
|
|||||||
let mail = SendableEmail::new(
|
let mail = SendableEmail::new(
|
||||||
envelope,
|
envelope,
|
||||||
rowid.to_string(), // only used for internal logging
|
rowid.to_string(), // only used for internal logging
|
||||||
&message,
|
message,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref mut transport) = self.transport {
|
if let Some(ref mut transport) = self.transport {
|
||||||
|
|||||||
Reference in New Issue
Block a user