Courri...Builder(3pm)

✨ Courriel::Builder β€” Build emails with sugar ✨

okay bestie, so this is Courriel::Builder, part of the Courriel fam, and it's literally the cutest way to make emails in Perl. no cap. πŸ’Œ


🌸 VERSION 🌸

version 0.49 β€” she's giving stable, she's giving polished, she's giving we been knew. πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

use Courriel::Builder;

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    header( 'X-Generator' => 'MyApp' ),
    plain_body($plain_text),
    html_body(
        $html,
        attach('path/to/image.jpg'),
        attach('path/to/other-image.jpg'),
    ),
    attach('path/to/spreadsheet.xls'),
    attach( content => $file_content ),
);

look at that. gorgeous. no nested hashrefs, no crying. just vibes. 🫢


πŸ’– DESCRIPTION πŸ’–

This module provides some sugar syntax for emails of all shapes and sizes β€” from the most basic plain-text baddie to a full-on multipart situation with plain AND html bodies, inline images living inside your html, etc. like, it scales. it's giving range. πŸ‘‘


πŸŽ€ API πŸŽ€

This module exports all of the following functions by default. Under the hood it uses Sub::Exporter, which means you can lowkey just import the functions under different names if that's your thing. Go peep Sub::Exporter for the deets. ✨


🌈 build_email( ... )

This one returns a brand new Courriel object. You feed it the results of all the other functions you call, and it does the thing.

It expects you to pass in a body of some sort β€” text, html, or both β€” and it will throw an error if you don't. no body, no email, periodt. 😭

It will also add Date and Message-ID headers to your email if you don't provide them yourself, which keeps the email RFC-compliant. she's responsible like that. πŸ’…


🌸 subject($subject)

Sets the subject of the email. It expects a single string. You can pass an empty string, but not undef. don't do it bestie. πŸ™ˆ


πŸ¦‹ from($from)

Sets the From header of the email. Expects a single string, or an object with a format() method β€” like Email::Address::XS. either way, iconic.


πŸ’œ to($from)

Sets the To header of the email. Expects a list of strings and/or objects with a format() method, like Email::Address::XS. yes you can invite multiple people, it's a party. πŸŽ‰


πŸ’Œ cc($from)

Sets the Cc header of the email. Same deal as to() β€” expects a list of strings and/or objects with a format() method, like Email::Address::XS. keeping everyone in the loop, we love to see it.


⭐ header( $name => $value )

Sets a header's value. Call it as many times as you want! And yes, you can call it more than once with the same header name to set multiple values for that header. spam it, it's fine. πŸ”₯


πŸ“ plain_body( ... )

This defines a plain text body for the email. You can call it with a single argument β€” a scalar or a reference to a scalar. That creates a text/plain part based on the content you provide in that argument. By default, the charset for the body is UTF-8 and the encoding is base64. the defaults are already serving. ✨

You can also call this function with a hash of options. It accepts the following options:

  • content β€” The content of the body. This can be a string or scalar reference.
  • charset β€” The charset for the body. This defaults to UTF-8.
  • encoding β€” The encoding for the body. This defaults to base64. Other valid values are quoted-printable, 7bit, and 8bit.
⚠️ It is strongly recommended that you let Courriel handle the transfer encoding for you. like, just let her cook. 🧚

🧚 html_body( ... )

This accepts the same arguments as the plain_body() function. same energy, different mime type. πŸ’…

You can also pass in the results of one or more calls to the attach() function. If you pass in attachments, it creates a multipart/related email part, which lets you refer to images by the Content-ID using the cid: URL scheme. cute AND functional. πŸŽ€


πŸ‘‘ attach( ... )

This function creates an attachment for the email. In the simplest form, you pass it a single argument, which should be a path to a file on disk. That file gets attached to the email. easy. 🌟

