mirror of
https://github.com/chatmail/core.git
synced 2026-04-26 01:46:34 +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:
@@ -353,6 +353,10 @@ char* dc_get_blobdir (const dc_context_t* context);
|
||||
* - `fetch_existing_msgs` = 1=fetch most recent existing messages on configure (default),
|
||||
* 0=do not fetch existing messages on configure.
|
||||
* In both cases, existing recipients are added to the contact database.
|
||||
* - `max_smtp_rcpt_to` = set the max. number of recipients that should be used for `RCPT TO:` smtp header.
|
||||
* If a message needs to be sent to more recipients, multiple messages are sent out,
|
||||
* each with exactly the same MIME-message (with `To:` mime headers that may contain all recipients)
|
||||
* (defaults to 50)
|
||||
*
|
||||
* If you want to retrieve a value, use dc_get_config().
|
||||
*
|
||||
|
||||
@@ -69,6 +69,9 @@ pub enum Config {
|
||||
#[strum(props(default = "0"))] // also change MediaQuality.default() on changes
|
||||
MediaQuality,
|
||||
|
||||
#[strum(props(default = "50"))]
|
||||
MaxSmtpRcptTo,
|
||||
|
||||
/// If set to "1", on the first time `start_io()` is called after configuring,
|
||||
/// the newest existing messages are fetched.
|
||||
/// Existing recipients are added to the contact database regardless of this setting.
|
||||
|
||||
@@ -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