Cleanup and improved handling of BODYSTRUCTURE

This commit is contained in:
the-djmaze 2022-01-14 12:51:32 +01:00
parent 0b767bb373
commit 8343e76d5f
8 changed files with 201 additions and 436 deletions

View file

@ -20,11 +20,7 @@ abstract class Utils
public static function NormalizeCharset(string $sEncoding, bool $bAsciAsUtf8 = false) : string public static function NormalizeCharset(string $sEncoding, bool $bAsciAsUtf8 = false) : string
{ {
$sEncoding = \strtolower($sEncoding); $sEncoding = \preg_replace('/^iso8/', 'iso-8', \strtolower($sEncoding));
$sEncoding = \preg_replace('/^iso8/', 'iso-8', $sEncoding);
$sEncoding = \preg_replace('/^cp-([\d])/', 'cp$1', $sEncoding);
$sEncoding = \preg_replace('/^windows?12/', 'windows-12', $sEncoding);
switch ($sEncoding) switch ($sEncoding)
{ {
@ -32,38 +28,40 @@ abstract class Utils
case 'ascii': case 'ascii':
case 'us-asci': case 'us-asci':
case 'us-ascii': case 'us-ascii':
$sEncoding = $bAsciAsUtf8 ? Enumerations\Charset::UTF_8 : return $bAsciAsUtf8 ? Enumerations\Charset::UTF_8 :
Enumerations\Charset::ISO_8859_1; Enumerations\Charset::ISO_8859_1;
break;
case 'unicode-1-1-utf-7': case 'unicode-1-1-utf-7':
case 'unicode-1-utf-7': case 'unicode-1-utf-7':
case 'unicode-utf-7': case 'unicode-utf-7':
$sEncoding = 'utf-7'; return 'utf-7';
break;
case 'utf8': case 'utf8':
case 'utf-8': case 'utf-8':
$sEncoding = Enumerations\Charset::UTF_8; return Enumerations\Charset::UTF_8;
break;
case 'utf7imap': case 'utf7imap':
case 'utf-7imap': case 'utf-7imap':
case 'utf7-imap': case 'utf7-imap':
case 'utf-7-imap': case 'utf-7-imap':
$sEncoding = 'utf7-imap'; return 'utf7-imap';
break;
case 'ks-c-5601-1987': case 'ks-c-5601-1987':
case 'ks_c_5601-1987': case 'ks_c_5601-1987':
case 'ks_c_5601_1987': case 'ks_c_5601_1987':
$sEncoding = 'euc-kr'; return 'euc-kr';
break;
case 'x-gbk': case 'x-gbk':
$sEncoding = 'gb2312'; return 'gb2312';
break;
case 'iso-8859-i': case 'iso-8859-i':
case 'iso-8859-8-i': case 'iso-8859-8-i':
$sEncoding = 'iso-8859-8'; return 'iso-8859-8';
break;
} }
$sEncoding = \preg_replace('/^cp-([\d])/', 'cp$1', $sEncoding);
$sEncoding = \preg_replace('/^windows?12/', 'windows-12', $sEncoding);
return $sEncoding; return $sEncoding;
} }

View file

