parse(fopen('path/to/file.txt'), true); * // use $message here * ``` * * @author Zaahid Bateson */ class MailMimeParser { /** * @var string the default charset used to encode strings (or string content * like streams) returned by MailMimeParser (for e.g. the string * returned by calling $message->getTextContent()). */ public const DEFAULT_CHARSET = 'UTF-8'; /** * @var string the default definition file. */ private const DEFAULT_DEFINITIONS_FILE = __DIR__ . '/di_config.php'; /** * @var Container The instance's dependency injection container. */ protected Container $container; /** * @var MessageParserService for parsing messages */ protected MessageParserService $messageParser; /** * @var Container The static global container */ private static ?Container $globalContainer = null; /** * @var array an array of global definitions * being used. */ private static array $globalDefinitions = [self::DEFAULT_DEFINITIONS_FILE]; /** * Returns the default ContainerBuilder with default loaded definitions. */ private static function getGlobalContainerBuilder() : ContainerBuilder { $builder = new ContainerBuilder(); foreach (self::$globalDefinitions as $def) { $builder->addDefinitions($def); } return $builder; } /** * Sets global configuration for php-di. Overrides all previously set * definitions. You can optionally not use the default MMP definitions file * by passing 'false' to the $useDefaultDefinitionsFile argument. * * @var array array of definitions */ public static function setGlobalPhpDiConfigurations(array $phpDiConfigs, bool $useDefaultDefinitionsFile = true) : void { self::$globalDefinitions = \array_merge( ($useDefaultDefinitionsFile) ? [self::DEFAULT_DEFINITIONS_FILE] : [], $phpDiConfigs ); self::$globalContainer = null; } public static function addGlobalPhpDiContainerDefinition(array|string|DefinitionSource $phpDiConfig) : void { self::$globalDefinitions[] = $phpDiConfig; self::$globalContainer = null; } public static function resetGlobalPhpDiContainerDefinitions() : void { self::$globalDefinitions = [self::DEFAULT_DEFINITIONS_FILE]; self::$globalContainer = null; } /** * Returns the global php-di container instance. * */ public static function getGlobalContainer() : Container { if (self::$globalContainer === null) { $builder = self::getGlobalContainerBuilder(); self::$globalContainer = $builder->build(); } return self::$globalContainer; } /** * Registers the provided logger globally. */ public static function setGlobalLogger(LoggerInterface $logger) : void { self::$globalDefinitions[] = [LoggerInterface::class => $logger]; self::$globalContainer = null; } /** * Provide custom php-di configuration to customize dependency injection, or * provide a custom logger for the instance only. * * Note: this only affects instances created through this instance of the * MailMimeParser, or the container itself. Calling 'new MimePart()' * directly for instance, would use the global service locator to setup any * dependencies MimePart needs. This applies to a provided $logger too -- * it would only affect instances of objects created through the provided * MailMimeParser. * * Passing false to $useGlobalDefinitions will cause MMP to not use any * global definitions. The default definitions file * MailMimeParser::DEFAULT_DEFINITIONS_FILE will still be added though. * * @see MailMimeParser::setGlobalPhpDiConfiguration() to register * configuration globally. * @see MailMimeParser::setGlobalLogger() to set a global logger */ public function __construct( ?LoggerInterface $logger = null, array|string|DefinitionSource|null $phpDiContainerConfig = null, bool $useGlobalDefinitions = true ) { if ($phpDiContainerConfig !== null || $logger !== null) { if ($useGlobalDefinitions) { $builder = self::getGlobalContainerBuilder(); } else { $builder = new ContainerBuilder(); $builder->addDefinitions(self::DEFAULT_DEFINITIONS_FILE); } if ($phpDiContainerConfig !== null) { $builder->addDefinitions($phpDiContainerConfig); } if ($logger !== null) { $builder->addDefinitions([LoggerInterface::class => $logger]); } $this->container = $builder->build(); } else { $this->container = self::getGlobalContainer(); } $this->messageParser = $this->container->get(MessageParserService::class); } /** * Parses the passed stream handle or string into an {@see IMessage} object * and returns it. * * If the passed $resource is a resource handle or StreamInterface, the * resource must remain open while the returned IMessage object exists. * Pass true as the second argument to have the resource attached to the * IMessage and closed for you when it's destroyed, or pass false to * manually close it if it should remain open after the IMessage object is * destroyed. * * @param resource|StreamInterface|string $resource The resource handle to * the input stream of the mime message, or a string containing a * mime message. * @param bool $attached pass true to have it attached to the returned * IMessage and destroyed with it. */ public function parse(mixed $resource, bool $attached) : IMessage { $stream = Utils::streamFor( $resource, ['metadata' => ['mmp-detached-stream' => ($attached !== true)]] ); if (!$stream->isSeekable()) { $stream = new CachingStream($stream); } return $this->messageParser->parse($stream); } }