Mime 元件
Mime 元件可讓您操作用於傳送電子郵件的 MIME 訊息,並提供與 MIME 類型相關的工具。
安裝
1
$ composer require symfony/mime
注意
如果您在 Symfony 應用程式外部安裝此元件,您必須在程式碼中 require `vendor/autoload.php
` 檔案,才能啟用 Composer 提供的類別自動載入機制。 請閱讀 `這篇文章` 以瞭解更多詳細資訊。
簡介
MIME (多用途網際網路郵件延伸) 是一種網際網路標準,它延伸了電子郵件的原始基本格式,以支援以下功能:
- 標頭和文字內容使用非 ASCII 字元;
- 具有多個部分的訊息主體 (例如 HTML 和純文字內容);
- 非文字附件:音訊、視訊、影像、PDF 等。
整個 MIME 標準既複雜又龐大,但 Symfony 抽象化了所有複雜性,以提供兩種建立 MIME 訊息的方式
用法
使用 `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`,這已為您完成,這要歸功於 `自動組態`。