Merge remote-tracking branch 'origin/support/3.2' into develop

This commit is contained in:
Molkobain
2026-05-06 11:19:30 +02:00
3 changed files with 265 additions and 17 deletions

View File

@@ -29,7 +29,9 @@ use Symfony\Component\CssSelector\Exception\ParseException;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport;
use Symfony\Component\Mime\Email as SymfonyEmail;
use Symfony\Component\Mime\HtmlToTextConverter\DefaultHtmlToTextConverter;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
@@ -183,18 +185,7 @@ class EMailSymfony extends Email
$sDsn = sprintf('smtp://%s%s@%s%s', $sDsnUser, $sDsnPassword, $sDsnPort, $sEncQuery);
}
$oTransport = Transport::fromDsn($sDsn);
// Handle peer verification
$oStream = $oTransport->getStream();
$aOptions = $oStream->getStreamOptions();
if (!$bVerifyPeer && array_key_exists('ssl', $aOptions)) {
// Disable verification
$aOptions['ssl']['verify_peer'] = false;
$aOptions['ssl']['verify_peer_name'] = false;
$aOptions['ssl']['allow_self_signed'] = true;
}
$oStream->setStreamOptions($aOptions);
$oTransport = $this->CreateSmtpTransport($sDsn, $bVerifyPeer);
$oMailer = new Mailer($oTransport);
break;
@@ -260,6 +251,36 @@ class EMailSymfony extends Email
}
}
/**
* Build and configure an SMTP transport from a DSN string.
*
* Extracted from {@see SendSynchronous} to make SSL option handling independently testable.
* When $bVerifyPeer is false, the ssl stream context options must be written unconditionally:
* with STARTTLS the connection starts unencrypted, so the 'ssl' key is absent from the stream
* options at construction time and only used later when stream_socket_enable_crypto() is called.
*
* @param string $sDsn Full Symfony Mailer DSN (smtp:// or smtps://)
* @param bool $bVerifyPeer Whether to verify the peer SSL certificate
*
* @return \Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport
*/
protected function CreateSmtpTransport(string $sDsn, bool $bVerifyPeer): EsmtpTransport
{
/** @var EsmtpTransport $oTransport */
$oTransport = Transport::fromDsn($sDsn);
$oStream = $oTransport->getStream();
$aOptions = $oStream->getStreamOptions();
if (!$bVerifyPeer) {
$aOptions['ssl']['verify_peer'] = false;
$aOptions['ssl']['verify_peer_name'] = false;
$aOptions['ssl']['allow_self_signed'] = true;
}
$oStream->setStreamOptions($aOptions);
return $oTransport;
}
/**
* Reprocess the body of the message (if it is an HTML message)
* to replace the URL of images based on attachments by a link
@@ -416,13 +437,13 @@ class EMailSymfony extends Email
$this->m_aData['body'] = ['body' => $sBody, 'mimeType' => $sMimeType];
$oTextPart = new TextPart(strip_tags($sBody), 'utf-8', 'plain', 'base64');
// Embed inline images and store them in attachments (so BuildSymfonyMessageFromInternal can pick them)
if ($sPrimaryMimeType === 'text/html') {
$aAdditionalParts = $this->EmbedInlineImages($sBody);
$oTextPart = new TextPart((new DefaultHtmlToTextConverter())->convert($sBody, 'utf-8'), 'utf-8', 'plain', 'base64');
$oHtmlPart = new TextPart($sBody, 'utf-8', 'html', 'base64');
$oAlternativePart = new AlternativePart($oHtmlPart, $oTextPart);
// It's important de order parts from least prefered to most prefered as per RFC 2046 {@see https://www.rfc-editor.org/rfc/rfc2046.html#section-5.1.4}
$oAlternativePart = new AlternativePart($oTextPart, $oHtmlPart);
// Default root part is the HTML body
$oRootPart = $oAlternativePart;