@ -52,11 +52,6 @@ class BodyStructure
*/ */
private $sDisposition; private $sDisposition;
/**
* @var array
*/
private $aDispositionParams;
/** /**
* @var string * @var string
*/ */
@ -65,23 +60,18 @@ class BodyStructure
/** /**
* @var string * @var string
*/ */
private $sLanguage; private $sLanguage = '';
/** /**
* @var string * @var string
*/ */
private $sLocation; private $sLocation = '';
/** /**
* @var int * @var int
*/ */
private $iSize; private $iSize;
/**
* @var int
*/
private $iTextLineCount;
/** /**
* @var string * @var string
*/ */
@ -92,35 +82,14 @@ class BodyStructure
*/ */
private $aSubParts; private $aSubParts;
function __construct(string $sContentType, ?string $sCharset, array $aBodyParams, ?string $sContentID, public function MailEncodingName() : string
?string $sDescription, ?string $sMailEncodingName, ?string $sDisposition, ?array $aDispositionParams, string $sFileName,
?string $sLanguage, ?string $sLocation, int $iSize, int $iTextLineCount, string $sPartID, array $aSubParts)
{
$this->sContentType = $sContentType;
$this->sCharset = $sCharset;
$this->aBodyParams = $aBodyParams;
$this->sContentID = $sContentID;
$this->sDescription = $sDescription;
$this->sMailEncodingName = $sMailEncodingName;
$this->sDisposition = $sDisposition;
$this->aDispositionParams = $aDispositionParams;
$this->sFileName = $sFileName;
$this->sLanguage = $sLanguage;
$this->sLocation = $sLocation;
$this->iSize = $iSize;
$this->iTextLineCount = $iTextLineCount;
$this->sPartID = $sPartID;
$this->aSubParts = $aSubParts;
}
public function MailEncodingName() : ?string
{ {
return $this->sMailEncodingName; return $this->sMailEncodingName;
} }
public function PartID() : string public function PartID() : string
{ {
return (string) $this->sPartID; return $this->sPartID;
} }
public function FileName() : string public function FileName() : string
@ -141,7 +110,7 @@ class BodyStructure
public function EstimatedSize() : int public function EstimatedSize() : int
{ {
$fCoefficient = 1; $fCoefficient = 1;
switch (\strtolower($this->MailEncodingName())) switch ($this->sMailEncodingName)
{ {
case 'base64': case 'base64':
$fCoefficient = 0.75; $fCoefficient = 0.75;
@ -151,68 +120,63 @@ class BodyStructure
break; break;
} }
return (int) ($this->Size() * $fCoefficient); return (int) ($this->iSize * $fCoefficient);
} }
public function Charset() : ?string public function Charset() : string
{ {
return $this->sCharset; return $this->sCharset;
} }
public function ContentID() : string public function ContentID() : string
{ {
return (null === $this->sContentID) ? '' : $this->sContentID; return $this->sContentID;
} }
public function ContentLocation() : string public function ContentLocation() : string
{ {
return (null === $this->sLocation) ? '' : $this->sLocation; return $this->sLocation;
} }
public function IsInline() : bool public function IsInline() : bool
{ {
return (null === $this->sDisposition) ? return 'inline' === $this->sDisposition || \strlen($this->sContentID);
(\strlen($this->ContentID())) : ('inline' === strtolower($this->sDisposition));
} }
public function IsImage() : bool public function IsImage() : bool
{ {
return 'image' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName()); return 'image' === \MailSo\Base\Utils::ContentTypeType($this->sContentType, $this->sFileName);
} }
public function IsArchive() : bool public function IsArchive() : bool
{ {
return 'archive' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName()); return 'archive' === \MailSo\Base\Utils::ContentTypeType($this->sContentType, $this->sFileName);
} }
public function IsPdf() : bool public function IsPdf() : bool
{ {
return 'pdf' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName()); return 'pdf' === \MailSo\Base\Utils::ContentTypeType($this->sContentType, $this->sFileName);
} }
public function IsDoc() : bool public function IsDoc() : bool
{ {
return 'doc' === \MailSo\Base\Utils::ContentTypeType($this->ContentType(), $this->FileName()); return 'doc' === \MailSo\Base\Utils::ContentTypeType($this->sContentType, $this->sFileName);
} }
public function IsPgpSignature() : bool public function IsPgpSignature() : bool
{ {
return \in_array(\strtolower($this->ContentType()), return \in_array($this->sContentType,
array('application/pgp-signature', 'application/pkcs7-signature')); array('application/pgp-signature', 'application/pkcs7-signature'));
} }
public function IsAttachBodyPart() : bool public function IsAttachBodyPart() : bool
{ {
$bResult = ( return 'attachment' === $this->sDisposition
(null !== $this->sDisposition && 'attachment' === \strtolower($this->sDisposition)) || (
); !\str_starts_with($this->sContentType, 'multipart/')
&& 'text/html' !== $this->sContentType
if (!$bResult && null !== $this->sContentType) && 'text/plain' !== $this->sContentType
{ );
$sContentType = \strtolower($this->sContentType);
$bResult = false === \strpos($sContentType, 'multipart/') &&
'text/html' !== $sContentType && 'text/plain' !== $sContentType;
}
return $bResult; return $bResult;
} }
@ -222,7 +186,7 @@ class BodyStructure
$bResult = !empty($this->aBodyParams['format']) && $bResult = !empty($this->aBodyParams['format']) &&
'flowed' === \strtolower(\trim($this->aBodyParams['format'])); 'flowed' === \strtolower(\trim($this->aBodyParams['format']));
if ($bResult && \in_array(\strtolower($this->MailEncodingName()), array('base64', 'quoted-printable'))) if ($bResult && \in_array($this->sMailEncodingName, array('base64', 'quoted-printable')))
{ {
$bResult = false; $bResult = false;
} }
@ -230,43 +194,13 @@ class BodyStructure
return $bResult; return $bResult;
} }
public function SearchPlainParts() : array
{
$aReturn = array();
$aParts = $this->SearchByContentType('text/plain');
foreach ($aParts as $oPart)
{
if (!$oPart->IsAttachBodyPart())
{
$aReturn[] = $oPart;
}
}
return $aReturn;
}
public function SearchHtmlParts() : array
{
$aReturn = array();
$aParts = $this->SearchByContentType('text/html');
foreach ($aParts as $oPart)
{
if (!$oPart->IsAttachBodyPart())
{
$aReturn[] = $oPart;
}
}
return $aReturn;
}
public function SearchInlineEncryptedPart() : ?self public function SearchInlineEncryptedPart() : ?self
{ {
if ('multipart/encrypted' === \strtolower($this->ContentType())) if ('multipart/encrypted' === \strtolower($this->sContentType))
{ {
$aSearchParts = $this->SearchByCallback(function ($oItem) { $aSearchParts = \iterator_to_array($this->SearchByCallback(function ($oItem) {
return $oItem->IsInline(); return $oItem->IsInline();
}); }));
if (1 === \count($aSearchParts) && isset($aSearchParts[0])) if (1 === \count($aSearchParts) && isset($aSearchParts[0]))
{ {
@ -277,82 +211,68 @@ class BodyStructure
return null; return null;
} }
public function SearchHtmlOrPlainParts() : array public function GetHtmlAndPlainParts() : array
{ {
$mResult = $this->SearchHtmlParts() ?: $this->SearchPlainParts(); $aParts = $this->SearchByCallback(function ($oItem) {
if (!$mResult) return ('text/html' === $oItem->sContentType || 'text/plain' === $oItem->sContentType)
{ && !$oItem->IsAttachBodyPart();
$oPart = $this->SearchInlineEncryptedPart(); });
if ($oPart instanceof self)
{ if ($aParts->valid()) {
$mResult = array($oPart); return \iterator_to_array($aParts);
}
} }
return $mResult; $oPart = $this->SearchInlineEncryptedPart();
if ($oPart instanceof self) {
return array($oPart);
}
return [];
} }
public function SearchCharset() : string public function SearchCharset() : string
{ {
$sResult = ''; $gParts = $this->SearchByCallback(function ($oPart) {
$mParts = \array_merge($this->SearchHtmlParts(), $this->SearchPlainParts()); return $oPart->Charset()
&& ('text/html' === $oPart->sContentType || 'text/plain' === $oPart->sContentType)
&& !$oPart->IsAttachBodyPart();
});
foreach ($mParts as $oPart) if (!$gParts->valid()) {
{ $gParts = $this->SearchByCallback(function ($oPart) {
$sResult = $oPart ? $oPart->Charset() : ''; return $oPart->Charset() && $oPart->IsAttachBodyPart();
if ($sResult) });
{
break;
}
} }
if (!$sResult) return $gParts->valid() ? $gParts->current()->Charset() : '';
{
$aParts = $this->SearchAttachmentsParts();
foreach ($aParts as $oPart)
{
$sResult = $oPart ? $oPart->Charset() : '';
if ($sResult)
{
break;
}
}
}
return $sResult ?: '';
} }
/** /**
* @param mixed $fCallback * @param mixed $fCallback
*/ */
public function SearchByCallback($fCallback) : array // public function SearchByCallback($fCallback) : \Generator
public function SearchByCallback($fCallback) : iterable
{ {
$aReturn = array(); if ($fCallback($this)) {
if ($fCallback($this)) yield $this;
{
$aReturn[] = $this;
} }
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ $oSubPart) {
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ $oSubPart) yield from $oSubPart->SearchByCallback($fCallback);
{
$aReturn = \array_merge($aReturn, $oSubPart->SearchByCallback($fCallback));
} }
return $aReturn;
} }
public function SearchAttachmentsParts() : array public function SearchAttachmentsParts() : iterable
{ {
return $this->SearchByCallback(function ($oItem) { return $this->SearchByCallback(function ($oItem) {
return $oItem->IsAttachBodyPart(); return $oItem->IsAttachBodyPart();
}); });
} }
public function SearchByContentType(string $sContentType) : array public function SearchByContentType(string $sContentType) : iterable
{ {
$sContentType = \strtolower($sContentType); $sContentType = \strtolower($sContentType);
return $this->SearchByCallback(function ($oItem) use ($sContentType) { return $this->SearchByCallback(function ($oItem) use ($sContentType) {
return $sContentType === $oItem->ContentType(); return $sContentType === $oItem->sContentType;
}); });
} }
@ -382,7 +302,7 @@ class BodyStructure
return $oPart; return $oPart;
} }
private static function decodeAttrParameter(array $aParams, string $sParamName, string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8) : string private static function decodeAttrParameter(array $aParams, string $sParamName, string $sCharset) : string
{ {
$sResult = ''; $sResult = '';
if (isset($aParams[$sParamName])) if (isset($aParams[$sParamName]))
@ -455,34 +375,23 @@ class BodyStructure
return null; return null;
} }
$sBodyMainType = null; $sContentTypeMain = '';
if (\is_string($aBodyStructure[0])) $sContentTypeSub = '';
{
$sBodyMainType = $aBodyStructure[0];
}
$sBodySubType = null;
$sContentType = '';
$aSubParts = array(); $aSubParts = array();
$aBodyParams = array(); $aBodyParams = array();
$sName = null; $sName = '';
$sCharset = null; $sCharset = ''; // \MailSo\Base\Enumerations\Charset::UTF_8 ?
$sContentID = null; $sContentID = '';
$sDescription = null; $sDescription = '';
$sMailEncodingName = null; $sMailEncodingName = '';
$iSize = 0; $iSize = 0;
$iTextLineCount = 0; // valid for rfc822/message and text parts
$iExtraItemPos = 0; // list index of items which have no well-established position (such as 0, 1, 5, etc). $iExtraItemPos = 0; // list index of items which have no well-established position (such as 0, 1, 5, etc).
if (null === $sBodyMainType) if (\is_array($aBodyStructure[0]))
{ {
// Process multipart body structure // Process multipart body structure
if (!\is_array($aBodyStructure[0])) $sContentTypeMain = 'multipart';
{ $sContentTypeSub = 'mixed'; // primary default
return null;
}
$sBodyMainType = 'multipart';
$sSubPartIDPrefix = ''; $sSubPartIDPrefix = '';
if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1])
{ {
@ -498,17 +407,22 @@ class BodyStructure
$iIndex = 1; $iIndex = 1;
/**
* First process the subparts, like:
("text" "plain" ("charset" "utf-8") )
("text" "html" )
*/
while ($iExtraItemPos < \count($aBodyStructure) && \is_array($aBodyStructure[$iExtraItemPos])) while ($iExtraItemPos < \count($aBodyStructure) && \is_array($aBodyStructure[$iExtraItemPos]))
{ {
$oPart = self::NewInstance($aBodyStructure[$iExtraItemPos], $sSubPartIDPrefix.$iIndex); $oPart = self::NewInstance($aBodyStructure[$iExtraItemPos], $sSubPartIDPrefix.$iIndex);
if (null === $oPart) if (!$oPart)
{ {
return null; return null;
} }
// For multipart, we have no charset info in the part itself. Thus, // For multipart, we have no charset info in the part itself. Thus,
// obtain charset from nested parts. // obtain charset from nested parts.
if ($sCharset == null) if (!$sCharset)
{ {
$sCharset = $oPart->Charset(); $sCharset = $oPart->Charset();
} }
@ -518,43 +432,35 @@ class BodyStructure
++$iIndex; ++$iIndex;
} }
/**
* Now process the subparts containter like:
"alternative" ("boundary" "--boundary_id")
*/
if ($iExtraItemPos < \count($aBodyStructure)) if ($iExtraItemPos < \count($aBodyStructure))
{ {
if (!\is_string($aBodyStructure[$iExtraItemPos])) if (!\is_string($aBodyStructure[$iExtraItemPos]))
{ {
return null; return null;
} }
$sContentTypeSub = \strtolower($aBodyStructure[$iExtraItemPos]);
$sBodySubType = \strtolower($aBodyStructure[$iExtraItemPos]);
++$iExtraItemPos; ++$iExtraItemPos;
} if ($iExtraItemPos < \count($aBodyStructure) && \is_array($aBodyStructure[$iExtraItemPos]))
if ($iExtraItemPos < \count($aBodyStructure))
{
$sBodyParamList = $aBodyStructure[$iExtraItemPos];
if (\is_array($sBodyParamList))
{ {
$aBodyParams = self::getKeyValueListFromArrayList($sBodyParamList); $aBodyParams = self::getKeyValueListFromArrayList($aBodyStructure[$iExtraItemPos]);
} }
} }
++$iExtraItemPos;
} }
else else if (\is_string($aBodyStructure[0]))
{ {
// Process simple (singlepart) body structure // Process simple (singlepart) body structure
if (7 > \count($aBodyStructure)) if (7 > \count($aBodyStructure) || !\is_string($aBodyStructure[1]))
{ {
return null; return null;
} }
$sBodyMainType = \strtolower($sBodyMainType); $sContentTypeMain = \strtolower($aBodyStructure[0]);
if (!\is_string($aBodyStructure[1])) $sContentTypeSub = \strtolower($aBodyStructure[1]);
{
return null;
}
$sBodySubType = \strtolower($aBodyStructure[1]);
$aBodyParamList = $aBodyStructure[2]; $aBodyParamList = $aBodyStructure[2];
if (\is_array($aBodyParamList)) if (\is_array($aBodyParamList))
@ -565,7 +471,7 @@ class BodyStructure
$sCharset = $aBodyParams['charset']; $sCharset = $aBodyParams['charset'];
} }
$sName = self::decodeAttrParameter($aBodyParams, 'name', $sContentType); $sName = self::decodeAttrParameter($aBodyParams, 'name', $sCharset);
} }
if (null !== $aBodyStructure[3]) if (null !== $aBodyStructure[3])
@ -574,7 +480,6 @@ class BodyStructure
{ {
return null; return null;
} }
$sContentID = $aBodyStructure[3]; $sContentID = $aBodyStructure[3];
} }
@ -584,7 +489,6 @@ class BodyStructure
{ {
return null; return null;
} }
$sDescription = $aBodyStructure[4]; $sDescription = $aBodyStructure[4];
} }
@ -597,14 +501,7 @@ class BodyStructure
$sMailEncodingName = $aBodyStructure[5]; $sMailEncodingName = $aBodyStructure[5];
} }
if (\is_numeric($aBodyStructure[6])) $iSize = \is_numeric($aBodyStructure[6]) ? (int) $aBodyStructure[6] : -1;
{
$iSize = (int) $aBodyStructure[6];
}
else
{
$iSize = -1;
}
if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1])
{ {
@ -614,161 +511,85 @@ class BodyStructure
} }
$iExtraItemPos = 7; $iExtraItemPos = 7;
if ('text' === $sBodyMainType) if ('text' === $sContentTypeMain)
{ {
if ($iExtraItemPos < \count($aBodyStructure)) /**
{ * A body type of type TEXT contains, immediately after the basic
if (\is_numeric($aBodyStructure[$iExtraItemPos])) * fields, the size of the body in text lines.
{ */
$iTextLineCount = (int) $aBodyStructure[$iExtraItemPos];
}
else
{
$iTextLineCount = -1;
}
}
else
{
$iTextLineCount = -1;
}
++$iExtraItemPos; ++$iExtraItemPos;
} }
else if ('message' === $sBodyMainType && 'rfc822' === $sBodySubType) else if ('message' === $sContentTypeMain && 'rfc822' === $sContentTypeSub)
{ {
if ($iExtraItemPos + 2 < \count($aBodyStructure)) /**
{ * A body type of type MESSAGE and subtype RFC822 contains,
if (\is_numeric($aBodyStructure[$iExtraItemPos + 2])) * immediately after the basic fields, the envelope structure,
{ * body structure, and size in text lines of the encapsulated message.
$iTextLineCount = (int) $aBodyStructure[$iExtraItemPos + 2]; */
}
else
{
$iTextLineCount = -1;
}
}
else
{
$iTextLineCount = -1;
}
$iExtraItemPos += 3; $iExtraItemPos += 3;
} }
}
++$iExtraItemPos; // skip MD5 digest of the body because most mail servers leave it NIL anyway else
{
return null;
} }
$sContentType = $sBodyMainType.'/'.$sBodySubType; // Skip body MD5 because most mail servers leave it NIL anyway
++$iExtraItemPos;
$sDisposition = null; $sDisposition = '';
$aDispositionParams = null; $sFileName = '';
$sFileName = null;
if ($iExtraItemPos < \count($aBodyStructure)) if ($iExtraItemPos < \count($aBodyStructure))
{ {
$aDispList = $aBodyStructure[$iExtraItemPos]; $aDispList = $aBodyStructure[$iExtraItemPos];
if (\is_array($aDispList) && 1 < \count($aDispList)) if (\is_array($aDispList) && 1 < \count($aDispList))
{ {
if (null !== $aDispList[0]) if (!\is_string($aDispList[0]))
{ {
if (\is_string($aDispList[0])) return null;
{
$sDisposition = $aDispList[0];
}
else
{
return null;
}
} }
$sDisposition = $aDispList[0];
$aDispParamList = $aDispList[1]; if (\is_array($aDispList[1]))
if (\is_array($aDispParamList))
{ {
$aDispositionParams = self::getKeyValueListFromArrayList($aDispParamList); $aDispositionParams = self::getKeyValueListFromArrayList($aDispList[1]);
$sFileName = self::decodeAttrParameter($aDispositionParams, 'filename', $sCharset ?: ''); $sFileName = self::decodeAttrParameter($aDispositionParams, 'filename', $sCharset);
} }
} }
} }
++$iExtraItemPos; $oStructure = new self;
$oStructure->sContentType = \strtolower($sContentTypeMain.'/'.$sContentTypeSub);
$oStructure->sCharset = $sCharset;
$oStructure->aBodyParams = $aBodyParams;
$oStructure->sContentID = $sContentID;
$oStructure->sDescription = $sDescription;
$oStructure->sMailEncodingName = \strtolower($sMailEncodingName);
$oStructure->sDisposition = \strtolower($sDisposition);
$oStructure->sFileName = \MailSo\Base\Utils::Utf8Clear($sFileName ?: $sName);
$oStructure->iSize = $iSize;
$oStructure->sPartID = $sPartID;
$oStructure->aSubParts = $aSubParts;
$sLanguage = null;
if ($iExtraItemPos < \count($aBodyStructure)) if ($iExtraItemPos < \count($aBodyStructure))
{ {
if (null !== $aBodyStructure[$iExtraItemPos]) if (\is_array($aBodyStructure[$iExtraItemPos]))
{ {
if (\is_array($aBodyStructure[$iExtraItemPos])) $oStructure->sLanguage = \implode(',', $aBodyStructure[$iExtraItemPos]);
{ }
$sLanguage = \implode(',', $aBodyStructure[$iExtraItemPos]); else if (\is_string($aBodyStructure[$iExtraItemPos]))
} {
else if (\is_string($aBodyStructure[$iExtraItemPos])) $oStructure->sLanguage = $aBodyStructure[$iExtraItemPos];
{
$sLanguage = $aBodyStructure[$iExtraItemPos];
}
} }
++$iExtraItemPos; ++$iExtraItemPos;
} }
$sLocation = null; if ($iExtraItemPos < \count($aBodyStructure) && \is_string($aBodyStructure[$iExtraItemPos]))
if ($iExtraItemPos < \count($aBodyStructure))
{ {
if (null !== $aBodyStructure[$iExtraItemPos]) $oStructure->sLocation = $aBodyStructure[$iExtraItemPos];
{
if (\is_string($aBodyStructure[$iExtraItemPos]))
{
$sLocation = $aBodyStructure[$iExtraItemPos];
}
}
++$iExtraItemPos;
} }
return new self( return $oStructure;
$sContentType,
$sCharset,
$aBodyParams,
$sContentID,
$sDescription,
$sMailEncodingName,
$sDisposition,
$aDispositionParams,
\MailSo\Base\Utils::Utf8Clear($sFileName ?: $sName),
$sLanguage,
$sLocation,
$iSize,
$iTextLineCount,
$sPartID,
$aSubParts
);
}
public static function NewInstanceFromRfc822SubPart(array $aBodyStructure, string $sSubPartID) : ?self
{
$aBodySubStructure = self::findPartByIndexInArray($aBodyStructure, $sSubPartID);
if ($aBodySubStructure && \is_array($aBodySubStructure) && isset($aBodySubStructure[8]))
{
return self::NewInstance($aBodySubStructure[8], $sSubPartID);
}
return null;
}
private static function findPartByIndexInArray(array $aList, string $sPartID) : ?array
{
$bFind = false;
$aPath = \explode('.', ''.$sPartID);
$aCurrentPart = $aList;
foreach ($aPath as $iPos => $iNum)
{
$iIndex = \intval($iNum) - 1;
if (0 <= $iIndex && 0 < $iPos ? isset($aCurrentPart[8][$iIndex]) : isset($aCurrentPart[$iIndex]))
{
$aCurrentPart = 0 < $iPos ? $aCurrentPart[8][$iIndex] : $aCurrentPart[$iIndex];
$bFind = true;
}
}
return $bFind ? $aCurrentPart : null;
} }
/** /**
@ -783,7 +604,7 @@ class BodyStructure
{ {
for ($iIndex = 0; $iIndex < $iLen; $iIndex += 2) for ($iIndex = 0; $iIndex < $iLen; $iIndex += 2)
{ {
if (\is_string($aList[$iIndex]) && isset($aList[$iIndex + 1]) && \is_string($aList[$iIndex + 1])) if (\is_string($aList[$iIndex]) && \is_string($aList[$iIndex + 1]))
{ {
$aDict[\strtolower($aList[$iIndex])] = $aList[$iIndex + 1]; $aDict[\strtolower($aList[$iIndex])] = $aList[$iIndex + 1];
} }

View file

@ -83,20 +83,13 @@ class FetchResponse
return $oResult; return $oResult;
} }
public function GetFetchBodyStructure(string $sRfc822SubMimeIndex = '') : ?BodyStructure public function GetFetchBodyStructure() : ?BodyStructure
{ {
$aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE); $aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE);
if (\is_array($aBodyStructureArray)) return \is_array($aBodyStructureArray)
{ ? BodyStructure::NewInstance($aBodyStructureArray)
if (\strlen($sRfc822SubMimeIndex)) : null;
{
return BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex);
}
return BodyStructure::NewInstance($aBodyStructureArray);
}
return null;
} }
/** /**
@ -125,12 +118,10 @@ class FetchResponse
* Like: BODY[HEADER.FIELDS (RETURN-PATH RECEIVED MIME-VERSION MESSAGE-ID CONTENT-TYPE FROM TO CC BCC SENDER REPLY-TO DELIVERED-TO IN-REPLY-TO REFERENCES DATE SUBJECT SENSITIVITY X-MSMAIL-PRIORITY IMPORTANCE X-PRIORITY X-DRAFT-INFO RETURN-RECEIPT-TO DISPOSITION-NOTIFICATION-TO X-CONFIRM-READING-TO AUTHENTICATION-RESULTS X-DKIM-AUTHENTICATION-RESULTS LIST-UNSUBSCRIBE X-SPAM-STATUS X-SPAMD-RESULT X-BOGOSITY X-VIRUS X-VIRUS-SCANNED X-VIRUS-STATUS)] * Like: BODY[HEADER.FIELDS (RETURN-PATH RECEIVED MIME-VERSION MESSAGE-ID CONTENT-TYPE FROM TO CC BCC SENDER REPLY-TO DELIVERED-TO IN-REPLY-TO REFERENCES DATE SUBJECT SENSITIVITY X-MSMAIL-PRIORITY IMPORTANCE X-PRIORITY X-DRAFT-INFO RETURN-RECEIPT-TO DISPOSITION-NOTIFICATION-TO X-CONFIRM-READING-TO AUTHENTICATION-RESULTS X-DKIM-AUTHENTICATION-RESULTS LIST-UNSUBSCRIBE X-SPAM-STATUS X-SPAMD-RESULT X-BOGOSITY X-VIRUS X-VIRUS-SCANNED X-VIRUS-STATUS)]
* @return mixed * @return mixed
*/ */
public function GetHeaderFieldsValue(string $sRfc822SubMimeIndex = '') : string public function GetHeaderFieldsValue() : string
{ {
$bNextIsValue = false; $bNextIsValue = false;
$sRfc822SubMimeIndex = \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3])) if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
{ {
foreach ($this->oImapResponse->ResponseList[3] as $mItem) foreach ($this->oImapResponse->ResponseList[3] as $mItem)
@ -141,9 +132,9 @@ class FetchResponse
} }
if (\is_string($mItem) && ( if (\is_string($mItem) && (
$mItem === 'BODY['.$sRfc822SubMimeIndex.'HEADER]' || $mItem === 'BODY[HEADER]' ||
0 === \strpos($mItem, 'BODY['.$sRfc822SubMimeIndex.'HEADER.FIELDS') || 0 === \strpos($mItem, 'BODY[HEADER.FIELDS') ||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'MIME]')) $mItem === 'BODY[MIME]'))
{ {
$bNextIsValue = true; $bNextIsValue = true;
} }

