popphp/pop-mime

Pop PHP 框架的 MIME 组件

2.0.0 2023-11-09 04:51 UTC

This package is auto-updated.

Last update: 2024-09-09 06:53:42 UTC


README

Build Status Coverage Status

Join the chat at https://popphp.slack.com Join the chat at https://discord.gg/TZjgT74U7E

概述

pop-mime 是一个组件,提供处理 MIME 消息和内容的能力。使用它,您可以生成正确格式的 MIME 消息及其所有相关头部和部分,或者可以将现有的 MIME 消息解析为其相应的对象,并从那里进行操作。这可以与邮件和 HTTP 组件(如 pop-mailpop-http)一起使用。

pop-mimePop PHP 框架 的一个组件。

安装

使用 Composer 安装 pop-mime

composer require popphp/pop-mime

或者,在您的 composer.json 文件中引入它

"require": {
    "popphp/pop-mime" : "^2.0.0"
}

顶部

快速入门

创建简单的 MIME 消息

use Pop\Mime\Message;
use Pop\Mime\Part\Body;

$message = new Message();
$message->addHeaders([
    'Subject' => 'Hello World',
    'To'      => 'test@test.com',
    'Date'    => date('m/d/Y g:i A')
]);

$body = new Body('Hello World!');
$message->setBody($body);

echo $message;

这将生成以下 MIME 消息

Subject: Hello World
To: test@test.com
Date: 11/13/2023 5:38 PM

Hello World!

顶部

部分

主要消息对象本质上是一个顶级部分对象。一个部分对象可以包含头部、主体对象或其他嵌套部分对象。当一个部分对象有嵌套部分时,这将创建一个多部分消息。所需的边界将自动生成。

use Pop\Mime\Message;
use Pop\Mime\Part;

$message = new Message();
$message->addHeaders([
    'Subject' => 'Hello World',
    'To'      => 'test@test.com',
    'Date'    => date('m/d/Y g:i A')
]);

$message->setSubType('alternative');

$html = new Part();
$html->addHeader('Content-Type', 'text/html');
$html->setBody('<html><body><h1>This is the HTML message.</h1></body></html>');

$text = new Part();
$text->addHeader('Content-Type', 'text/plain');
$text->setBody('This is the text message.');

$message->addParts([$html, $text]);

echo $message;

上面的示例将生成

Subject: Hello World
To: test@test.com
Date: 10/31/2023 6:12 PM
Content-Type: multipart/alternative; boundary=f79f7366a24132e15132142b0a830a9cac98010f

This is a multi-part message in MIME format.
--f79f7366a24132e15132142b0a830a9cac98010f
Content-Type: text/html

<html><body><h1>This is the HTML message.</h1></body></html>
--f79f7366a24132e15132142b0a830a9cac98010f
Content-Type: text/plain

This is the text message.
--f79f7366a24132e15132142b0a830a9cac98010f--

顶部

附件

部分对象也可以是文件附件。

use Pop\Mime\Message;
use Pop\Mime\Part;

$message = new Message();
$message->addHeaders([
    'Subject'      => 'Hello World',
    'To'           => 'test@test.com',
    'Date'         => date('m/d/Y g:i A'),
    'MIME-Version' => '1.0'
]);

$message->setSubType('mixed');

$html = new Part();
$html->addHeader('Content-Type', 'text/html');
$html->setBody('<html><body><h1>This is the HTML message.</h1></body></html>');

$text = new Part();
$text->addHeader('Content-Type', 'text/plain');
$text->setBody('This is the text message.');

$file = new Part();
$file->addHeader('Content-Type', 'application/pdf');
$file->addFile('test.pdf');

$message->addParts([$html, $text, $file]);

echo $message;

上面的示例将生成

Subject: Hello World
To: test@test.com
Date: 11/13/2023 5:46 PM
MIME-Version: 1.0
Content-Type: multipart/mixed;
    boundary=5bedb090b0b35ce8029464dbec97013c3615cc5a

This is a multi-part message in MIME format.
--5bedb090b0b35ce8029464dbec97013c3615cc5a
Content-Type: text/html

