mirror of
https://github.com/chatmail/core.git
synced 2026-04-21 15:36:30 +03:00
send messages via SMTP in configurable chunks
providers may have a maximum for the SMTP RCPT TO: header, therefore, an outgoing message is split into several chunks. the chunk size defaults to 50, however, if known to be larger or smaller by a dedicated provider, this setting may be changed. this does not affect the MIME To: headers, if a provider has a maximum here, this is change would not help.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
use super::Smtp;
|
||||
use async_smtp::*;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::context::Context;
|
||||
use crate::events::EventType;
|
||||
use itertools::Itertools;
|
||||
@@ -33,38 +34,41 @@ impl Smtp {
|
||||
job_id: u32,
|
||||
) -> Result<()> {
|
||||
let message_len_bytes = message.len();
|
||||
let chunk_size = context.get_config_int(Config::MaxSmtpRcptTo).await as usize;
|
||||
|
||||
let recipients_display = recipients.iter().map(|x| x.to_string()).join(",");
|
||||
for recipients_chunk in recipients.chunks(chunk_size).into_iter() {
|
||||
let recipients = recipients_chunk.to_vec();
|
||||
let recipients_display = recipients.iter().map(|x| x.to_string()).join(",");
|
||||
|
||||
let envelope =
|
||||
Envelope::new(self.from.clone(), recipients).map_err(Error::EnvelopeError)?;
|
||||
let mail = SendableEmail::new(
|
||||
envelope,
|
||||
format!("{}", job_id), // only used for internal logging
|
||||
message,
|
||||
);
|
||||
|
||||
if let Some(ref mut transport) = self.transport {
|
||||
// The timeout is 1min + 3min per MB.
|
||||
let timeout = 60 + (180 * message_len_bytes / 1_000_000) as u64;
|
||||
transport
|
||||
.send_with_timeout(mail, Some(&Duration::from_secs(timeout)))
|
||||
.await
|
||||
.map_err(Error::SendError)?;
|
||||
|
||||
context.emit_event(EventType::SmtpMessageSent(format!(
|
||||
"Message len={} was smtp-sent to {}",
|
||||
message_len_bytes, recipients_display
|
||||
)));
|
||||
self.last_success = Some(std::time::SystemTime::now());
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
warn!(
|
||||
context,
|
||||
"uh? SMTP has no transport, failed to send to {}", recipients_display
|
||||
let envelope =
|
||||
Envelope::new(self.from.clone(), recipients).map_err(Error::EnvelopeError)?;
|
||||
let mail = SendableEmail::new(
|
||||
envelope,
|
||||
format!("{}", job_id), // only used for internal logging
|
||||
&message,
|
||||
);
|
||||
Err(Error::NoTransport)
|
||||
|
||||
if let Some(ref mut transport) = self.transport {
|
||||
// The timeout is 1min + 3min per MB.
|
||||
let timeout = 60 + (180 * message_len_bytes / 1_000_000) as u64;
|
||||
transport
|
||||
.send_with_timeout(mail, Some(&Duration::from_secs(timeout)))
|
||||
.await
|
||||
.map_err(Error::SendError)?;
|
||||
|
||||
context.emit_event(EventType::SmtpMessageSent(format!(
|
||||
"Message len={} was smtp-sent to {}",
|
||||
message_len_bytes, recipients_display
|
||||
)));
|
||||
self.last_success = Some(std::time::SystemTime::now());
|
||||
} else {
|
||||
warn!(
|
||||
context,
|
||||
"uh? SMTP has no transport, failed to send to {}", recipients_display
|
||||
);
|
||||
return Err(Error::NoTransport);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user