Improved MIME handling for JSON

This commit is contained in:
the-djmaze 2023-01-05 10:55:59 +01:00
parent d4e1e90eef
commit a2ddd493ce
11 changed files with 134 additions and 143 deletions

View file

@ -11,6 +11,8 @@
namespace MailSo\Imap; namespace MailSo\Imap;
use MailSo\Mime\ParameterCollection;
/** /**
* @category MailSo * @category MailSo
* @package Imap * @package Imap
@ -19,9 +21,9 @@ class BodyStructure
{ {
private string $sContentType; private string $sContentType;
private string $sCharset; private array $aContentTypeParams;
private array $aBodyParams; private string $sCharset;
private string $sContentID; private string $sContentID;
@ -63,6 +65,11 @@ class BodyStructure
return $this->sContentType; return $this->sContentType;
} }
public function ContentTypeParameters() : array
{
return $this->aContentTypeParams;
}
public function Size() : int public function Size() : int
{ {
return $this->iSize; return $this->iSize;
@ -133,8 +140,8 @@ class BodyStructure
{ {
// https://datatracker.ietf.org/doc/html/rfc3156#section-4 // https://datatracker.ietf.org/doc/html/rfc3156#section-4
return 'multipart/encrypted' === $this->sContentType return 'multipart/encrypted' === $this->sContentType
&& !empty($this->aBodyParams['protocol']) && !empty($this->aContentTypeParams['protocol'])
&& 'application/pgp-encrypted' === \strtolower(\trim($this->aBodyParams['protocol'])) && 'application/pgp-encrypted' === \strtolower(\trim($this->aContentTypeParams['protocol']))
// The multipart/encrypted body MUST consist of exactly two parts. // The multipart/encrypted body MUST consist of exactly two parts.
&& 2 === \count($this->aSubParts) && 2 === \count($this->aSubParts)
&& 'application/pgp-encrypted' === $this->aSubParts[0]->ContentType() && 'application/pgp-encrypted' === $this->aSubParts[0]->ContentType()
@ -146,8 +153,8 @@ class BodyStructure
{ {
// https://datatracker.ietf.org/doc/html/rfc3156#section-5 // https://datatracker.ietf.org/doc/html/rfc3156#section-5
return 'multipart/signed' === $this->sContentType return 'multipart/signed' === $this->sContentType
&& !empty($this->aBodyParams['protocol']) && !empty($this->aContentTypeParams['protocol'])
&& 'application/pgp-signature' === \strtolower(\trim($this->aBodyParams['protocol'])) && 'application/pgp-signature' === \strtolower(\trim($this->aContentTypeParams['protocol']))
// The multipart/signed body MUST consist of exactly two parts. // The multipart/signed body MUST consist of exactly two parts.
&& 2 === \count($this->aSubParts) && 2 === \count($this->aSubParts)
&& $this->aSubParts[1]->IsPgpSignature(); && $this->aSubParts[1]->IsPgpSignature();
@ -172,8 +179,8 @@ class BodyStructure
public function IsFlowedFormat() : bool public function IsFlowedFormat() : bool
{ {
return !empty($this->aBodyParams['format']) return !empty($this->aContentTypeParams['format'])
&& 'flowed' === \strtolower(\trim($this->aBodyParams['format'])) && 'flowed' === \strtolower(\trim($this->aContentTypeParams['format']))
&& !\in_array($this->sMailEncodingName, array('base64', 'quoted-printable')); && !\in_array($this->sMailEncodingName, array('base64', 'quoted-printable'));
} }
@ -255,20 +262,15 @@ class BodyStructure
public function GetPartByMimeIndex(string $sMimeIndex) : self public function GetPartByMimeIndex(string $sMimeIndex) : self
{ {
$oPart = null; $oPart = null;
if (\strlen($sMimeIndex)) if (\strlen($sMimeIndex)) {
{ if ($sMimeIndex === $this->sPartID) {
if ($sMimeIndex === $this->sPartID)
{
$oPart = $this; $oPart = $this;
} }
if (null === $oPart) if (null === $oPart) {
{ foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ $oSubPart) {
foreach ($this->aSubParts as /* @var $oSubPart \MailSo\Imap\BodyStructure */ $oSubPart)
{
$oPart = $oSubPart->GetPartByMimeIndex($sMimeIndex); $oPart = $oSubPart->GetPartByMimeIndex($sMimeIndex);
if (null !== $oPart) if (null !== $oPart) {
{
break; break;
} }
} }
@ -281,60 +283,43 @@ class BodyStructure
private static function decodeAttrParameter(array $aParams, string $sParamName, string $sCharset) : string private static function decodeAttrParameter(array $aParams, string $sParamName, string $sCharset) : string
{ {
$sResult = ''; $sResult = '';
if (isset($aParams[$sParamName])) if (isset($aParams[$sParamName])) {
{
$sResult = \MailSo\Base\Utils::DecodeHeaderValue($aParams[$sParamName], $sCharset); $sResult = \MailSo\Base\Utils::DecodeHeaderValue($aParams[$sParamName], $sCharset);
} } else if (isset($aParams[$sParamName.'*'])) {
else if (isset($aParams[$sParamName.'*']))
{
$aValueParts = \explode("''", $aParams[$sParamName.'*'], 2); $aValueParts = \explode("''", $aParams[$sParamName.'*'], 2);
if (2 === \count($aValueParts)) if (2 === \count($aValueParts)) {
{
$sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8; $sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8;
$sResult = \MailSo\Base\Utils::ConvertEncoding( $sResult = \MailSo\Base\Utils::ConvertEncoding(
\urldecode($aValueParts[1]), $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); \urldecode($aValueParts[1]), $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
} } else {
else
{
$sResult = \urldecode($aParams[$sParamName.'*']); $sResult = \urldecode($aParams[$sParamName.'*']);
} }
} } else {
else
{
$sCharset = ''; $sCharset = '';
$sCharsetIndex = -1; $sCharsetIndex = -1;
$aFileNames = array(); $aFileNames = array();
foreach ($aParams as $sName => $sValue) foreach ($aParams as $sName => $sValue) {
{
$aMatches = array(); $aMatches = array();
if (\preg_match('/^'.\preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches)) if (\preg_match('/^'.\preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches)) {
{
$iIndex = (int) $aMatches[1]; $iIndex = (int) $aMatches[1];
if ($sCharsetIndex < $iIndex && false !== \strpos($sValue, "''")) if ($sCharsetIndex < $iIndex && false !== \strpos($sValue, "''")) {
{
$aValueParts = \explode("''", $sValue, 2); $aValueParts = \explode("''", $sValue, 2);
if (2 === \count($aValueParts) && \strlen($aValueParts[0])) if (2 === \count($aValueParts) && \strlen($aValueParts[0])) {
{
$sCharsetIndex = $iIndex; $sCharsetIndex = $iIndex;
$sCharset = $aValueParts[0]; $sCharset = $aValueParts[0];
$sValue = $aValueParts[1]; $sValue = $aValueParts[1];
} }
} }
$aFileNames[$iIndex] = $sValue; $aFileNames[$iIndex] = $sValue;
} }
} }
if (\count($aFileNames)) if (\count($aFileNames)) {
{
\ksort($aFileNames, SORT_NUMERIC); \ksort($aFileNames, SORT_NUMERIC);
$sResult = \implode(\array_values($aFileNames)); $sResult = \implode(\array_values($aFileNames));
$sResult = \urldecode($sResult); $sResult = \urldecode($sResult);
if (\strlen($sCharset)) {
if (\strlen($sCharset))
{
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult, $sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);
} }
@ -353,8 +338,8 @@ class BodyStructure
$sContentTypeMain = ''; $sContentTypeMain = '';
$sContentTypeSub = ''; $sContentTypeSub = '';
$aSubParts = array(); $aSubParts = array();
$aBodyParams = array(); $aContentTypeParams = array();
$sName = ''; $sFileName = '';
$sCharset = ''; // \MailSo\Base\Enumerations\Charset::UTF_8 ? $sCharset = ''; // \MailSo\Base\Enumerations\Charset::UTF_8 ?
$sContentID = ''; $sContentID = '';
$sDescription = ''; $sDescription = '';
@ -362,20 +347,16 @@ class BodyStructure
$iSize = 0; $iSize = 0;
$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 (\is_array($aBodyStructure[0])) if (\is_array($aBodyStructure[0])) {
{
// Process multipart body structure // Process multipart body structure
$sContentTypeMain = 'multipart'; $sContentTypeMain = 'multipart';
$sContentTypeSub = 'mixed'; // primary default $sContentTypeSub = 'mixed'; // primary default
$sSubPartIDPrefix = ''; $sSubPartIDPrefix = '';
if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) {
{
// This multi-part is root part of message. // This multi-part is root part of message.
$sSubPartIDPrefix = $sPartID; $sSubPartIDPrefix = $sPartID;
$sPartID .= 'TEXT'; $sPartID .= 'TEXT';
} } else if (\strlen($sPartID)) {
else if (\strlen($sPartID))
{
// This multi-part is a part of another multi-part. // This multi-part is a part of another multi-part.
$sSubPartIDPrefix = $sPartID.'.'; $sSubPartIDPrefix = $sPartID.'.';
} }
@ -387,18 +368,15 @@ class BodyStructure
("text" "plain" ("charset" "utf-8") ) ("text" "plain" ("charset" "utf-8") )
("text" "html" ) ("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 (!$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) if (!$sCharset) {
{
$sCharset = $oPart->Charset(); $sCharset = $oPart->Charset();
} }
@ -411,26 +389,20 @@ class BodyStructure
* Now process the subparts containter like: * Now process the subparts containter like:
"alternative" ("boundary" "--boundary_id") "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]); $sContentTypeSub = \strtolower($aBodyStructure[$iExtraItemPos]);
++$iExtraItemPos; ++$iExtraItemPos;
if ($iExtraItemPos < \count($aBodyStructure) && \is_array($aBodyStructure[$iExtraItemPos])) if ($iExtraItemPos < \count($aBodyStructure) && \is_array($aBodyStructure[$iExtraItemPos])) {
{ $aContentTypeParams = self::getKeyValueListFromArrayList($aBodyStructure[$iExtraItemPos]);
$aBodyParams = self::getKeyValueListFromArrayList($aBodyStructure[$iExtraItemPos]);
} }
} }
} } else if (\is_string($aBodyStructure[0])) {
else if (\is_string($aBodyStructure[0]))
{
// Process simple (singlepart) body structure // Process simple (singlepart) body structure
if (7 > \count($aBodyStructure) || !\is_string($aBodyStructure[1])) if (7 > \count($aBodyStructure) || !\is_string($aBodyStructure[1])) {
{
return null; return null;
} }
@ -438,39 +410,33 @@ class BodyStructure
$sContentTypeSub = \strtolower($aBodyStructure[1]); $sContentTypeSub = \strtolower($aBodyStructure[1]);
$aBodyParamList = $aBodyStructure[2]; $aBodyParamList = $aBodyStructure[2];
if (\is_array($aBodyParamList)) if (\is_array($aBodyParamList)) {
{ $aContentTypeParams = self::getKeyValueListFromArrayList($aBodyParamList);
$aBodyParams = self::getKeyValueListFromArrayList($aBodyParamList); if (isset($aContentTypeParams['charset'])) {
if (isset($aBodyParams['charset'])) $sCharset = $aContentTypeParams['charset'];
{ }
$sCharset = $aBodyParams['charset']; $sFileName = self::decodeAttrParameter($aContentTypeParams, 'name', $sCharset);
if ($sFileName) {
$aContentTypeParams['name'] = $sFileName;
} }
$sName = self::decodeAttrParameter($aBodyParams, 'name', $sCharset);
} }
if (null !== $aBodyStructure[3]) if (null !== $aBodyStructure[3]) {
{ if (!\is_string($aBodyStructure[3])) {
if (!\is_string($aBodyStructure[3]))
{
return null; return null;
} }
$sContentID = $aBodyStructure[3]; $sContentID = $aBodyStructure[3];
} }
if (null !== $aBodyStructure[4]) if (null !== $aBodyStructure[4]) {
{ if (!\is_string($aBodyStructure[4])) {
if (!\is_string($aBodyStructure[4]))
{
return null; return null;
} }
$sDescription = $aBodyStructure[4]; $sDescription = $aBodyStructure[4];
} }
if (null !== $aBodyStructure[5]) if (null !== $aBodyStructure[5]) {
{ if (!\is_string($aBodyStructure[5])) {
if (!\is_string($aBodyStructure[5]))
{
return null; return null;
} }
$sMailEncodingName = $aBodyStructure[5]; $sMailEncodingName = $aBodyStructure[5];
@ -478,24 +444,20 @@ class BodyStructure
$iSize = \is_numeric($aBodyStructure[6]) ? (int) $aBodyStructure[6] : -1; $iSize = \is_numeric($aBodyStructure[6]) ? (int) $aBodyStructure[6] : -1;
if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) if (!\strlen($sPartID) || '.' === $sPartID[\strlen($sPartID) - 1]) {
{
// This is the only sub-part of the message (otherwise, it would be // This is the only sub-part of the message (otherwise, it would be
// one of sub-parts of a multi-part, and partID would already be fully set up). // one of sub-parts of a multi-part, and partID would already be fully set up).
$sPartID .= '1'; $sPartID .= '1';
} }
$iExtraItemPos = 7; $iExtraItemPos = 7;
if ('text' === $sContentTypeMain) if ('text' === $sContentTypeMain) {
{
/** /**
* A body type of type TEXT contains, immediately after the basic * A body type of type TEXT contains, immediately after the basic
* fields, the size of the body in text lines. * fields, the size of the body in text lines.
*/ */
++$iExtraItemPos; ++$iExtraItemPos;
} } else if ('message' === $sContentTypeMain && 'rfc822' === $sContentTypeSub) {
else if ('message' === $sContentTypeMain && 'rfc822' === $sContentTypeSub)
{
/** /**
* A body type of type MESSAGE and subtype RFC822 contains, * A body type of type MESSAGE and subtype RFC822 contains,
* immediately after the basic fields, the envelope structure, * immediately after the basic fields, the envelope structure,
@ -503,9 +465,7 @@ class BodyStructure
*/ */
$iExtraItemPos += 3; $iExtraItemPos += 3;
} }
} } else {
else
{
return null; return null;
} }
@ -515,18 +475,14 @@ class BodyStructure
$sDisposition = ''; $sDisposition = '';
$sFileName = ''; $sFileName = '';
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 (!\is_string($aDispList[0])) {
if (!\is_string($aDispList[0]))
{
return null; return null;
} }
$sDisposition = $aDispList[0]; $sDisposition = $aDispList[0];
if (\is_array($aDispList[1])) if (\is_array($aDispList[1])) {
{
$aDispositionParams = self::getKeyValueListFromArrayList($aDispList[1]); $aDispositionParams = self::getKeyValueListFromArrayList($aDispList[1]);
$sFileName = self::decodeAttrParameter($aDispositionParams, 'filename', $sCharset); $sFileName = self::decodeAttrParameter($aDispositionParams, 'filename', $sCharset);
} }
@ -536,13 +492,13 @@ class BodyStructure
$oStructure = new self; $oStructure = new self;
$oStructure->sContentType = \strtolower($sContentTypeMain.'/'.$sContentTypeSub); $oStructure->sContentType = \strtolower($sContentTypeMain.'/'.$sContentTypeSub);
$oStructure->aContentTypeParams = $aContentTypeParams;
$oStructure->sCharset = $sCharset; $oStructure->sCharset = $sCharset;
$oStructure->aBodyParams = $aBodyParams;
$oStructure->sContentID = $sContentID; $oStructure->sContentID = $sContentID;
$oStructure->sDescription = $sDescription; $oStructure->sDescription = $sDescription;
$oStructure->sMailEncodingName = \strtolower($sMailEncodingName); $oStructure->sMailEncodingName = \strtolower($sMailEncodingName);
$oStructure->sDisposition = \strtolower($sDisposition); $oStructure->sDisposition = \strtolower($sDisposition);
$oStructure->sFileName = \MailSo\Base\Utils::Utf8Clear($sFileName ?: $sName); $oStructure->sFileName = \MailSo\Base\Utils::Utf8Clear($sFileName);
$oStructure->iSize = $iSize; $oStructure->iSize = $iSize;
$oStructure->sPartID = $sPartID; $oStructure->sPartID = $sPartID;
$oStructure->aSubParts = $aSubParts; $oStructure->aSubParts = $aSubParts;
@ -571,12 +527,9 @@ class BodyStructure
{ {
$aDict = array(); $aDict = array();
$iLen = \count($aList); $iLen = \count($aList);
if (0 === ($iLen % 2)) if (0 === ($iLen % 2)) {
{ for ($iIndex = 0; $iIndex < $iLen; $iIndex += 2) {
for ($iIndex = 0; $iIndex < $iLen; $iIndex += 2) if (\is_string($aList[$iIndex]) && \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

@ -99,6 +99,7 @@ class Attachment implements \JsonSerializable
'Uid' => (string) $this->iUid, 'Uid' => (string) $this->iUid,
'MimeIndex' => (string) $this->oBodyStructure->PartID(), 'MimeIndex' => (string) $this->oBodyStructure->PartID(),
'MimeType' => $this->oBodyStructure->ContentType(), 'MimeType' => $this->oBodyStructure->ContentType(),
'MimeTypeParams' => $this->oBodyStructure->ContentTypeParameters(),
'FileName' => \MailSo\Base\Utils::SecureFileName($this->oBodyStructure->FileName(true)), 'FileName' => \MailSo\Base\Utils::SecureFileName($this->oBodyStructure->FileName(true)),
'EstimatedSize' => $this->oBodyStructure->EstimatedSize(), 'EstimatedSize' => $this->oBodyStructure->EstimatedSize(),
'Cid' => $this->oBodyStructure->ContentID(), 'Cid' => $this->oBodyStructure->ContentID(),

View file

@ -11,8 +11,8 @@
namespace MailSo\Mail; namespace MailSo\Mail;
use \MailSo\Base\Utils; use MailSo\Base\Utils;
use \MailSo\Imap\Enumerations\FetchType; use MailSo\Imap\Enumerations\FetchType;
/** /**
* @category MailSo * @category MailSo

View file

@ -151,15 +151,15 @@ class Attachment
$oAttachmentPart->Headers->append( $oAttachmentPart->Headers->append(
new Header(Enumerations\Header::CONTENT_TYPE, new Header(Enumerations\Header::CONTENT_TYPE,
$this->ContentType().';'. $this->ContentType().
(($oContentTypeParameters) ? ' '.$oContentTypeParameters->ToString() : '') ($oContentTypeParameters ? '; '.$oContentTypeParameters : '')
) )
); );
$oAttachmentPart->Headers->append( $oAttachmentPart->Headers->append(
new Header(Enumerations\Header::CONTENT_DISPOSITION, new Header(Enumerations\Header::CONTENT_DISPOSITION,
($this->IsInline() ? 'inline' : 'attachment').';'. ($this->IsInline() ? 'inline' : 'attachment').
(($oContentDispositionParameters) ? ' '.$oContentDispositionParameters->ToString() : '') ($oContentDispositionParameters ? '; '.$oContentDispositionParameters : '')
) )
); );

View file

@ -200,6 +200,11 @@ class Email implements \JsonSerializable
return \trim($sReturn); return \trim($sReturn);
} }
public function __toString() : string
{
return $this->ToString();
}
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function jsonSerialize() public function jsonSerialize()
{ {

View file

@ -66,6 +66,11 @@ class EmailCollection extends \MailSo\Base\Collection
return \implode(', ', $aReturn); return \implode(', ', $aReturn);
} }
public function __toString() : string
{
return $this->ToString();
}
private function parseEmailAddresses(string $sRawEmails) : void private function parseEmailAddresses(string $sRawEmails) : void
{ {
// $sRawEmails = \MailSo\Base\Utils::Trim($sRawEmails); // $sRawEmails = \MailSo\Base\Utils::Trim($sRawEmails);

View file

@ -126,13 +126,6 @@ class Header
$this->oParameters->setParameter($sName, $sValue); $this->oParameters->setParameter($sName, $sValue);
} }
private function wordWrapHelper(string $sValue, string $sGlue = "\r\n ") : string
{
return \trim(\substr(\wordwrap($this->NameWithDelimitrom().$sValue,
74, $sGlue
), \strlen($this->NameWithDelimitrom())));
}
public function __toString() : string public function __toString() : string
{ {
$sResult = $this->sFullValue; $sResult = $this->sFullValue;
@ -159,11 +152,12 @@ class Header
{ {
$oEmailCollection = new EmailCollection($this->sFullValue); $oEmailCollection = new EmailCollection($this->sFullValue);
if ($oEmailCollection && $oEmailCollection->count()) { if ($oEmailCollection && $oEmailCollection->count()) {
$sResult = $oEmailCollection->ToString(true, false); $sResult = $oEmailCollection->ToString(true);
} }
} }
return $this->NameWithDelimitrom().$this->wordWrapHelper($sResult); // https://www.rfc-editor.org/rfc/rfc2822#section-2.1.1
return \wordwrap($this->NameWithDelimitrom() . $sValue, 78, "\r\n ");
} }
public function IsSubject() : bool public function IsSubject() : bool

View file

@ -342,7 +342,7 @@ class Message extends Part
} }
$oPart->Headers->append( $oPart->Headers->append(
new Header(Enumerations\Header::CONTENT_TYPE, new Header(Enumerations\Header::CONTENT_TYPE,
$aAttachments[0]->ContentType().'; '.$oParameters->ToString()) $aAttachments[0]->ContentType().'; '.$oParameters)
); );
if ($resource = $aAttachments[0]->Resource()) { if ($resource = $aAttachments[0]->Resource()) {
@ -427,11 +427,6 @@ class Message extends Part
foreach ($this->aHeadersValue as $sName => $mValue) { foreach ($this->aHeadersValue as $sName => $mValue) {
if (!($bWithoutBcc && \strtolower(Enumerations\Header::BCC) === \strtolower($sName))) { if (!($bWithoutBcc && \strtolower(Enumerations\Header::BCC) === \strtolower($sName))) {
if (\is_object($mValue)) {
if ($mValue instanceof EmailCollection || $mValue instanceof Email || $mValue instanceof ParameterCollection) {
$mValue = $mValue->ToString();
}
}
$oRootPart->Headers->SetByName($sName, (string) $mValue); $oRootPart->Headers->SetByName($sName, (string) $mValue);
} }
} }

View file

@ -15,7 +15,7 @@ namespace MailSo\Mime;
* @category MailSo * @category MailSo
* @package Mime * @package Mime
*/ */
class Parameter class Parameter implements \JsonSerializable
{ {
private string $sName; private string $sName;
@ -88,4 +88,18 @@ class Parameter
return $this->sName . '="' . $this->sValue . '"'; return $this->sName . '="' . $this->sValue . '"';
} }
public function __toString() : string
{
return $this->ToString();
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return array(
'name' => $this->sName,
'value' => $this->sValue
);
}
} }

View file

@ -81,10 +81,29 @@ class ParameterCollection extends \MailSo\Base\Collection
$aResult[] = $sLine; $aResult[] = $sLine;
} }
} }
return \count($aResult) ? \implode('; ', $aResult) : ''; return \count($aResult) ? \implode('; ', $aResult) : '';
} }
public function __toString() : string
{
return $this->ToString();
}
/*
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$aResult = array();
foreach ($this as $oParam) {
$aResult[$oParam->Name()] = $oParam->Value();
}
return array(
'@Object' => 'Collection/ParameterCollection',
'@Collection' => $aResult
);
}
*/
private function reParseParameters() : void private function reParseParameters() : void
{ {
$aDataToReParse = $this->getArrayCopy(); $aDataToReParse = $this->getArrayCopy();

View file

@ -51,7 +51,12 @@ class Part
{ {
return \trim(\strtolower($this->Headers->ValueByName(Enumerations\Header::CONTENT_TYPE))); return \trim(\strtolower($this->Headers->ValueByName(Enumerations\Header::CONTENT_TYPE)));
} }
/*
public function ContentTypeParameters() : ParameterCollection
{
return $this->Headers->ParametersByName(\MailSo\Mime\Enumerations\Header::CONTENT_TYPE);
}
*/
public function ContentID() : string public function ContentID() : string
{ {
return \trim($this->Headers->ValueByName(Enumerations\Header::CONTENT_ID)); return \trim($this->Headers->ValueByName(Enumerations\Header::CONTENT_ID));