mirror of
https://github.com/chatmail/core.git
synced 2026-05-03 21:36:29 +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),
|
* - `fetch_existing_msgs` = 1=fetch most recent existing messages on configure (default),
|
||||||
* 0=do not fetch existing messages on configure.
|
* 0=do not fetch existing messages on configure.
|
||||||
* In both cases, existing recipients are added to the contact database.
|
* 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().
|
* 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
|
#[strum(props(default = "0"))] // also change MediaQuality.default() on changes
|
||||||
MediaQuality,
|
MediaQuality,
|
||||||
|
|
||||||
|
#[strum(props(default = "50"))]
|
||||||
|
MaxSmtpRcptTo,
|
||||||
|
|
||||||
/// If set to "1", on the first time `start_io()` is called after configuring,
|
/// If set to "1", on the first time `start_io()` is called after configuring,
|
||||||
/// the newest existing messages are fetched.
|
/// the newest existing messages are fetched.
|
||||||
/// Existing recipients are added to the contact database regardless of this setting.
|
/// Existing recipients are added to the contact database regardless of this setting.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use super::Smtp;
|
use super::Smtp;
|
||||||
use async_smtp::*;
|
use async_smtp::*;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -33,38 +34,41 @@ impl Smtp {
|
|||||||
job_id: u32,
|
job_id: u32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let message_len_bytes = message.len();
|
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 =
|
let envelope =
|
||||||
Envelope::new(self.from.clone(), recipients).map_err(Error::EnvelopeError)?;
|
Envelope::new(self.from.clone(), recipients).map_err(Error::EnvelopeError)?;
|
||||||
let mail = SendableEmail::new(
|
let mail = SendableEmail::new(
|
||||||
envelope,
|
envelope,
|
||||||
format!("{}", job_id), // only used for internal logging
|
format!("{}", job_id), // only used for internal logging
|
||||||
message,
|
&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
|
|
||||||
);
|
);
|
||||||
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