Emailing under Windows using R

Using vbs scripting to email from R
R
Author

Harvey

Published

May 10, 2021

Programatically sending an email under Linux is relatively simple. There are several command line clients such as sendmail and mail which are very easy to use. There are also several R packages to help send emails such as {mailr} and {blastula}.
Generally you need access to an SMTP to send messages programatically and this may not be possible in a work setting.
Here’s a simple R function to send an email under Windows. It uses vbs scripting to send an email via the Outlook client itself, without needing server parameters.

#' Send an email with attachments
#'
#' Sends an email to a recipient using vbs scripting.
#' `body` contains the body of the email and `files` contains a list of files
#' to attach.
#'
#' @param to Recipient email address
#' @param subject Subject line
#' @param body Body text
#' @param files List of files to attach
#'
#' @export
lc_send_email <- function(to = NULL, subject = "", body = "", files = list()) {

  if (is.null(to)) return(NULL)

  if (length(files) > 0) {
    v.files <- unlist(sapply(files, function(f) {
      paste0('myAttachments.Add "', normalizePath(f), '", olByValue')
    }))
  } else {
    v.files <- ''
  }

  ## build a vbs script to send an email to user
  v.outlook_commands <- c(
    'Dim olApp',
    'Dim objMailItem',
    'Dim myAttachments',
    'Set olApp = CreateObject("Outlook.Application")',
    'Set objMailItem = olApp.CreateItem(0)',
    'Set myAttachments = objMailItem.Attachments',
    paste0('objMailItem.Subject = "', subject, '"'),
    paste0('objMailItem.To = "', to, '"'),
    paste0('objMailItem.Body = "', body, '"'),
    v.files,
    'objMailItem.Send',
    'Set olApp = Nothing',
    'Set objMailItem = Nothing'
  )

  ## write script to temporary location
  script_file <- tempfile(fileext = '.vbs')
  sink(script_file, append = FALSE)
  cat(v.outlook_commands, sep='\n')
  sink()

  ## execute script
  system_script <- paste0('WScript ', normalizePath(script_file))
  system(system_script)

}