跳到內容

Mime 元件

編輯此頁面

Mime 元件可讓您操作用於傳送電子郵件的 MIME 訊息,並提供與 MIME 類型相關的工具。

安裝

1
$ composer require symfony/mime

注意

如果您在 Symfony 應用程式外部安裝此元件,您必須在程式碼中 require `vendor/autoload.php` 檔案,才能啟用 Composer 提供的類別自動載入機制。 請閱讀 `這篇文章` 以瞭解更多詳細資訊。

簡介

MIME (多用途網際網路郵件延伸) 是一種網際網路標準,它延伸了電子郵件的原始基本格式,以支援以下功能:

  • 標頭和文字內容使用非 ASCII 字元;
  • 具有多個部分的訊息主體 (例如 HTML 和純文字內容);
  • 非文字附件:音訊、視訊、影像、PDF 等。

整個 MIME 標準既複雜又龐大,但 Symfony 抽象化了所有複雜性,以提供兩種建立 MIME 訊息的方式

  • 基於 `Email` 類別的高階 API,可快速建立具有所有常見功能的電子郵件訊息;
  • 基於 `Message` 類別的低階 API,可完全掌控電子郵件訊息的每個部分。

用法

使用 `Email` 類別及其 *可串聯* 方法來撰寫整個電子郵件訊息

1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Mime\Email;

$email = (new Email())
    ->from('fabien@symfony.com')
    ->to('foo@example.com')
    ->cc('bar@example.com')
    ->bcc('baz@example.com')
    ->replyTo('fabien@symfony.com')
    ->priority(Email::PRIORITY_HIGH)
    ->subject('Important Notification')
    ->text('Lorem ipsum...')
    ->html('<h1>Lorem ipsum</h1> <p>...</p>')
;

此元件的唯一目的是建立電子郵件訊息。 使用 `Mailer 元件` 來實際傳送它們。

Twig 整合

Mime 元件與 Twig 完美整合,讓您可以使用 Twig 範本建立訊息、嵌入影像、內嵌 CSS 等。 有關如何使用這些功能的詳細資訊,請參閱 Mailer 文件:`Twig:HTML & CSS`。

但是,如果您在沒有 Symfony 框架的情況下使用 Mime 元件,則需要處理一些設定詳細資訊。

Twig 設定

若要與 Twig 整合,請使用 `BodyRenderer` 類別來呈現範本,並使用結果更新電子郵件訊息內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ...
use Symfony\Bridge\Twig\Mime\BodyRenderer;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

// when using the Mime component inside a full-stack Symfony application, you
// don't need to do this Twig setup. You only have to inject the 'twig' service
$loader = new FilesystemLoader(__DIR__.'/templates');
$twig = new Environment($loader);

$renderer = new BodyRenderer($twig);
// this updates the $email object contents with the result of rendering
// the template defined earlier with the given context
$renderer->render($email);

內嵌 CSS 樣式 (和其他擴充功能)

若要使用 `inline_css` 篩選器,請先安裝 Twig 擴充功能

1
$ composer require twig/cssinliner-extra

Now,啟用擴充功能

1
2
3
4
5
6
// ...
use Twig\Extra\CssInliner\CssInlinerExtension;

$loader = new FilesystemLoader(__DIR__.'/templates');
$twig = new Environment($loader);
$twig->addExtension(new CssInlinerExtension());

相同的程序應適用於啟用其他擴充功能,例如 `MarkdownExtension` 和 `InkyExtension`。

建立原始電子郵件訊息

這對於需要完全掌控每個電子郵件部分的高階應用程式非常有用。 不建議將其用於具有一般電子郵件需求的應用程式,因為它會增加複雜性,但沒有實際收益。

在繼續之前,務必先瞭解電子郵件訊息的低階結構。 考量一個訊息,其中包含同時作為文字和 HTML 的一些內容、嵌入在這些內容中的單一 PNG 影像,以及附加到訊息的 PDF 檔案。 MIME 標準允許可使用不同的方式來結構化此訊息,但下列樹狀結構是在大多數電子郵件用戶端上運作的結構

1
2
3
4
5
6
7
multipart/mixed
├── multipart/related
│   ├── multipart/alternative
│   │   ├── text/plain
│   │   └── text/html
│   └── image/png
└── application/pdf

這是每個 MIME 訊息部分的目的

  • `multipart/alternative`:當兩個或多個部分是相同 (或非常相似) 內容的替代方案時使用。 慣用格式必須最後新增。
  • `multipart/mixed`:用於在同一訊息中傳送不同的內容類型,例如在附加檔案時。
  • `multipart/related`:用於指示每個訊息部分都是聚合整體的元件。 最常見的用法是顯示嵌入在訊息內容中的影像。

當使用低階 `Message` 類別來建立電子郵件訊息時,您必須牢記以上所有內容,才能手動定義電子郵件的不同部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Mime\Header\Headers;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
use Symfony\Component\Mime\Part\TextPart;

