The Mime Component

The Mime component allows manipulating the MIME messages used to send emailsand provides utilities related to MIME types.

New in version 4.3: The Mime component was introduced in Symfony 4.3 and it's stillconsidered an experimental feature.

Installation

  1. $ composer require symfony/mime

Note

If you install this component outside of a Symfony application, you mustrequire the vendor/autoload.php file in your code to enable the classautoloading mechanism provided by Composer. Readthis article for more details.

Introduction

MIME (Multipurpose Internet Mail Extensions) is an Internet standard thatextends the original basic format of emails to support features like:

  • Headers and text contents using non-ASCII characters;
  • Message bodies with multiple parts (e.g. HTML and plain text contents);
  • Non-text attachments: audio, video, images, PDF, etc.The entire MIME standard is complex and huge, but Symfony abstracts all thatcomplexity to provide two ways of creating MIME messages:

  • A high-level API based on the Email classto quickly create email messages with all the common features;

  • A low-level API based on the Message classto have an absolute control over every single part of the email message.

Usage

Use the Email class and their _chainable_methods to compose the entire email message:

  1. use Symfony\Component\Mime\Email;
  2.  
  3. $email = (new Email())
  4. ->from('[email protected]')
  5. ->to('[email protected]')
  6. ->cc('[email protected]')
  7. ->bcc('[email protected]')
  8. ->replyTo('[email protected]')
  9. ->priority(Email::PRIORITY_HIGH)
  10. ->subject('Important Notification')
  11. ->text('Lorem ipsum...')
  12. ->html('<h1>Lorem ipsum</h1> <p>...</p>')
  13. ;

This only purpose of this component is to create the email messages. Use theMailer component to actually send them. In Symfonyapplications, it's easier to use the Mailer integration.

Most of the details about how to create Email objects, including Twig integration,can be found in the Mailer documentation.

Twig Integration

The Mime component comes with excellent integration with Twig, allowing you tocreate messages from Twig templates, embed images, inline CSS and more. Detailson how to use those features can be found in the Mailer documentation:Twig: HTML & CSS.

But if you're using the Mime component without the Symfony framework, you'll needto handle a few setup details.

Twig Setup

To integrate with Twig, use the BodyRendererclass to render the template and update the email message contents with the results:

  1. // ...
  2. use Symfony\Bridge\Twig\Mime\BodyRenderer;
  3. use Twig\Environment;
  4. use Twig\Loader\FilesystemLoader;
  5.  
  6. // when using the Mime component inside a full-stack Symfony application, you
  7. // don't need to do this Twig setup. You only have to inject the 'twig' service
  8. $loader = new FilesystemLoader(__DIR__.'/templates');
  9. $twig = new Environment($loader);
  10.  
  11. $renderer = new BodyRenderer($twig);
  12. // this updates the $email object contents with the result of rendering
  13. // the template defined earlier with the given context
  14. $renderer->render($email);

Inlining CSS Styles (and other Extensions)

To use the inline_css filter, first install the Twigextension:

  1. $ composer require twig/cssinliner-extension

Now, enable the extension:

  1. // ...
  2. use Twig\CssInliner\CssInlinerExtension;
  3.  
  4. $loader = new FilesystemLoader(__DIR__.'/templates');
  5. $twig = new Environment($loader);
  6. $twig->addExtension(new CssInlinerExtension());

The same process should be used for enabling other extensions, like theMarkdownExtension and InkyExtension.

Creating Raw Email Messages

This is useful for advanced applications that need absolute control over everyemail part. It's not recommended for applications with regular emailrequirements because it adds complexity for no real gain.

Before continuing, it's important to have a look at the low level structure ofan email message. Consider a message which includes some content as both textand HTML, a single PNG image embedded in those contents and a PDF file attachedto it. The MIME standard allows structuring this message in different ways, butthe following tree is the one that works on most email clients:

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

This is the purpose of each MIME message part:

  • multipart/alternative: used when two or more parts are alternatives of thesame (or very similar) content. The preferred format must be added last.
  • multipart/mixed: used to send different content types in the same message,such as when attaching files.
  • multipart/related: used to indicate that each message part is a componentof an aggregate whole. The most common usage is to display images embeddedin the message contents.When using the low-level Message class tocreate the email message, you must keep all the above in mind to define thedifferent parts of the email by hand:
  1. use Symfony\Component\Mime\Header\Headers;
  2. use Symfony\Component\Mime\Message;
  3. use Symfony\Component\Mime\Part\Multipart\AlternativePart;
  4. use Symfony\Component\Mime\Part\TextPart;
  5.  
  6. $headers = (new Headers())
  7. ->addMailboxListHeader('From', ['[email protected]'])
  8. ->addMailboxListHeader('To', ['[email protected]'])
  9. ->addTextHeader('Subject', 'Important Notification')
  10. ;
  11.  
  12. $textContent = new TextPart('Lorem ipsum...');
  13. $htmlContent = new TextPart('<h1>Lorem ipsum</h1> <p>...</p>', 'html');
  14. $body = new AlternativePart($textContent, $htmlContent);
  15.  
  16. $email = new Message($headers, $body);