View file

@ -100,11 +100,6 @@ class Attachment implements \JsonSerializable
return $this->oBodyStructure ? $this->oBodyStructure->ContentType() : ''; return $this->oBodyStructure ? $this->oBodyStructure->ContentType() : '';
} }
public function ContentTransferEncoding() : string
{
return $this->oBodyStructure ? $this->oBodyStructure->MailEncodingName() : '';
}
public function EncodedSize() : int public function EncodedSize() : int
{ {
return $this->oBodyStructure ? $this->oBodyStructure->Size() : 0; return $this->oBodyStructure ? $this->oBodyStructure->Size() : 0;

View file

@ -170,7 +170,7 @@ class MailClient
$oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure(); $oBodyStructure = $aFetchResponse[0]->GetFetchBodyStructure();
if ($oBodyStructure) if ($oBodyStructure)
{ {
foreach ($oBodyStructure->SearchHtmlOrPlainParts() as $oPart) foreach ($oBodyStructure->GetHtmlAndPlainParts() as $oPart)
{ {
$sLine = FetchType::BODY_PEEK.'['.$oPart->PartID().']'; $sLine = FetchType::BODY_PEEK.'['.$oPart->PartID().']';
if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size()) if (0 < $iBodyTextLimit && $iBodyTextLimit < $oPart->Size())
@ -181,13 +181,10 @@ class MailClient
$aFetchItems[] = $sLine; $aFetchItems[] = $sLine;
} }
$aSignatureParts = $oBodyStructure->SearchByContentType('application/pgp-signature'); $gSignatureParts = $oBodyStructure->SearchByContentType('application/pgp-signature');
if (\is_array($aSignatureParts) && \count($aSignatureParts)) foreach ($gSignatureParts as $oPart)
{ {
foreach ($aSignatureParts as $oPart) $aFetchItems[] = FetchType::BODY_PEEK.'['.$oPart->PartID().']';
{
$aFetchItems[] = FetchType::BODY_PEEK.'['.$oPart->PartID().']';
}
} }
} }
} }