<html><body><h1>This is the HTML message.</h1></body></html>
--5bedb090b0b35ce8029464dbec97013c3615cc5a
Content-Type: text/plain

This is the text message.
--5bedb090b0b35ce8029464dbec97013c3615cc5a
Content-Type: application/pdf
Content-Disposition: attachment; filename=test.pdf
Content-Transfer-Encoding: base64

JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURl
Y29kZT4+CnN0cmVhbQp4nC3KPQvCQBCE4X5/xdRC4uya3F1gOUhAC7vAgYXY+dEJpvHv5yIyMMXL
[...base64 encoded file contents...]
QzQ2RUUyMDU1RkIxOEY3PiBdCi9Eb2NDaGVja3N1bSAvNUZDMzQxQzBFQzc0MTA2MTZEQzFGRjk4
MDdFMzNFRDgKPj4Kc3RhcnR4cmVmCjc2NDQKJSVFT0YK

--5bedb090b0b35ce8029464dbec97013c3615cc5a--

顶部

头部

头部和头部值对象允许轻松创建并细粒度控制 MIME 消息的头部值。

$header = new Header('Content-Type', 'text/html');
echo $header;
Content-Type: text/html

顶部

头部值

头部值可以作为字符串传递到头部对象中,但它们将成为头部值对象。当获取它们时,您可以通过这种方式获取值对象

$header = new Header('Content-Type', 'text/html');
print_r($header->getValue()); // Returns an instance of Pop\Mime\Header\Value
Pop\Mime\Part\Header\Value Object
(
    [scheme:protected] => 
    [value:protected] => text/html
    [parameters:protected] => Array
        (
        )

    [delimiter:protected] => ;
    [forceQuote:protected] => 
)

头部值对象的好处是它允许对头部值进行精细控制,包括方案、参数、分隔符以及是否强制引号。

示例 1
use Pop\Mime\Part\Header;

$header = new Header('Content-Disposition');
$value  = new Header\Value('attachment');
$value->addParameter('filename', 'filename.jpg');

$header->addValue($value);
echo $header;
Content-Disposition: attachment; filename=filename.jpg
示例 2
$header = new Header('Authorization');
$value  = new Header\Value();
$value->setDelimiter(',')
    ->setScheme('Digest ')
    ->setForceQuote(true)
    ->addParameter('username', 'my_username')
    ->addParameter('realm', 'my_realm')
    ->addParameter('nonce', 'my-nonce-123456')
    ->addParameter('uri', '/my-uri')
    ->addParameter('response', 'my-response-123456');

$header->addValue($value);
echo $header;
Authorization: Digest username="my_username", realm="my_realm", nonce="my-nonce-123456", uri="/my-uri", response="my-response-123456"

您始终可以将头部值作为字符串获取

$headerString = $header->getValueAsString();

顶部

多个头部值

在某些情况下,一个头部可能需要包含多个值。它们可以作为数组传递给构造函数

$header = new Header('X-Multi-Header', ['value-1', 'value-2', 'value-3']);

或者,通过单个头部值对象

$header = new Header('X-Multi-Header');
$header->addValue('value-1')
    ->addValue('value-2')
    ->addValue('value-3')
echo $header;
X-Multi-Header: value-1
X-Multi-Header: value-2
X-Multi-Header: value-3

您可以通过索引访问每个头部值

$value = $header->getValue(2);

顶部

多部分消息

有一个接口可以轻松创建多部分消息,而不是像上面示例中那样手动进行。

HTTP 多部分表单

use Pop\Mime\Message;

$formData = [
    'username' => 'admin@test/whatever%DUDE!',
    'password' => '123456',
    'colors'   => ['Red', 'Green']
];

$formMessage = Message::createForm($formData);
echo $formMessage;
Content-Type: multipart/form-data; boundary=1f39a2798e049befa5b835a1434a6c7a21e9713a

This is a multi-part message in MIME format.
--1f39a2798e049befa5b835a1434a6c7a21e9713a
Content-Disposition: form-data; name=username

admin%40test%2Fwhatever%25DUDE%21
--1f39a2798e049befa5b835a1434a6c7a21e9713a
Content-Disposition: form-data; name=password