Embedding images and attaching files is possible by creating the appropriateemail multiparts:

  1. // ...
  2. use Symfony\Component\Mime\Part\DataPart;
  3. use Symfony\Component\Mime\Part\Multipart\MixedPart;
  4. use Symfony\Component\Mime\Part\Multipart\RelatedPart;
  5.  
  6. // ...
  7. $embeddedImage = new DataPart(fopen('/path/to/images/logo.png', 'r'), null, 'image/png');
  8. $imageCid = $embeddedImage->getContentId();
  9.  
  10. $attachedFile = new DataPart(fopen('/path/to/documents/terms-of-use.pdf', 'r'), null, 'application/pdf');
  11.  
  12. $textContent = new TextPart('Lorem ipsum...');
  13. $htmlContent = new TextPart(sprintf(
  14. '<img src="cid:%s"/> <h1>Lorem ipsum</h1> <p>...</p>', $imageCid
  15. ), 'html');
  16. $bodyContent = new AlternativePart($textContent, $htmlContent);
  17. $body = new RelatedPart($bodyContent, $embeddedImage);
  18.  
  19. $messageParts = new MixedPart($body, $attachedFile);
  20.  
  21. $email = new Message($headers, $messageParts);

Serializing Email Messages

Email messages created with either the Email or Message classes can beserialized because they are simple data objects:

  1. $email = (new Email())
  2. ->from('[email protected]')
  3. // ...
  4. ;
  5.  
  6. $serializedEmail = serialize($email);

A common use case is to store serialized email messages, include them in amessage sent with the Messenger component andrecreate them later when sending them. Use theRawMessage class to recreate email messagesfrom their serialized contents:

  1. use Symfony\Component\Mime\RawMessage;
  2.  
  3. // ...
  4. $serializedEmail = serialize($email);
  5.  
  6. // later, recreate the original message to actually send it
  7. $message = new RawMessage(unserialize($serializedEmail));

MIME Types Utilities

Although MIME was designed mainly for creating emails, the content types (alsoknown as MIME types and "media types") defined by MIME standards are also ofimportance in communication protocols outside of email, such as HTTP. That'swhy this component also provides utilities to work with MIME types.

The MimeTypes class transforms betweenMIME types and file name extensions:

  1. use Symfony\Component\Mime\MimeTypes;
  2.  
  3. $mimeTypes = new MimeTypes();
  4. $exts = $mimeTypes->getExtensions('application/javascript');
  5. // $exts = ['js', 'jsm', 'mjs']
  6. $exts = $mimeTypes->getExtensions('image/jpeg');
  7. // $exts = ['jpeg', 'jpg', 'jpe']
  8.  
  9. $mimeTypes = $mimeTypes->getMimeTypes('js');
  10. // $mimeTypes = ['application/javascript', 'application/x-javascript', 'text/javascript']
  11. $mimeTypes = $mimeTypes->getMimeTypes('apk');
  12. // $mimeTypes = ['application/vnd.android.package-archive']

These methods return arrays with one or more elements. The element positionindicates its priority, so the first returned extension is the preferred one.

Guessing the MIME Type

Another useful utility allows to guess the MIME type of any given file:

  1. use Symfony\Component\Mime\MimeTypes;
  2.  
  3. $mimeTypes = new MimeTypes();
  4. $mimeType = $mimeTypes->guessMimeType('/some/path/to/image.gif');
  5. // Guessing is not based on the file name, so $mimeType will be 'image/gif'
  6. // only if the given file is truly a GIF image

Guessing the MIME type is a time-consuming process that requires inspectingpart of the file contents. Symfony applies multiple guessing mechanisms, oneof them based on the PHP fileinfo extension. It's recommended to installthat extension to improve the guessing performance.

Adding a MIME Type Guesser

You can register your own MIME type guesser by creating a class that implementsMimeTypeGuesserInterface:

  1. namespace App;
  2.  
  3. use Symfony\Component\Mime\MimeTypeGuesserInterface;
  4.  
  5. class SomeMimeTypeGuesser implements MimeTypeGuesserInterface
  6. {
  7. public function isGuesserSupported(): bool
  8. {
  9. // return true when the guesser is supported (might depend on the OS for instance)
  10. return true;
  11. }
  12.  
  13. public function guessMimeType(string $path): ?string
  14. {
  15. // inspect the contents of the file stored in $path to guess its
  16. // type and return a valid MIME type ... or null if unknown
  17.  
  18. return '...';
  19. }
  20. }