emayili

CRAN status GitHub Actions build status Codecov test coverage Lifecycle: experimental

{emayili} is a package for sending emails from R. The design goals are:

The package name is an adaption of the Zulu word for email, imeyili.

The documentation for {emayili} can be found here.

Installation

Get the stable version from CRAN.

install.packages("emayili")

Or grab it directly from GitHub.

# Install from the master branch.
remotes::install_github("datawookie/emayili")
# Install from the development branch.
remotes::install_github("datawookie/emayili", ref = "dev")

Usage

First create a message object.

library(emayili)
library(magrittr)

email <- envelope()

Creating a Message

The message has class envelope.

class(email)
[1] "envelope"

Add addresses for the sender and recipient.

email <- email %>%
  from("alice@yahoo.com") %>%
  to("bob@google.com") %>%
  cc("craig@google.com")

There are also bcc() and reply() functions for setting the Bcc and Reply-To fields.

Add a subject.

email <- email %>% subject("This is a plain text message!")

Add a text body. You can use html() to add an HTML body.

email <- email %>% text("Hello!")

Add an attachment.

email <- email %>% attachment("image.jpg")

You can also create the message in a single command:

email <- envelope(
  to = "bob@google.com",
  from = "alice@yahoo.com",
  subject = "This is a plain text message!",
  text = "Hello!"
)

Simply printing a message displays the header information.

email
Date:                      Wed, 15 Sep 2021 07:07:25 GMT
From:                      alice@yahoo.com
To:                        bob@google.com
Cc:                        craig@google.com
Subject:                   This is a plain text message!
X-Mailer:                  {emayili}-0.4.20

You can identify emails which have been sent using {emayili} by the presence of an X-Mailer header which includes both the package name and version.

If you want to see the complete MIME object, just convert to a string.

You can also call the print() method and specify details = TRUE.

You can set the envelope_details option to assert that the details should always be printed.

# Always print envelope details.
#
options(envelope_details = TRUE)

By default the results returned by most of the methods are invisible. You can make them visible via the envelope_invisible (default: TRUE).

# Always show envelope.
#
options(envelope_invisible = FALSE)

Interpolating Text

You can use {glue} syntax to interpolate content into the body of a message.

name = "Alice"

envelope() %>%
  text("Hello {name}!")
Date:                      Wed, 15 Sep 2021 07:07:25 GMT
X-Mailer:                  {emayili}-0.4.20
MIME-Version:              1.0
Content-Type:              text/plain; charset=utf-8
Content-Disposition:       inline
Content-Transfer-Encoding: 7bit

Hello {name}!

Rendering Markdown

You can render Markdown straight into a message.

Use either plain Markdown.

envelope() %>%
  # Render plain Markdown from a character vector.
  render(
    "Check out `{emayili}` on [CRAN](https://cran.r-project.org/package=emayili).",
    plain = TRUE
  )
Date:                      Wed, 15 Sep 2021 07:07:25 GMT
X-Mailer:                  {emayili}-0.4.20
MIME-Version:              1.0
Content-Type:              text/html; charset=utf-8
Content-Disposition:       inline

<p>Check out <code>{emayili}</code> on <a href="https://cran.r-project.org/package=emayili">CRAN</a>.</p>

Or R Markdown.

envelope() %>%
  # Render R Markdown from a file.
  render("message.Rmd")

In both cases the function will accept either a file path or a character vector containing Markdown text.

🚨 Note: Inline images embedded in the rendered HTML will not appear in the GMail (and potentially other) web client.

Adding an Inline Image

Adding an inline image to an HTML message is possible. There are two ways to achieve this.

1. Base64 Encoding

First you’ll need to Base64 encode the image.

img_base64 <- base64enc::base64encode("image.jpg")

Then create the HTML message body.

html_body <- sprintf('<html><body><img src="data:image/jpeg;base64,%s"></body></html>', img_base64)

And finally add it to the email.

email <- envelope() %>% html(html_body)

Note: It’s important that you specify the appropriate media type (image/jpeg for JPEG and image/png for PNG).

2. Using a CID

Unfortunately some mail clients (like Gmail) will not display Base64 encoded images. In this case using a CID is a working alternative.

First create the message body which references an image by CID.

html_body <- '<html><body><img src="cid:image"></body></html>'

Then attach the image and specify the cid argument.

email <- envelope() %>%
  html(html_body) %>%
  attachment(path = "image.jpg", cid = "image")

Sending a Message

Create a SMTP server object and send the message.

smtp <- server(host = "smtp.gmail.com",
               port = 465,
               username = "bob@gmail.com",
               password = "bd40ef6d4a9413de9c1318a65cbae5d7")
smtp(email, verbose = TRUE)

To see the guts of the message as passed to the SMTP server:

print(email, details = TRUE)

Using STARTTLS

If you’re trying to send email with a host that uses the STARTTLS security protocol (like Google Mail, Yahoo! or AOL), then it will most probably be blocked due to insufficient security. In order to circumvent this, you can grant access to less secure apps. See the links below for specifics:

Standards Documents

The following (draft) standards documents relate to emails:

Similar Packages

There is a selection of other R packages which also send emails:

Developer Notes

Code Coverage

You can find the test coverage report at Codecov. For developmnent purposes it’s more convenient to use the {covr} package.

Generate a coverage report.

library(covr)

report()

Calculate test coverage.

coverage <- package_coverage()

Coverage statistics as a data frame.

as.data.frame(coverage)

Show lines without coverage.

zero_coverage(coverage)