$headers = (new Headers())
    ->addMailboxListHeader('From', ['fabien@symfony.com'])
    ->addMailboxListHeader('To', ['foo@example.com'])
    ->addTextHeader('Subject', 'Important Notification')
;

$textContent = new TextPart('Lorem ipsum...');
$htmlContent = new TextPart('<h1>Lorem ipsum</h1> <p>...</p>', null, 'html');
$body = new AlternativePart($textContent, $htmlContent);

$email = new Message($headers, $body);

透過建立適當的電子郵件多部分,即可嵌入影像和附加檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ...
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;

// ...
$embeddedImage = new DataPart(fopen('/path/to/images/logo.png', 'r'), null, 'image/png');
$imageCid = $embeddedImage->getContentId();

$attachedFile = new DataPart(fopen('/path/to/documents/terms-of-use.pdf', 'r'), null, 'application/pdf');

$textContent = new TextPart('Lorem ipsum...');
$htmlContent = new TextPart(sprintf(
    '<img src="cid:%s"/> <h1>Lorem ipsum</h1> <p>...</p>', $imageCid
), null, 'html');
$bodyContent = new AlternativePart($textContent, $htmlContent);
$body = new RelatedPart($bodyContent, $embeddedImage);

$messageParts = new MixedPart($body, $attachedFile);

$email = new Message($headers, $messageParts);

序列化電子郵件訊息

以 `Email` 或 `Message` 類別建立的電子郵件訊息可以序列化,因為它們是簡單的資料物件

1
2
3
4
5
6
$email = (new Email())
    ->from('fabien@symfony.com')
    // ...
;

$serializedEmail = serialize($email);

常見的用例是儲存序列化的電子郵件訊息、將它們包含在使用 `Messenger 元件` 傳送的訊息中,並在稍後傳送它們時重新建立它們。 使用 `RawMessage` 類別,從其序列化的內容重新建立電子郵件訊息

1
2
3
4
5
6
7
use Symfony\Component\Mime\RawMessage;

// ...
$serializedEmail = serialize($email);

// later, recreate the original message to actually send it
$message = new RawMessage(unserialize($serializedEmail));

MIME 類型工具

雖然 MIME 主要設計用於建立電子郵件,但 MIME 標準定義的內容類型 (也稱為 `MIME 類型` 和 「媒體類型」) 在電子郵件以外的通訊協定 (例如 HTTP) 中也很重要。 這就是此元件也提供用於處理 MIME 類型的工具的原因。

`MimeTypes` 類別會在 MIME 類型和檔案名稱副檔名之間轉換

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Mime\MimeTypes;

$mimeTypes = new MimeTypes();
$exts = $mimeTypes->getExtensions('application/javascript');
// $exts = ['js', 'jsm', 'mjs']
$exts = $mimeTypes->getExtensions('image/jpeg');
// $exts = ['jpeg', 'jpg', 'jpe']

$types = $mimeTypes->getMimeTypes('js');
// $types = ['application/javascript', 'application/x-javascript', 'text/javascript']
$types = $mimeTypes->getMimeTypes('apk');
// $types = ['application/vnd.android.package-archive']

這些方法會傳回包含一個或多個元素的陣列。 元素位置表示其優先順序,因此第一個傳回的副檔名是慣用的副檔名。

猜測 MIME 類型

另一個實用的工具可讓您猜測任何指定檔案的 MIME 類型

1
2
3
4
5
6
use Symfony\Component\Mime\MimeTypes;

$mimeTypes = new MimeTypes();
$mimeType = $mimeTypes->guessMimeType('/some/path/to/image.gif');
// Guessing is not based on the file name, so $mimeType will be 'image/gif'
// only if the given file is truly a GIF image

Guessing the MIME type is a time-consuming process that requires inspecting part of the file contents. Symfony applies multiple guessing mechanisms, one of them based on the PHP `fileinfo 擴充功能`。 建議您安裝該擴充功能以提升猜測效能。

新增 MIME 類型猜測器

您可以透過建立實作 `MimeTypeGuesserInterface` 的類別,來新增您自己的 MIME 類型猜測器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace App;

use Symfony\Component\Mime\MimeTypeGuesserInterface;

class SomeMimeTypeGuesser implements MimeTypeGuesserInterface
{
    public function isGuesserSupported(): bool
    {
        // return true when the guesser is supported (might depend on the OS for instance)
        return true;
    }

    public function guessMimeType(string $path): ?string
    {
        // inspect the contents of the file stored in $path to guess its
        // type and return a valid MIME type ... or null if unknown

        return '...';
    }
}

MIME type guessers must be `registered as services` and `tagged` with the `mime.mime_type_guesser` tag. If you're using the `default services.yaml configuration`,這已為您完成,這要歸功於 `自動組態`。

這項工作(包括程式碼範例)已根據 `Creative Commons BY-SA 3.0` 授權條款授權。
TOC
    版本