Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2 new Symfony components: HttpClient and MIME

2 new Symfony components: HttpClient and MIME

Fabien Potencier

March 01, 2019
Tweet

More Decks by Fabien Potencier

Other Decks in Technology

Transcript

  1. Back to the basics...
    Fabien Potencier
    @fabpot

    View full-size slide

  2. Process > proc_open()
    VarDumper > var_dump()
    VarExporter > var_export()
    Finder > *Iterator
    HttpFoundation > $_GET/$_POST
    HttpKernel > echo
    What's next?

    View full-size slide

  3. file_get_contents()
    no dependencies

    View full-size slide

  4. 3) Symfony HTTPClient
    Do HTTP requests, the powerful way
    Fabien Potencier
    @fabpot

    View full-size slide

  5. Great DX - Great Perf - Great Design
    (auto) proxy configuration
    DNS cache pre-population
    1st class error handling
    auto-gzip compression
    timeout management
    public key pinning
    progress callback
    extended info
    request abort
    HTTP/2-push
    IDN support
    Psr18Client
    time stats
    streaming
    base URI
    ...

    View full-size slide

  6. 379 requests in
    HTTP/2
    0,3 s!

    View full-size slide

  7. What’s next? Your contrib!
    TraceableHttpClient, profiler panel, logger
    integration, mock client, record/replay, raw
    sockets, cookie jar, ...

    View full-size slide

  8. R.I.P. Goutte
    Integrates with battle-tested components
    HttpClient
    + BrowserKit
    + DomCrawler
    + CssSelector
    + HttpCache

    View full-size slide

  9. Back to the basics...
    part 4/n
    Fabien Potencier
    @fabpot

    View full-size slide

  10. 4) Symfony MIME
    Everything you need to create beautiful emails
    Fabien Potencier
    @fabpot

    View full-size slide

  11. Symfony Mime

    View full-size slide

  12. use Symfony\Component\Mime\Email;
    $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text message')
    ->html('Some HTML message')
    ->attach('doc.txt')
    ;
    The basics

    View full-size slide

  13. $email = (new Email())
    ->from('[email protected]')
    ->to(new Address('[email protected]'))
    ->addTo(new NamedAddress('[email protected]', 'Fabien'))
    ->addCc('[email protected]', '[email protected]')
    ->addCc(...['[email protected]', '[email protected]'])
    ->subject('Some subject')
    ->text('Some text')
    ;
    from, to, cc, bcc

    View full-size slide

  14. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text message')
    ->html('Some HTML message')
    ;
    echo strlen(serialize($email));
    Email is a data object
    Only 2k
    vs
    16k for Swiftmailer

    View full-size slide

  15. Why is it so different

    from Swiftmailer?

    View full-size slide

  16. $email = (new Email())
    ->text('Some text message')
    ->html('Some HTML message')
    ;
    $email = (new \Swift_Message())
    ->setBody('Some text message')
    ->addPart('Some HTML message', 'text/html')
    ;
    A better data object model
    16k serialized
    38 objects
    complex serialization
    "fixed" headers
    2k serialized
    7 objects
    simple serialization
    "dynamic" headers

    View full-size slide

  17. echo $email->toString();
    sleep(2);
    $email->to('[email protected]');
    echo $email->toString();
    Fixed vs dynamic headers
    Different

    set of headers
    Date, Boundary, Message-ID

    View full-size slide

  18. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text(fopen('email.txt', 'r'))
    ->html(fopen('email.html', 'r'))
    ;
    echo $email->toString();
    foreach ($email->toIterable() as $chunk) {
    echo $chunk;
    }
    String or resources, your choice

    View full-size slide

  19. // Email extends Message
    use Symfony\Component\Mime\Message;
    use Symfony\Component\Mime\Part\TextPart;
    use Symfony\Component\Mime\Header\Headers;
    $body = new TextPart('Some content');
    $headers = (new Headers())
    ->addMailboxListHeader('From', ['[email protected]'])
    ->addMailboxListHeader('To', ['[email protected]'])
    ->AddTextHeader('Subject', 'Some subject')
    ;
    $email = new Message($headers, $body);
    And you get full control!

    View full-size slide

  20. $txt = new TextPart('Some content');
    $html = new TextPart('Some content', 'html');
    $body = new AlternativePart($txt, $html);
    $email = new Message($headers, $body);
    Get creative

    View full-size slide

  21. A "complete" email
    multipart/mixed
    |
    |------------> multipart/related
    | |
    | |------------> multipart/alternative
    | | |
    | | ------------> text/plain
    | | |
    | | ------------> text/html
    | |
    | ------------> image/png
    |
    ------------> application/pdf
    ->text()
    ->html()
    ->embed()
    ->attach()

    View full-size slide

  22. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->setBody($body)
    ;
    Mix several approaches

    View full-size slide

  23. $email
    ->attach('Some content', 'doc.txt', 'text/plain')
    ->attachFromPath('/path/to/doc.txt')
    ->attach(fopen('doc.txt', 'r'), 'doc.txt', 'text/plain')
    ;
    Attachments

    View full-size slide

  24. $email = (new Email())
    ->from('[email protected]')
    ->to('[email protected]')
    ->subject('Some subject')
    ->text('Some text')
    ->html('The new logo: ')
    ->embedFromPath('logo-small.jpg', 'logo.jpg')
    ;
    Embeds

    View full-size slide

  25. // Email extends Message extends RawMessage
    use Symfony\Component\Mime\RawMessage;
    $message = new RawMessage($email->toString());
    $message->toString();
    Go raw!
    Serialize an email as
    a string instead of a PHP
    object

    View full-size slide

  26. Creating Emails
    with Twig
    Twig is perfect for emails
    aka, Twig is not dead and still very useful :)

    View full-size slide

  27. use Symfony\Bridge\Twig\Mime\Renderer;
    use Symfony\Bridge\Twig\Mime\TemplatedEmail;
    use Twig\Environment;
    use Twig\Loader\FilesystemLoader;
    use Symfony\Component\Mime\NamedAddress;
    $twig = new Environment($loader = new FilesystemLoader(__DIR__.'/templates'));
    $loader->addPath(__DIR__.'/images', 'images');
    $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->text('Some text content')
    ->htmlTemplate('simple.html.twig')
    ->context([
    'city' => 'Lille'
    ])
    ;
    $renderer = new Renderer($twig);
    echo $renderer->render($email)->toString();
    Native integration with Twig

    View full-size slide


  28. Welcome {{ email.toName }} from {{ city }}!




    Native integration with Twig
    Symfony\Bridge\Twig\Mime\
    WrappedTemplatedEmail
    Twig template name
    Template context

    View full-size slide

  29. {% do email.attach('@docs/doc.pdf') %}

    Welcome {{ email.toName }}!




    Native integration with Twig

    View full-size slide

  30. {% do email.priority(5) %}

    Welcome {{ email.toName }}!




    Native integration with Twig

    View full-size slide

  31. $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->textTemplate('simple.txt.twig')
    ->htmlTemplate('simple.html.twig')
    ;
    Native integration with Twig

    View full-size slide

  32. $email = (new TemplatedEmail())
    ->from('[email protected]')
    ->to(new NamedAddress('[email protected]', 'Fabien'))
    ->template('simple.email.twig')
    ;
    Native integration with Twig

    View full-size slide

  33. {% block config %}
    {% do email.attach('@images/planfaidherbe.jpeg') %}
    {% endblock %}
    {% block subject %}Email Subject{% endblock %}
    {% block text %}
    Optional text representation
    {% endblock %}
    {% block html %}
    Welcome {{ email.toName }}!

    {% endblock %}
    Native integration with Twig

    View full-size slide

  34. {% block text %}
    {% set formula = "2 > 1?" %}
    {% autoescape false %}
    {{ formula }}
    {% endautoescape %}
    {% endblock %}
    {% block html %}
    {% set formula = "2 > 1?" %}
    {{ formula }}
    {% endblock %}
    Native integration with Twig
    HTML escape
    by default with the "name"
    strategy
    From: [email protected]
    To: Fabien
    MIME-Version: 1.0
    Date: Thu, 28 Feb 2019 12:10:16 +0100
    Message-ID: <[email protected]>
    Content-Type: multipart/alternative;
    boundary="_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    =20
    2 > 1?
    =20
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_
    Content-Type: text/html; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    =20
    2 > 1?
    --_=_symfony_1551352216_9df84f01f42af586d65b48578466206f_=_--

    View full-size slide

  35. Tip!
    If the Text part is empty,
    the Renderer automatically generates one

    View full-size slide

  36. But HTML in emails is hard
    Compatibility with email clients
    Inline CSS
    Responsive layout

    View full-size slide

  37. use Twig\CssInliner\CssInlinerExtension;
    $twig->addExtension(new CssInlinerExtension());
    {% filter inline_css %}
    <br/>b { color: red }<br/>

    Welcome {{ email.toName }}!

    {% endfilter %}
    Inlining CSS

    View full-size slide

  38. {% filter inline_css("@css/email.css") %}
    <br/>b { color: red }<br/>

    Welcome {{ email.toName }}!

    {% endfilter %}
    Inlining CSS

    View full-size slide

  39. use Twig\Markdown\MarkdownExtension;
    $twig->addExtension(new MarkdownExtension());

    {% filter markdown %}
    | Version | LTS? | Latest |
    | ------------- |:-------------:| -------:|
    | 1.0 | Yes | 1.0.1 |
    | 2.1 | No | 2.1.33 |
    {% endfilter %}

    Use Markdown to simplify your templates

    View full-size slide

  40. use Twig\Inky\InkyExtension;
    $twig->addExtension(new InkyExtension());
    Use Inky to simplify your HTML
    https://foundation.zurb.com/emails.html

    View full-size slide

  41. {% filter inky|inline_css(source("@zurb/stylesheets/main.css")) %}




    Symfony Connect







    Forgot Your Password?

    It happens. Click the link below to reset it.
    Reset Password

    unsubscribe here.



    {% endfilter %}
    Use Inky to simplify your HTML

    View full-size slide

  42. What about sending

    our emails now?

    View full-size slide

  43. Thank you! ❤

    View full-size slide