You can also pass a hash of options. The valid keys are:

  • file β€” The file to attach to the email. You can also pass the content explicitly.
  • content β€” The content of the attachment. This can be a string or scalar reference.
  • filename β€” You can set the filename that will be used in the attachment's Content-Disposition header. If you pass a file parameter, that will be used when this isn't provided. If you pass a content parameter, then there will be no filename set for the attachment unless you pass a filename parameter as well. so like, name your child or the child shall remain nameless. 😭
  • mime_type β€” You can explicitly set the mime type for the attachment. If you don't, this function will use File::LibMagic to try to figure out the mime type for the attachment. she'll guess. usually correctly. πŸ’…
  • content_id β€” This will set the Content-ID header for the attachment. If you're creating an HTML body with cid: scheme URLs, you'll need to set this for each attachment that the HTML body refers to.

The id will be wrapped in angle brackets (<id-goes-here>) when set as a header. noted. ✨


🍰 COOKBOOK 🍰

Some examples of how to build different types of emails. a little recipe book, just for you.


🌈 Simple Email With Plain Text Body

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    plain_body($plain_text),
);

This creates an email with a single text/plain part. minimalist. chic. no notes. 🫢


🌸 Simple Email With HTML Body

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    html_body($html_text),
);

This creates an email with a single text/html part. fancy but low effort, the dream combo. ✨


πŸ’œ Email With Both Plain and HTML Bodies

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    plain_body($plain_text),
    html_body($html_text),
);

This creates an email with this structure:

multipart/alternative
  |
  |-- text/plain (disposition = inline)
  |-- text/html  (disposition = inline)

both bodies, best of both worlds, the multiverse is thriving. 🌌


πŸŽ€ Email With Both Plain and HTML Bodies and Inline Images

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    plain_body($plain_text),
    html_body(
        $html_text,
        attach(
            file       => 'path/to/image1.jpg',
            content_id => 'image1',
        ),
        attach(
            file       => 'path/to/image2.jpg',
            content_id => 'image2',
        ),
    ),
);

This creates an email with this structure:

multipart/alternative
  |
  |-- text/plain (disposition = inline)
  |-- multipart/related
        |
        |-- text/html  (disposition = inline)
        |-- image/jpeg (disposition = attachment, Content-ID = image1)
        |-- image/jpeg (disposition = attachment, Content-ID = image2)

the images are inside the html, which is inside the related part. nesting dolls but make it email. πŸͺ†


⭐ Email With Both Plain and HTML Bodies and Attachments

my $email = build_email(
    subject('An email for you'),
    from('joe@example.com'),
    to( 'jane@example.com', 'alice@example.com' ),
    plain_body($plain_text),
    html_body(
        $html_text,
    ),
    attach('path/to/spreadsheet.xls'),
    attach( content => \$png_image_content ),
);

This creates an email with this structure:

multipart/mixed
  |
  |-- multipart/alternative
  |     |
  |     |-- text/plain (disposition = inline)
  |     |-- text/html  (disposition = inline)
  |
  |-- application/vnd.ms-excel (disposition = attachment)
  |-- image/png                (disposition = attachment)

look at that hierarchy. immaculate. she ate and left no crumbs. πŸ‘‘


🫢 SUPPORT 🫢

Bugs may be submitted at <https://github.com/houseabsolute/Courriel/issues>.

I am also usually active on IRC as autarch on irc://irc.perl.org. come say hi, fr fr. πŸ’¬


🧚 SOURCE 🧚

The source code repository for Courriel can be found at <https://github.com/houseabsolute/Courriel>. go lurk, it's fine.


πŸ‘‘ AUTHOR πŸ‘‘

Dave Rolsky <autarch@urth.org> β€” the icon behind the icon. 🫑


This software is Copyright (c) 2021 by Dave Rolsky.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)

The full text of the license can be found in the LICENSE file included with this distribution.


and that's the whole page bestie!! πŸ’– this was rendered with perl v5.32.1 on 2021-08-22, and the page itself is Courri...Builder(3pm) β€” mwah, no notes, go build some emails. πŸ’…βœ¨πŸŽ€πŸ¦‹πŸŒΈπŸ«Ά