From bebae735aae2c1030d6fb564d322c1480a51a86d Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 6 Nov 2024 12:13:20 +0000 Subject: [PATCH] Fixed #96: Add new option 'parseMultipartMixedTextAttachmentsAsFiles' to ezcMailParserOptions By setting this option like: $parser = new ezcMailParser(); $parser->options->parseMultipartMixedTextAttachmentsAsFiles = true; The parser returns text parts as attachments, but only if they are sub-parts of multipart/mixed parts. This is distinct from the 'parseTextAttachmentsAsFiles' option, which does it for *all* text parts. --- ChangeLog | 8 ++++++ src/options/parser_options.php | 21 +++++++++++++-- src/parser/interfaces/part_parser.php | 34 +++++++++++++++++++++--- src/parser/parser.php | 9 +++++++ src/parser/parts/multipart_parser.php | 2 +- src/parser/parts/rfc822_parser.php | 2 +- tests/parser/parser_test.php | 38 +++++++++++++++++++++++++++ 7 files changed, 107 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa17400d..e688d379 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +1.10.0 - [RELEASEDATE] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Fixed #96: Add new option 'parseMultipartMixedTextAttachmentsAsFiles' to + ezcMailParserOptions to retrieve only text attachments, that are sub-parts of + multipart/mixed parts an ezcMailFile object, instead of the default ezcMailText + object. + 1.9.7 - Tuesday 20 August 2024 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/options/parser_options.php b/src/options/parser_options.php index ac0b6816..3d0de157 100644 --- a/src/options/parser_options.php +++ b/src/options/parser_options.php @@ -33,6 +33,7 @@ * $options->mailClass = 'myCustomMailClass'; // extends ezcMail * $options->fileClass = 'myCustomFileClass'; // extends ezcMailFile * $options->parseTextAttachmentsAsFiles = true; // to get the text attachments in ezcMailFile objects + * $options->parseMultipartMixedTextAttachmentsAsFiles = true; // to get all text attachments that are sub-parts of multipart/mixed parts as ezcMailFile objects * * $parser = new ezcMailParser( $options ); * @@ -43,6 +44,7 @@ * $parser->options->mailClass = 'myCustomMailClass'; // extends ezcMail * $parser->options->fileClass = 'myCustomFileClass'; // extends ezcMailFile * $parser->options->parseTextAttachmentsAsFiles = true; + * $parser->options->parseMultipartMixedTextAttachmentsAsFiles = true; * * * @property string $mailClass @@ -54,7 +56,11 @@ * by the parser to handle file attachments. The default value is * ezcMailFile. * @property string $parseTextAttachmentsAsFiles - * Specifies whether to parse the text attachments in an ezcMailTextPart + * Specifies whether to parse the text attachments in an ezcMailText part + * (default) or in an ezcMailFile (by setting the option to true). + * @property string $parseMultipartMixedTextAttachmentsAsFiles + * Specifies whether to parse the text attachments that are sub-parts + * of a multipart/mixed part as an ezcMailText part * (default) or in an ezcMailFile (by setting the option to true). * @package Mail * @version //autogen// @@ -74,7 +80,8 @@ public function __construct( array $options = array() ) { $this->mailClass = 'ezcMail'; // default value for mail class is 'ezcMail' $this->fileClass = 'ezcMailFile'; // default value for file attachment class is 'ezcMailFile' - $this->parseTextAttachmentsAsFiles = false; // default is to parse text attachments in ezcMailTextPart objects + $this->parseTextAttachmentsAsFiles = false; // default is to parse text attachments in ezcMailText objects + $this->parseMultipartMixedTextAttachmentsAsFiles = false; // default is to parse multiple/mixed text attachments in ezcMailText objects parent::__construct( $options ); } @@ -140,6 +147,16 @@ public function __set( $propertyName, $propertyValue ) ezcMailPartParser::$parseTextAttachmentsAsFiles = $propertyValue; break; + + case 'parseMultipartMixedTextAttachmentsAsFiles': + if ( !is_bool( $propertyValue ) ) + { + throw new ezcBaseValueException( $propertyName, $propertyValue, 'bool' ); + } + $this->properties[$propertyName] = $propertyValue; + ezcMailPartParser::$parseMultipartMixedTextAttachmentsAsFiles = $propertyValue; + break; + default: throw new ezcBasePropertyNotFoundException( $propertyName ); } diff --git a/src/parser/interfaces/part_parser.php b/src/parser/interfaces/part_parser.php index a81378b3..89fd4e96 100644 --- a/src/parser/interfaces/part_parser.php +++ b/src/parser/interfaces/part_parser.php @@ -66,7 +66,7 @@ abstract class ezcMailPartParser 'sender', 'subject', 'sender', 'to' ); /** - * The default is to parse text attachments into ezcMailTextPart objects. + * The default is to parse text attachments into ezcMailText objects. * * Setting this to true before calling the parser will parse text attachments * into ezcMailFile objects. Use the parser options for this: @@ -81,6 +81,23 @@ abstract class ezcMailPartParser */ public static $parseTextAttachmentsAsFiles = false; + /** + * The default is to parse text attachments into ezcMailText objects. + * + * Setting this to true before calling the parser will parse text attachments + * that are sub-parts of Multipart/Mixed parts into ezcMailFail objects. + * Use the parser options for this: + * + * + * $parser = new ezcMailParser(); + * $parser->options->parseMultipartMixedTextAttachmentsAsFiles = true; + * // call $parser->parseMail( $set ); + * + * + * @var bool + */ + public static $parseMultipartMixedTextAttachmentsAsFiles = false; + /** * The name of the last header parsed. * @@ -118,7 +135,7 @@ abstract public function finish(); * @param ezcMailHeadersHolder $headers * @return ezcMailPartParser */ - static public function createPartParserForHeaders( ezcMailHeadersHolder $headers ) + static public function createPartParserForHeaders( ezcMailHeadersHolder $headers, ?ezcMailPartParser $parentParser = null ) { // default as specified by RFC2045 - #5.2 $mainType = 'text'; @@ -168,7 +185,18 @@ static public function createPartParserForHeaders( ezcMailHeadersHolder $headers break; case 'text': - if ( ezcMailPartParser::$parseTextAttachmentsAsFiles === true ) + if ( ezcMailPartParser::$parseMultipartMixedTextAttachmentsAsFiles === true ) + { + if ( $parentParser instanceof ezcMailMultipartMixedParser ) + { + $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers ); + } + else + { + $bodyParser = new ezcMailTextParser( $subType, $headers ); + } + } + else if ( ezcMailPartParser::$parseTextAttachmentsAsFiles === true ) { $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers ); } diff --git a/src/parser/parser.php b/src/parser/parser.php index fef2a83e..1604d5de 100644 --- a/src/parser/parser.php +++ b/src/parser/parser.php @@ -83,6 +83,15 @@ * $parser->options->parseTextAttachmentsAsFiles = true; * * + * In some cases, you might only want to create {@link ezcMailFile} objects + * for text attachments that are sub-parts of multipart/mixed parts. + * In that case, you can use the parseMultipartMixedTextAttachmentsAsFiles + * option. Example: + * + * $parser = new ezcMailParser(); + * $parser->options->parseMultipartMixedTextAttachmentsAsFiles = true; + * + * * @property ezcMailParserOptions $options * Holds the options you can set to the mail parser. * diff --git a/src/parser/parts/multipart_parser.php b/src/parser/parts/multipart_parser.php index d31fb802..52ecbd50 100644 --- a/src/parser/parts/multipart_parser.php +++ b/src/parser/parts/multipart_parser.php @@ -181,7 +181,7 @@ public function parseBody( $origLine ) { if ( $this->parserState == self::PARSE_STATE_HEADERS && $line == '' ) { - $this->currentPartParser = self::createPartParserForHeaders( $this->currentPartHeaders ); + $this->currentPartParser = self::createPartParserForHeaders( $this->currentPartHeaders, $this ); $this->parserState = self::PARSE_STATE_BODY; } else if ( $this->parserState == self::PARSE_STATE_HEADERS ) diff --git a/src/parser/parts/rfc822_parser.php b/src/parser/parts/rfc822_parser.php index eed7c413..0a74c30d 100644 --- a/src/parser/parts/rfc822_parser.php +++ b/src/parser/parts/rfc822_parser.php @@ -107,7 +107,7 @@ public function parseBody( $origLine ) } // get the correct body type - $this->bodyParser = self::createPartParserForHeaders( $headers ); + $this->bodyParser = self::createPartParserForHeaders( $headers, $this ); } else if ( $this->parserState == self::PARSE_STATE_HEADERS ) { diff --git a/tests/parser/parser_test.php b/tests/parser/parser_test.php index 77365add..8c324fae 100644 --- a/tests/parser/parser_test.php +++ b/tests/parser/parser_test.php @@ -1937,5 +1937,43 @@ public function testVarious14b() $this->assertEquals( 'application', $alternativeParts[1]->contentType ); $this->assertEquals( 'html', $alternativeParts[1]->mimeType ); } + + + public function testVarious14c() + { + $parser = new ezcMailParser(); + $parser->options->parseMultipartMixedTextAttachmentsAsFiles = true; + + $set = new SingleFileSet( 'various/test-html-text-and-text-attachment' ); + $mail = $parser->parseMail( $set ); + $this->assertEquals( 1, count( $mail ) ); + $mail = $mail[0]; + $parts = $mail->body->getParts(); + + $this->assertEquals( 4, count( $parts ) ); + $this->assertEquals( 'ezcMailMultipartAlternative', get_class( $parts[0] ) ); + + $this->assertEquals( 'ezcMailFile', get_class( $parts[1] ) ); + $this->assertEquals( '2_load_xss.html.txt', basename( $parts[1]->fileName ) ); + $this->assertEquals( 'text', $parts[1]->contentType ); + $this->assertEquals( 'plain', $parts[1]->mimeType ); + + $this->assertEquals( 'ezcMailFile', get_class( $parts[2] ) ); + $this->assertEquals( 'form_03.doc', basename( $parts[2]->fileName ) ); + $this->assertEquals( 'application', $parts[2]->contentType ); + $this->assertEquals( 'msword', $parts[2]->mimeType ); + + $this->assertEquals( 'ezcMailFile', get_class( $parts[3] ) ); + $this->assertEquals( '2932_1 Ward Grouped Mayor-Lismore.pdf', basename( $parts[3]->fileName ) ); + $this->assertEquals( 'application', $parts[3]->contentType ); + $this->assertEquals( 'pdf', $parts[3]->mimeType ); + + $alternativeParts = $parts[0]->getParts(); + $this->assertEquals( 2, count( $alternativeParts ) ); + $this->assertEquals( 'ezcMailText', get_class( $alternativeParts[0] ) ); + $this->assertEquals( 'plain', $alternativeParts[0]->subType ); + $this->assertEquals( 'ezcMailText', get_class( $alternativeParts[1] ) ); + $this->assertEquals( 'html', $alternativeParts[1]->subType ); + } } ?>