{"id":14069134,"url":"https://github.com/datawookie/emayili","last_synced_at":"2025-05-15T13:05:15.620Z","repository":{"id":35599324,"uuid":"187310940","full_name":"datawookie/emayili","owner":"datawookie","description":"An R package for sending email messages.","archived":false,"fork":false,"pushed_at":"2025-05-05T18:29:25.000Z","size":4687,"stargazers_count":183,"open_issues_count":7,"forks_count":26,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-05T19:48:44.671Z","etag":null,"topics":["hacktoberfest","r","rstats"],"latest_commit_sha":null,"homepage":"https://datawookie.github.io/emayili/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datawookie.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-05-18T03:45:55.000Z","updated_at":"2025-05-01T21:55:57.000Z","dependencies_parsed_at":"2024-04-23T12:16:47.679Z","dependency_job_id":"04e903a6-b2f5-499d-bf96-0d51435558a8","html_url":"https://github.com/datawookie/emayili","commit_stats":{"total_commits":753,"total_committers":25,"mean_commits":30.12,"dds":"0.37317397078353254","last_synced_commit":"5e4781b043697a7997dce89a04a4b706ea021c3c"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datawookie%2Femayili","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datawookie%2Femayili/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datawookie%2Femayili/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datawookie%2Femayili/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datawookie","download_url":"https://codeload.github.com/datawookie/emayili/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254346624,"owners_count":22055808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","r","rstats"],"created_at":"2024-08-13T07:06:38.429Z","updated_at":"2025-05-15T13:05:15.600Z","avatar_url":"https://github.com/datawookie.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r setup, include=FALSE}\nknitr::opts_chunk$set(comment = NA)\n```\n\n# emayili \u003cimg src=\"man/figures/emayili-hex.png\" align=\"right\" alt=\"\" width=\"120\" /\u003e\n\n\u003c!-- badges: start --\u003e\n[![CRAN status](https://www.r-pkg.org/badges/version/emayili)](https://cran.r-project.org/package=emayili)\n![GitHub Actions build status](https://github.com/datawookie/emayili/actions/workflows/build.yaml/badge.svg)\n[![Codecov test coverage](https://img.shields.io/codecov/c/github/datawookie/emayili.svg)](https://app.codecov.io/gh/datawookie/emayili)\n[![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-green.svg)](https://lifecycle.r-lib.org/articles/stages.html)\n\u003c!-- badges: end --\u003e\n\n`{emayili}` is a package for sending emails from R. The design goals are:\n\n- works on all manner of SMTP servers and\n- has minimal dependencies (or dependencies which are easily satisfied).\n\nThe package name is an adaption of the Zulu word for email, _imeyili_.\n\nThe documentation for `{emayili}` can be found [here](https://datawookie.github.io/emayili/).\n\nNot that I pretend to have many stars on this project, but these plots are quite fun.\n\n[![Star History Chart](https://api.star-history.com/svg?repos=datawookie/emayili\u0026type=Date)](https://star-history.com/#datawookie/emayili\u0026Date)\n\n## Installation\n\nGet the stable version from [CRAN](https://CRAN.R-project.org/package=emayili).\n\n```{r eval=FALSE}\ninstall.packages(\"emayili\")\n```\n\nOr grab it directly from [GitHub](https://github.com/datawookie/emayili).\n\n```{r eval=FALSE}\n# Install from the master branch.\nremotes::install_github(\"datawookie/emayili\")\n# Install from the development branch.\nremotes::install_github(\"datawookie/emayili\", ref = \"dev\")\n```\n\n## Usage\n\nLoad the library.\n\n```{r message=FALSE}\nlibrary(emayili)\n\npackageVersion(\"emayili\")\n```\n\nCreate a message object.\n\n```{r}\nemail \u003c- envelope()\n```\n\n### Creating a Message\n\nThe message has class `envelope`.\n\n```{r}\nclass(email)\n```\n\nAdd addresses for the sender and recipient.\n\n```{r}\nemail \u003c- email %\u003e%\n  from(\"alice@yahoo.com\") %\u003e%\n  to(\"bob@google.com\") %\u003e%\n  cc(\"craig@google.com\")\n```\n\nThere are also `bcc()` and `reply()` functions for setting the `Bcc` and `Reply-To` fields.\n\nYou can supply multiple addresses in a variety of formats:\n\n- as a single comma-separated string\n- as separate strings; or\n- as a vector of strings.\n\n```{r multiple-addresses, eval = FALSE}\nenvelope() %\u003e% to(\"bob@google.com, craig@google.com, erin@gmail.com\")\nenvelope() %\u003e% to(\"bob@google.com\", \"craig@google.com\", \"erin@gmail.com\")\nenvelope() %\u003e% to(c(\"bob@google.com\", \"craig@google.com\", \"erin@gmail.com\"))\n```\n\nAdd a subject.\n\n```{r}\nemail \u003c- email %\u003e% subject(\"This is a plain text message!\")\n```\n\nAdd a text body.\n\n```{r eval=FALSE}\nemail \u003c- email %\u003e% text(\"Hello!\")\n```\n\nYou can use `html()` to add an HTML body. It accepts either a vector of characters or a `tagList()` from `{htmltools}`.\n\n```{r eval=FALSE}\nlibrary(htmltools)\n\nemail \u003c- email %\u003e% html(\n  tagList(\n    h2(\"Hello\"),\n    p(\"World!\")\n  )\n)\n```\n\nAdd an attachment.\n\n```{r eval=FALSE}\nemail \u003c- email %\u003e% attachment(\"image.jpg\")\n```\n\nYou can also create the message in a single command:\n\n```{r eval=FALSE}\nemail \u003c- envelope(\n  to = \"bob@google.com\",\n  from = \"alice@yahoo.com\",\n  subject = \"This is a plain text message!\",\n  text = \"Hello!\"\n)\n```\n\nSimply printing a message displays the header information.\n\n```{r}\nemail\n```\n\nYou 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.\n\nIf you want to see the complete MIME object, just convert to a string.\n\n```{r include = FALSE}\nas.character(email)\n```\n\nYou can also call the `print()` method and specify `details = TRUE`.\n\n```{r include = FALSE}\nprint(email, details = TRUE)\n```\n\n### Options\n\nYou can set the `envelope.details` option to assert that the details should always be printed.\n\n```{r}\n# Always print envelope details.\n#\noptions(envelope.details = TRUE)\n```\n\nBy default the results returned by most of the methods are invisible. You can make them visible via the `envelope.invisible` (default: `TRUE`).\n\n```{r}\n# Always show envelope.\n#\noptions(envelope.invisible = FALSE)\n```\n\n### Interpolating Text\n\nYou can use `{glue}` syntax to interpolate content into the body of a message.\n\n```{r}\nname \u003c- \"Alice\"\n\nenvelope() %\u003e%\n  text(\"Hello {{name}}!\")\n```\n\n### Rendering Markdown\n\nYou can render Markdown straight into a message.\n\nUse either plain Markdown.\n\n```{r}\nenvelope() %\u003e%\n  # Render plain Markdown from a character vector.\n  render(\n    \"Check out [`{emayili}`](https://cran.r-project.org/package=emayili).\"\n  )\n```\n\nOr R Markdown.\n\n```{r eval = FALSE}\nenvelope() %\u003e%\n  # Render R Markdown from a file.\n  render(\"message.Rmd\")\n```\n\nIn both cases the function will accept either a file path or a character vector containing Markdown text.\n\n\u003cimg src=\"man/figures/screenshot-email-rendered.png\" style=\"filter: drop-shadow(5px 5px 5px black); margin-bottom: 5px;\"\u003e\n\nInterpolation also works with `render()`.\n\n### Rendered CSS\n\nWhen you render an R Markdown document the resulting HTML includes CSS from three sources:\n\n- [Bootstrap](https://getbootstrap.com/)\n- [highlightjs](https://highlightjs.org/) and\n- `{rmarkdown}`.\n\nYou can control which of these propagate to the message using the `include_css` parameter which, by default, is set to `c(\"rmd\", \"bootstrap\", \"highlight\")`.\n\n🚨 _Note:_ Gmail doesn't like the Bootstrap CSS. If you want your styling to work on Gmail you should set `include_css =  c(\"rmd\", \"highlight\")`.\n\n### Extra CSS\n\nYou can insert extra CSS into your rendered messages.\n\n```{r eval = FALSE}\nenvelope() %\u003e%\n  render(\"message.Rmd\", css_files = \"extra.css\")\n```\n\nIf you are having trouble getting this to work with Gmail then it might be worthwhile taking a look at their [CSS support](https://developers.google.com/gmail/design/css).\n\n### Adding an Inline Image\n\nAdding an inline image to an HTML message is possible. There are two ways to achieve this.\n\n_1. Base64 Encoding_\n\nFirst you'll need to [Base64 encode](https://en.wikipedia.org/wiki/Base64) the image.\n\n```{r eval=FALSE}\nimg_base64 \u003c- base64enc::base64encode(\"image.jpg\")\n```\n\nThen create the HTML message body.\n\n```{r eval=FALSE}\nhtml_body \u003c- sprintf('\u003chtml\u003e\u003cbody\u003e\u003cimg src=\"data:image/jpeg;base64,%s\"\u003e\u003c/body\u003e\u003c/html\u003e', img_base64)\n```\n\nAnd finally add it to the email.\n\n```{r eval=FALSE}\nemail \u003c- envelope() %\u003e% html(html_body)\n```\n\n_Note:_ It's important that you specify the appropriate media type (`image/jpeg` for JPEG and `image/png` for PNG).\n\n_2. Using a CID_\n\nUnfortunately some mail clients (like Gmail) will not display Base64 encoded images. In this case using a CID is a working alternative.\n\nFirst create the message body which references an image by CID.\n\n```{r eval=FALSE}\nhtml_body \u003c- '\u003chtml\u003e\u003cbody\u003e\u003cimg src=\"cid:image\"\u003e\u003c/body\u003e\u003c/html\u003e'\n```\n\nThen attach the image and specify the `cid` argument.\n\n```{r eval=FALSE}\nemail \u003c- envelope() %\u003e%\n  html(html_body) %\u003e%\n  attachment(path = \"image.jpg\", cid = \"image\")\n```\n\n### Create a Server Object\n\nCreate a SMTP server object.\n\n```{r eval=FALSE}\nsmtp \u003c- server(\n  host = \"smtp.gmail.com\",\n  port = 465,\n  username = \"bob@gmail.com\",\n  password = \"bd40ef6d4a9413de9c1318a65cbae5d7\"\n)\n```\n\nIt's bad practice to include credentials in a script. A better approach would be to keep the credentials in your `.Renviron` file.\n\n```\nGMAIL_USERNAME=\"bob@gmail.com\"\nGMAIL_PASSWORD=\"bd40ef6d4a9413de9c1318a65cbae5d7\"\n```\n\nYou can then pull these variables into R using `Sys.getenv()` and then create the server object.\n\n```{r eval=FALSE}\nsmtp \u003c- server(\n  host = \"smtp.gmail.com\",\n  port = 465,\n  username = Sys.getenv(\"GMAIL_USERNAME\"),\n  password = Sys.getenv(\"GMAIL_PASSWORD\")\n)\n```\n\nIf you're trying to send email with a host that uses the STARTTLS security protocol (like Gmail, 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:\n\n* [Gmail](https://myaccount.google.com/security)\n* [Yahoo!](https://login.yahoo.com/account/security) and\n* [AOL](https://login.aol.com/account/security).\n\nGmail has recently changed their authentication procedure. If you are having trouble connecting to the Gmail SMTP server then take a look at [this](https://datawookie.dev/blog/2022/03/updated-gmail-authentication/).\n\n### Sending a Message\n\nSend the message.\n\n```{r eval=FALSE}\nsmtp(email, verbose = TRUE)\n```\n\nTo see the guts of the message as passed to the SMTP server:\n\n```{r eval=FALSE}\nprint(email, details = TRUE)\n```\n\n### Encryption\n\nBoth transport-level encryption and end-to-end [email encryption](https://en.wikipedia.org/wiki/Email_encryption) are supported. An SMTP connection can be initiated on port 465 (SMTPS, see [RFC 8314](https://www.rfc-editor.org/rfc/rfc8314)) or 587 (SMTP-MSA, see [RFC 6409](https://www.rfc-editor.org/rfc/rfc6409)), enabling transport-level encryption. Public-key cryptography (via GnuPG) can be used to sign and/or encrypt message contents for end-to-end encryption.\n\n## Standards Documents\n\nThe following (draft) standards documents relate to emails:\n\n- [RFC 2822](https://www.rfc-editor.org/rfc/rfc2822) — Internet Message Format\n- [RFC 5321](https://www.rfc-editor.org/rfc/rfc5321) — Simple Mail Transfer Protocol\n- [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322) — Internet Message Format\n- [RFC 6854](https://www.rfc-editor.org/rfc/rfc6854) — an update to RFC 5322.\n\n## Similar Packages\n\nThere is a selection of other R packages which also send emails:\n\n- [blastula](https://cran.r-project.org/package=blastula)\n- [blatr](https://cran.r-project.org/package=blatr) (Windows)\n- [gmailr](https://cran.r-project.org/package=gmailr)\n- [mail](https://cran.r-project.org/package=mail)\n- [mailR](https://cran.r-project.org/package=mailR)\n- [sendmailR](https://cran.r-project.org/package=sendmailR)\n- [ponyexpress](https://github.com/ropensci-archive/ponyexpress)\n\n## Blog Posts\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/10/emayili-support-for-gmail-sendgrid-mailgun/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/10/emayili-support-for-gmail-sendgrid-mailgun/\"\u003eSupport for Gmail, SendGrid \u0026 Mailgun\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/10/emayili-message-precedence/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/10/emayili-message-precedence/\"\u003eMessage Precedence\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/10/emayili-message-integrity/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/10/emayili-message-integrity/\"\u003eMessage Integrity\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-right-to-left/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-right-to-left/\"\u003eRight-to-Left\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-styling-figures/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-styling-figures/\"\u003eStyling Figures\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-managing-css/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-managing-css/\"\u003eManaging CSS\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-r-markdown-parameters/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-r-markdown-parameters/\"\u003eR Markdown Parameters\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-rendering-r-markdown/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-rendering-r-markdown/\"\u003eRendering R Markdown\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-rendering-plain-markdown/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-rendering-plain-markdown\"\u003eRendering Plain Markdown\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/09/emayili-interpolating-message-content/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/09/emayili-interpolating-message-content\"\u003eInterpolating Message Content\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2021/08/emayili-rudimentary-email-address-validation/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2021/08/emayili-rudimentary-email-address-validation\"\u003eRudimentary Email Address Validation\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://datawookie.dev/blog/2022/03/updated-gmail-authentication/featured.jpg\" width=\"100px\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://datawookie.dev/blog/2022/03/updated-gmail-authentication/\"\u003eUpdated Gmail Authentication\u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Developer Notes\n\n### Code Coverage\n\nYou can find the test coverage report at [Codecov](https://app.codecov.io/gh/datawookie/emayili). For development purposes it's more convenient to use the [`{covr}`](https://cran.r-project.org/package=covr) package.\n\nGenerate a coverage report.\n\n```{r eval = FALSE}\nlibrary(covr)\n\n# Tests that are skipped on CRAN should still be included in coverage report.\n#\nSys.setenv(NOT_CRAN = \"true\")\n\nreport()\n```\n\nCalculate test coverage.\n\n```{r eval = FALSE}\ncoverage \u003c- package_coverage()\n```\n\nCoverage statistics as a data frame.\n\n```{r eval = FALSE}\nas.data.frame(coverage)\n```\n\nShow lines without coverage.\n\n```{r eval = FALSE}\nzero_coverage(coverage)\n```\n\n### Checks\n\nCheck spelling.\n\n```{r eval = FALSE}\nspelling::spell_check_package()\n```\n\nQuick local checks.\n\n```{r eval = FALSE}\ndevtools::check()\n```\n\nRemote checks (take longer but more thorough).\n\n```{r eval = FALSE}\ndevtools::check_win_devel()\n\n# Check for a specific platform.\n#\nrhub::check(platform = \"debian-gcc-devel\")\nrhub::check_on_windows(check_args = \"--force-multiarch\")\nrhub::check_on_solaris()\n\n# Check on a bunch of platforms.\n#\nrhub::check_for_cran()\n\n# Check on important platforms.\n#\nrhub::check_for_cran(platforms = c(\n  \"debian-gcc-release\",\n  \"ubuntu-gcc-release\",\n  \"macos-m1-bigsur-release\",\n  \"windows-x86_64-release\",\n  NULL\n))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatawookie%2Femayili","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatawookie%2Femayili","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatawookie%2Femayili/lists"}