View file

@ -11,6 +11,9 @@
namespace MailSo\Mail; namespace MailSo\Mail;
use \MailSo\Base\Utils;
use \MailSo\Imap\Enumerations\FetchType;
/** /**
* @category MailSo * @category MailSo
* @package Mail * @package Mail
@ -116,11 +119,6 @@ class Message implements \JsonSerializable
return $this->bPgpEncrypted; return $this->bPgpEncrypted;
} }
public function SetHtml(string $sHtml) : void
{
$this->sHtml = $sHtml;
}
public function Folder() : string public function Folder() : string
{ {
return $this->sFolder; return $this->sFolder;
@ -298,19 +296,18 @@ class Message implements \JsonSerializable
$oBodyStructure = $oFetchResponse->GetFetchBodyStructure(); $oBodyStructure = $oFetchResponse->GetFetchBodyStructure();
} }
$sInternalDate = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::INTERNALDATE); $sInternalDate = $oFetchResponse->GetFetchValue(FetchType::INTERNALDATE);
$aFlags = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::FLAGS); $aFlags = $oFetchResponse->GetFetchValue(FetchType::FLAGS);
$this->sFolder = $sFolder; $this->sFolder = $sFolder;
$this->iUid = (int) $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::UID); $this->iUid = (int) $oFetchResponse->GetFetchValue(FetchType::UID);
$this->iSize = (int) $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE); $this->iSize = (int) $oFetchResponse->GetFetchValue(FetchType::RFC822_SIZE);
$this->aFlagsLowerCase = \array_map('strtolower', $aFlags ?: []); $this->aFlagsLowerCase = \array_map('strtolower', $aFlags ?: []);
$this->iInternalTimeStampInUTC = $this->iInternalTimeStampInUTC =
\MailSo\Base\DateTimeHelper::ParseInternalDateString($sInternalDate); \MailSo\Base\DateTimeHelper::ParseInternalDateString($sInternalDate);
$sCharset = $oBodyStructure ? $oBodyStructure->SearchCharset() : ''; $sCharset = $oBodyStructure ? Utils::NormalizeCharset($oBodyStructure->SearchCharset()) : '';
$sCharset = \MailSo\Base\Utils::NormalizeCharset($sCharset);
$sHeaders = $oFetchResponse->GetHeaderFieldsValue(); $sHeaders = $oFetchResponse->GetHeaderFieldsValue();
if (\strlen($sHeaders)) if (\strlen($sHeaders))
@ -324,8 +321,7 @@ class Message implements \JsonSerializable
if (\strlen($sContentTypeCharset)) if (\strlen($sContentTypeCharset))
{ {
$sCharset = $sContentTypeCharset; $sCharset = Utils::NormalizeCharset($sContentTypeCharset);
$sCharset = \MailSo\Base\Utils::NormalizeCharset($sCharset);
} }
if (\strlen($sCharset)) if (\strlen($sCharset))
@ -353,7 +349,7 @@ class Message implements \JsonSerializable
$this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect); $this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect);
$this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO); $this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
$this->sReferences = \MailSo\Base\Utils::StripSpaces( $this->sReferences = Utils::StripSpaces(
$oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES)); $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES));
$sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE); $sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE);
@ -491,20 +487,11 @@ class Message implements \JsonSerializable
} }
else if ($oFetchResponse->GetEnvelope()) else if ($oFetchResponse->GetEnvelope())
{ {
if (!\strlen($sCharset) && $oBodyStructure) $sCharset = $sCharset ?: \MailSo\Base\Enumerations\Charset::ISO_8859_1;
{
$sCharset = $oBodyStructure->SearchCharset();
$sCharset = \MailSo\Base\Utils::NormalizeCharset($sCharset);
}
if (!\strlen($sCharset))
{
$sCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1;
}
// date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, message-id // date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, message-id
$this->sMessageId = $oFetchResponse->GetFetchEnvelopeValue(9, ''); $this->sMessageId = $oFetchResponse->GetFetchEnvelopeValue(9, '');
$this->sSubject = \MailSo\Base\Utils::DecodeHeaderValue($oFetchResponse->GetFetchEnvelopeValue(1, ''), $sCharset); $this->sSubject = Utils::DecodeHeaderValue($oFetchResponse->GetFetchEnvelopeValue(1, ''), $sCharset);
$this->oFrom = $oFetchResponse->GetFetchEnvelopeEmailCollection(2, $sCharset); $this->oFrom = $oFetchResponse->GetFetchEnvelopeEmailCollection(2, $sCharset);
$this->oSender = $oFetchResponse->GetFetchEnvelopeEmailCollection(3, $sCharset); $this->oSender = $oFetchResponse->GetFetchEnvelopeEmailCollection(3, $sCharset);
@ -519,9 +506,10 @@ class Message implements \JsonSerializable
if ('multipart/signed' === \strtolower($this->sContentType) if ('multipart/signed' === \strtolower($this->sContentType)
&& 'application/pgp-signature' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL))) && 'application/pgp-signature' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL)))
{ {
$aPgpSignatureParts = $oBodyStructure ? $oBodyStructure->SearchByContentType('application/pgp-signature') : null; $gPgpSignatureParts = $oBodyStructure ? $oBodyStructure->SearchByContentType('application/pgp-signature') : null;
if ($this->bPgpSigned = !empty($aPgpSignatureParts)) { $this->bPgpSigned = $gPgpSignatureParts && $gPgpSignatureParts->valid();
$sPgpSignatureText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$aPgpSignatureParts[0]->PartID().']'); if ($this->bPgpSigned) {
$sPgpSignatureText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$gPgpSignatureParts->current()->PartID().']');
if (\is_string($sPgpSignatureText) && \strlen($sPgpSignatureText) && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) { if (\is_string($sPgpSignatureText) && \strlen($sPgpSignatureText) && 0 < \strpos($sPgpSignatureText, 'BEGIN PGP SIGNATURE')) {
$this->sPgpSignature = \trim($sPgpSignatureText); $this->sPgpSignature = \trim($sPgpSignatureText);
$this->sPgpSignatureMicAlg = (string) $oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'micalg'); $this->sPgpSignatureMicAlg = (string) $oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, 'micalg');
@ -533,23 +521,21 @@ class Message implements \JsonSerializable
$this->bPgpEncrypted = ('multipart/encrypted' === \strtolower($this->sContentType) $this->bPgpEncrypted = ('multipart/encrypted' === \strtolower($this->sContentType)
&& 'application/pgp-encrypted' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL))); && 'application/pgp-encrypted' === \strtolower($oHeaders->ParameterValue(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE, \MailSo\Mime\Enumerations\Parameter::PROTOCOL)));
$aTextParts = $oBodyStructure ? $oBodyStructure->SearchHtmlOrPlainParts() : null; $aTextParts = $oBodyStructure ? $oBodyStructure->GetHtmlAndPlainParts() : null;
if ($aTextParts) if ($aTextParts)
{ {
if (!\strlen($sCharset)) $sCharset = $sCharset ?: \MailSo\Base\Enumerations\Charset::UTF_8;
{
$sCharset = \MailSo\Base\Enumerations\Charset::UTF_8;
}
$aHtmlParts = array(); $aHtmlParts = array();
$aPlainParts = array(); $aPlainParts = array();
foreach ($aTextParts as $oPart) foreach ($aTextParts as $oPart)
{ {
$sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$oPart->PartID().']'); $sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']');
if (null === $sText) if (null === $sText)
{ {
$sText = $oFetchResponse->GetFetchValue(\MailSo\Imap\Enumerations\FetchType::BODY.'['.$oPart->PartID().']<0>'); $sText = $oFetchResponse->GetFetchValue(FetchType::BODY.'['.$oPart->PartID().']<0>');
if (\is_string($sText) && \strlen($sText)) if (\is_string($sText) && \strlen($sText))
{ {
$this->bTextPartIsTrimmed = true; $this->bTextPartIsTrimmed = true;
@ -564,11 +550,11 @@ class Message implements \JsonSerializable
$sTextCharset = $sCharset; $sTextCharset = $sCharset;
} }
$sTextCharset = \MailSo\Base\Utils::NormalizeCharset($sTextCharset, true); $sTextCharset = Utils::NormalizeCharset($sTextCharset, true);
$sText = \MailSo\Base\Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName()); $sText = Utils::DecodeEncodingValue($sText, $oPart->MailEncodingName());
$sText = \MailSo\Base\Utils::ConvertEncoding($sText, $sTextCharset, \MailSo\Base\Enumerations\Charset::UTF_8); $sText = Utils::ConvertEncoding($sText, $sTextCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
$sText = \MailSo\Base\Utils::Utf8Clear($sText); $sText = Utils::Utf8Clear($sText);
if ('text/html' === $oPart->ContentType()) if ('text/html' === $oPart->ContentType())
{ {
@ -578,7 +564,7 @@ class Message implements \JsonSerializable
{ {
if ($oPart->IsFlowedFormat()) if ($oPart->IsFlowedFormat())
{ {
$sText = \MailSo\Base\Utils::DecodeFlowedFormat($sText); $sText = Utils::DecodeFlowedFormat($sText);
} }
$aPlainParts[] = $sText; $aPlainParts[] = $sText;
@ -586,14 +572,8 @@ class Message implements \JsonSerializable
} }
} }
if (\count($aHtmlParts)) $this->sHtml = \implode('<br />', $aHtmlParts);
{ $this->sPlain = \trim(\implode("\n", $aPlainParts));
$this->sHtml = \implode('<br />', $aHtmlParts);
}
else
{
$this->sPlain = \trim(\implode("\n", $aPlainParts));
}
$aMatch = array(); $aMatch = array();
if (!$this->bPgpSigned && \preg_match('/-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0])) if (!$this->bPgpSigned && \preg_match('/-----BEGIN PGP SIGNATURE-----(.+)-----END PGP SIGNATURE-----/ism', $this->sPlain, $aMatch) && !empty($aMatch[0]))
@ -609,11 +589,11 @@ class Message implements \JsonSerializable
if ($oBodyStructure) if ($oBodyStructure)
{ {
$aAttachmentsParts = $oBodyStructure->SearchAttachmentsParts(); $gAttachmentsParts = $oBodyStructure->SearchAttachmentsParts();
if ($aAttachmentsParts && \count($aAttachmentsParts)) if ($gAttachmentsParts->valid())
{ {
$this->oAttachments = new AttachmentCollection; $this->oAttachments = new AttachmentCollection;
foreach ($aAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem) foreach ($gAttachmentsParts as /* @var $oAttachmentItem \MailSo\Imap\BodyStructure */ $oAttachmentItem)
{ {
$this->oAttachments->append( $this->oAttachments->append(
Attachment::NewBodyStructureInstance($this->sFolder, $this->iUid, $oAttachmentItem) Attachment::NewBodyStructureInstance($this->sFolder, $this->iUid, $oAttachmentItem)
@ -631,7 +611,7 @@ class Message implements \JsonSerializable
'@Object' => 'Object/Message', '@Object' => 'Object/Message',
'Folder' => $this->sFolder, 'Folder' => $this->sFolder,
'Uid' => $this->iUid, 'Uid' => $this->iUid,
'Subject' => \trim(\MailSo\Base\Utils::Utf8Clear($this->sSubject)), 'Subject' => \trim(Utils::Utf8Clear($this->sSubject)),
'MessageId' => $this->sMessageId, 'MessageId' => $this->sMessageId,
'Size' => $this->iSize, 'Size' => $this->iSize,
'SpamScore' => $this->iSpamScore, 'SpamScore' => $this->iSpamScore,

View file

@ -141,13 +141,6 @@ class Part
Enumerations\Header::CONTENT_TYPE))) : ''; Enumerations\Header::CONTENT_TYPE))) : '';
} }
public function ContentTransferEncoding() : string
{
return ($this->Headers) ?
\trim(\strtolower($this->Headers->ValueByName(
Enumerations\Header::CONTENT_TRANSFER_ENCODING))) : '';
}
public function ContentID() : string public function ContentID() : string
{ {
return ($this->Headers) ? \trim($this->Headers->ValueByName( return ($this->Headers) ? \trim($this->Headers->ValueByName(
@ -169,7 +162,7 @@ class Part
Enumerations\Header::CONTENT_TYPE, Enumerations\Header::CONTENT_TYPE,
Enumerations\Parameter::FORMAT))); Enumerations\Parameter::FORMAT)));
if ($bResult && \in_array(\strtolower($this->MailEncodingName()), array('base64', 'quoted-printable'))) if ($bResult && \in_array($this->MailEncodingName(), array('base64', 'quoted-printable')))
{ {
$bResult = false; $bResult = false;
} }