123456
--1f39a2798e049befa5b835a1434a6c7a21e9713a
Content-Disposition: form-data; name=colors[]

Red
--1f39a2798e049befa5b835a1434a6c7a21e9713a
Content-Disposition: form-data; name=colors[]

Green
--1f39a2798e049befa5b835a1434a6c7a21e9713a--

如果您只需要主要表单部分而不需要顶级头部和 MIME 预言,可以这样做

use Pop\Mime\Message;

$formData = [
    'username' => 'admin@test/whatever%DUDE!',
    'password' => '123456',
    'colors'   => ['Red', 'Green']
];

$formMessage = Message::createForm($formData);
echo $formMessage->renderRaw();

这将仅渲染表单数据内容,移除顶级头部和预言

--28fd350696733cf5d2c466383a7e0193a5cfffc3
Content-Disposition: form-data; name=username

admin%40test%2Fwhatever%25DUDE%21
--28fd350696733cf5d2c466383a7e0193a5cfffc3
Content-Disposition: form-data; name=password

123456
--28fd350696733cf5d2c466383a7e0193a5cfffc3
Content-Disposition: form-data; name=colors[]

Red
--28fd350696733cf5d2c466383a7e0193a5cfffc3
Content-Disposition: form-data; name=colors[]

Green
--28fd350696733cf5d2c466383a7e0193a5cfffc3--

包含文件的 HTTP 多部分表单

您也可以以几种不同的方式创建包含文件的表单数据

示例 1

$formData = [
    'file'     => [
        'filename'    => __DIR__ . '/test.pdf',
        'contentType' => 'application/pdf'
    ]
];

示例 2

$formData = [
    'file'     => [
        'filename' => 'test.pdf',
        'contents' => file_get_contents(__DIR__ . '/test.pdf')
        'mimeType' => 'application/pdf'
    ]
];

在示例 1 中,磁盘上的文件被传递并放入表单数据中。在示例 2 中,文件内容被明确传递到 contents 键以将文件数据设置到表单数据中。此外,为了灵活性,以下不区分大小写的键可用于 Content-Type

  • Content-Type
  • contentType
  • Mime-Type
  • mimeType
  • mime

顶部

解析

注意

此组件遵循 MIME 标准,使用 CRLF ("\r\n") 作为换行符。如果 MIME 消息不符合此标准,解析可能无法按预期工作。

解析消息

要解析 MIME 消息和内容,可以将 MIME 消息内容的字符串传递到以下方法中,它将返回一个包含所有相关头部和部分的消息对象。

use Pop\Mime\Message;

$message = Message::parseMessage($messageString);

解析头部字符串

如果您恰好有MIME头部字符串,您可以通过以下方式解析它。这将返回一个头部对象数组

use Pop\Mime\Message;

$headers = Message::parseMessage($headerString);

解析正文字符串

如果您恰好有MIME正文字符串,您可以通过以下方式解析它。这将返回一个部分对象数组

use Pop\Mime\Message;

$parts = Message::parseBody($bodyString);

解析单个部分字符串

如果您恰好有一个单个MIME部分的字符串,您可以通过以下方式解析它。这将返回一个部分对象

use Pop\Mime\Message;

$part = Message::parsePart($partString);

解析表单数据

作为一个特殊情况,如果您有multipart/form-data MIME内容,您可以按照以下方式解析它。这将返回一个表单数据数组

use Pop\Mime\Message;

$formData = Message::parseForm($formString);

请注意,为了使上述示例正常工作,它必须有一个至少包含Content-Type定义的头部,包括用于解析表单数据的边界

Content-Type: multipart/form-data;
    boundary=5bedb090b0b35ce8029464dbec97013c3615cc5a

--5bedb090b0b35ce8029464dbec97013c3615cc5a
Content-Disposition: form-data; name="username"

admin
--5bedb090b0b35ce8029464dbec97013c3615cc5a
Content-Disposition: form-data; name="password"

password
--5bedb090b0b35ce8029464dbec97013c3615cc5a--

顶部