From 031c90e797fff8adf482c1ed0ba4f43cc1cf32df Mon Sep 17 00:00:00 2001 From: jbostoen <6421683+jbostoen@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:15:08 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B07082=20Ability=20to=20forcefully=20send?= =?UTF-8?q?=20e-mails=20asynchronously=20(#501)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be usefull in use cases like sending mass emails in customer-survey --- core/email.class.inc.php | 9 ++++++ sources/Core/Email/EmailLaminas.php | 47 ++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/core/email.class.inc.php b/core/email.class.inc.php index e515b17f5..32c43680a 100644 --- a/core/email.class.inc.php +++ b/core/email.class.inc.php @@ -46,6 +46,15 @@ class EMail implements iEMail const ORIGINAL_FORMAT = 1; // Original format, consisting in serializing the whole object, inculding the Swift Mailer's object. // Did not work with attachements since their binary representation cannot be stored as a valid UTF-8 string const FORMAT_V2 = 2; // New format, only the raw data are serialized (base64 encoded if needed) + + /** @var int ENUM_SEND_DEFAULT This option can be used when sending an e-mail to respect the default configuration parameter. */ + const ENUM_SEND_DEFAULT = 0; + + /** @var int ENUM_SEND_FORCE_SYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: instant e-mail test. */ + const ENUM_SEND_FORCE_SYNCHRONOUS = 1; + + /** @var int ENUM_SEND_FORCE_ASYNCHRONOUS This option can be used when sending an e-mail to ignore the default and force synchronous sending instead. Example of a use case: Bulk mails. */ + const ENUM_SEND_FORCE_ASYNCHRONOUS = 2; public function __construct() { diff --git a/sources/Core/Email/EmailLaminas.php b/sources/Core/Email/EmailLaminas.php index 4159bd377..f88e21fdb 100644 --- a/sources/Core/Email/EmailLaminas.php +++ b/sources/Core/Email/EmailLaminas.php @@ -304,22 +304,53 @@ class EMailLaminas extends Email return $aImagesParts; } - public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null) + /** + * Sends an e-mail. + * + * @param string[] $aIssues Array to add any potentially encountered issues to. + * @param int|bool $iSyncAsync Specify whether the e-mail will be sent per default configuration, or whether there will be a forced (a)synchronous sending. One of Email::ENUM_SEND_* constants. To support legacy, it also allows a boolean (true = send synchronous). + * @param Object|null $oLog Log + * + * @details By default, the send method will respect the preference to send e-mails in an (a)synchronous way as defined in the iTop configuration by the administrator. + * In some use cases, it may be necessary to override this behavior. For example, for some tests it may be best if e-mails are always sent instantly (synchronous). + * Asynchronous may be preferred when sending a lot of bulk e-mails at once, to avoid hitting rate limits of e-mail providers (e.g. customer survey extension). + * + * @since 3.2.0 Previously, $iSyncAsync was a boolean ($bForceSynchronous) and this method only allowed to forcefully send e-mails synchronously even when the default was asynchronous. + * + * @return + */ + public function Send(&$aIssues, $iSyncAsync = Email::ENUM_SEND_DEFAULT, $oLog = null) { //select a default sender if none is provided. if (empty($this->m_aData['from']['address']) && !empty($this->m_aData['to'])) { $this->SetRecipientFrom($this->m_aData['to']); } - if ($bForceSynchronous) { + // In previous iTop versions, $iSyncAsync was $bForceSynchronous. To retain backward compatibility, this check is in place. + if($iSyncAsync === true) { + // This legacy mode forces synchronous sending, ignoring whatever default was configured. return $this->SendSynchronous($aIssues, $oLog); } else { - $oConfig = $this->LoadConfig(); - $bConfigASYNC = $oConfig->Get('email_asynchronous'); - if ($bConfigASYNC) { - return $this->SendAsynchronous($aIssues, $oLog); - } else { - return $this->SendSynchronous($aIssues, $oLog); + + switch($iSyncAsync) { + + case Email::ENUM_SEND_FORCE_SYNCHRONOUS: + return $this->SendSynchronous($aIssues, $oLog); + + case Email::ENUM_SEND_FORCE_ASYNCHRONOUS: + return $this->SendAsynchronous($aIssues, $oLog); + + case Email::ENUM_SEND_DEFAULT: + default: + + // Default behavior. + $oConfig = $this->LoadConfig(); + $bConfigASYNC = $oConfig->Get('email_asynchronous'); + if($bConfigASYNC) { + return $this->SendAsynchronous($aIssues, $oLog); + } else { + return $this->SendSynchronous($aIssues, $oLog); + } } } }