View file

@ -223,14 +223,6 @@ trait Response
} }
} }
$sPlain = '';
$sHtml = \trim($mResponse->Html());
if (!\strlen($sHtml))
{
$sPlain = \trim($mResponse->Plain());
}
$mResult['DraftInfo'] = $mResponse->DraftInfo(); $mResult['DraftInfo'] = $mResponse->DraftInfo();
$mResult['InReplyTo'] = $mResponse->InReplyTo(); $mResult['InReplyTo'] = $mResponse->InReplyTo();
$mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks(); $mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks();
@ -248,27 +240,25 @@ trait Response
}; };
} }
$sHtml = $mResponse->Html();
$sHtml = \preg_replace_callback('/(<pre[^>]*>)([\s\S\r\n\t]*?)(<\/pre>)/mi', function ($aMatches) { $sHtml = \preg_replace_callback('/(<pre[^>]*>)([\s\S\r\n\t]*?)(<\/pre>)/mi', function ($aMatches) {
return \preg_replace('/[\r\n]+/', '<br />', $aMatches[1].\trim($aMatches[2]).$aMatches[3]); return \preg_replace('/[\r\n]+/', '<br />', $aMatches[1].\trim($aMatches[2]).$aMatches[3]);
}, $sHtml); }, $sHtml);
$mResult['Html'] = \strlen($sHtml) ? \MailSo\Base\HtmlUtils::ClearHtml( $mResult['Html'] = \strlen($sHtml) ? \MailSo\Base\HtmlUtils::ClearHtml(
$sHtml, $bHasExternals, $aFoundCIDs, $aContentLocationUrls, $aFoundContentLocationUrls, $sHtml, $bHasExternals, $aFoundCIDs, $aContentLocationUrls, $aFoundContentLocationUrls,
$fAdditionalExternalFilter, !!$this->Config()->Get('labs', 'try_to_detect_hidden_images', false) $fAdditionalExternalFilter, !!$this->Config()->Get('labs', 'try_to_detect_hidden_images', false)
) : ''; ) : '';
unset($sHtml);
$mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter; $mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter;
$mResult['Plain'] = $sPlain; $mResult['Plain'] = $mResponse->Plain();
// $mResult['Plain'] = \strlen($sPlain) ? \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain) : '';
$mResult['isPgpSigned'] = $mResponse->isPgpSigned(); $mResult['isPgpSigned'] = $mResponse->isPgpSigned();
$mResult['isPgpEncrypted'] = $mResponse->isPgpEncrypted(); $mResult['isPgpEncrypted'] = $mResponse->isPgpEncrypted();
// $mResult['PgpSignature'] = $mResponse->PgpSignature(); // $mResult['PgpSignature'] = $mResponse->PgpSignature();
// $mResult['PgpSignatureMicAlg'] = $mResponse->PgpSignatureMicAlg(); // $mResult['PgpSignatureMicAlg'] = $mResponse->PgpSignatureMicAlg();
unset($sHtml, $sPlain);
$mResult['HasExternals'] = $bHasExternals; $mResult['HasExternals'] = $bHasExternals;
$mResult['HasInternals'] = \count($aFoundCIDs) || \count($aFoundContentLocationUrls); $mResult['HasInternals'] = \count($aFoundCIDs) || \count($aFoundContentLocationUrls);