#  /Users/rsaporta/git/misc/rscripts/utils/notify/email_using_mailR.r

### TODO:  if emailing several pepole with no 'name change' send them out as one unit


quickEmailS3 <- function(TODO="NOT YET IMPLEMENTED --- use s3_upload_and_share()  [2015-12-01]") {
     stop("Not yet implemented -- what about s3_upload_and_share() ? ")


     ## TODO
     
       ## WORKFLOW
       ## Given some files recently uploaded
       files.s3 <- c("s3://dev-rsaporta/justForYou/TESTING/Vodafone_activity.csv", "s3://dev-rsaporta/justForYou/TESTING/Vodafone_breakage.csv", "s3://dev-rsaporta/justForYou/TESTING/Vodafone_revenue.csv", "s3://dev-rsaporta/justForYou/TESTING/spotify_fact_analytics_count.tsv", "s3://dev-rsaporta/justForYou/TESTING/spotify_raw_row_counts.tsv", "s3://dev-rsaporta/justForYou/TESTING/spotify_raw_row_counts_by_day.tsv")
       ## Sign them
       ret <- s3_sign(files.s3)
       ## Convert to short_url
       shorts <- url_shorten(ret)


}
quickEmail <- function(..., files=NULL, from=c("Rick", "SAM", "sam", "rick"), cc=NULL, bcc=getRS("bcc")
                     , subject="[no subject]"
                     , body=msg, msg="", file=files
                     # , limit.on.attachment.size=limit, limit="19.5 MB"
                     # , s3=fileSize(file) > as.numeric.bytes(limit.on.attachment.size)
                     , info="your _____ file"
                     , verbose=TRUE) {
## info :: describes the file(s);  used only in the subject of the email. 

     ## Clean up 
     if (missing(subject) || identical(subject, "[no subject]")) {
          if (missing(info))
               info <- ""
          else 
               info %<>% trim %>% paste0(., " ")
          subject <- {ifelse(is.null(file), "From the Data Science team", sprintf("Your %sfile%s from the Data Science team", info, ifelse(length(file)>1, "s", "")))}
     }

     Args <- collectArgs(incl.dots=FALSE, except=c("from", "file", "files", "msg", "info"))
     dots <- list(...)

     if ("attachments" %in% names(dots)) {
          if (!is.null(file))
               stop ("cannot use both 'file' and 'attachments' -- please choose one")
          file <- attachments
          dots <- dots[names(dots) != "attachments"]
     }

     if ("to" %in% names(dots)) {
          warning("when using quickEmail() do not specify 'to=..'\nInstead simply pass the receipients as freestanding parameters -- eg:\n    quickEmail(Jane='jane@gmail.com', 'jane smith'='jane.smith@gmail.com', file='dfdfd', ..)", call.=FALSE)
          ## move the elements in 'to' a level, right in to dots
          dots <- c(dots[names(dots) != "to"], dots[["to"]])
     }

     ## Filter out pass-through arguments to email()
     if (!is.null(names(dots))) {
          wh.areArgs <- names(dots) %in% names(formals(email))
          Args <- c(Args, dots[wh.areArgs])
          dots <- dots[!wh.areArgs]          
     }

     if (!length(dots) && "to" %ni% names(Args)) {
          if (!is.null(cc)) {
               warning("'to' cannot be NULL/Blank.  Using 'cc' as 'to'")
               to <- cc
               cc <- NULL
          }
          stop ("\n\nNo 'to' argument given or implied\nHINT:  use quickEmail(\"name\", \"address@domain.com\", \'path/to/file\"")
     }

     ## Confirm everything else is a string
     wh.notStrings <- !sapply(dots, is.character)
     if (any(wh.notStrings))
          stop("Do not know how to deal with non-string arguments to '...'  Namely:\n", pasteC(capture.output(dots[wh.notStrings]), C="\n"))
     dots <- unlist(dots)

     ## look for additional files in the dots
     wh.areFiles <- grepl(regOr(c("^~", path.expand("~"), "/git", "((^|/)out/)", sprintf("\\.%s$", c("txt", "pdf", "xls", "xlsx", "csv", "tsv")))), dots)

     if (any(wh.areFiles)) {
          file <- c(file, dots[wh.areFiles])
          dots <- dots[!wh.areFiles]
     }

     ## Allow for quickEmail(name, address, file)
     if (length(dots) == 2 && sum(wh.addr <- grepl("@", dots)) == 1)
               dots <- setNames(nm=dots[!wh.addr], obj=dots[wh.addr])

     ## Otherwise, treat all of dots as "to"
     to <- formatEmailAddresses(dots)

     if (!grepl("@", from[[1]])) {
          from <- match.arg(from)
          from <- ifelse (tolower(from) == "rick", c("Rick's Computer <rsaporta@theorchard.com>"), "The S.A.M. <thesam@email.theorchard.com>")
     }

     Args <- c(as.list(Args), to=list(to), from=list(from), attachments=list(file))

     do.call(email, Args)
}

## EXAMPLES
if (FALSE) {
     quickEmail("rick", "rsaporta@gmail.com", .f.out.writeDT)
     quickEmail("rick", "rsaporta@gmail.com", f.out)
     quickEmail(f.out,  rick="rsaporta@gmail.com", me="rsaporta+me@gmail.com", from="rick", signature.by.name="rick", file=f.out)
     quickEmail("rick"="rsaporta@gmail.com", me="rsaporta+me@gmail.com", from="rick", signature.by.name="rick", file=f.out, body="Hello\nTesting %info% World")
}

email <- function(to, subject, body=msg, from="The S.A.M. <thesam@email.theorchard.com>"
     , msg=""
     , bcc=getRS("bcc")
     , cc=NULL
     , signature.by.name=sig, sig=c("SAM") ## sig is a synonym for signature.by.name
     , smtp.settings=getDefaultSMTPsettings()
     , attachments=c()
     , limit.on.attachment.size="19.5 MB"
     , html=TRUE
     , fail.if.cannot.attach=TRUE
     , dont.insert.names=FALSE
     , default.name.to.insert.if.to.is.blank=""
     , use.single.name.instead = FALSE  ## Options: TRUE or "Folks" or "All" etc (some generic gretting). TRUE will take names and comma separate them
     , allow.cc.when.using.name=FALSE
     , zArchive.whenDone.info=!{exists("TEST_RUN") && isTRUE(TEST_RUN)}
     , fail_on_package_load_error = FALSE
     , verbose=TRUE
     ) {
## msg : a synonym for body
## sig : a synonym for signature.by.name

     if (!require(mailR, quietly=TRUE)) {
          err_msg <- "could not load package mailR -- cannot send emails from R"
          if (fail_on_package_load_error)
               stop(err_msg)
          ## else 
          warning(err_msg, "\n Exiting email() without sending email")
          return(FALSE)
     }

     ## Take a backup
     body.orig <- body


     #### ------------------------   REPLACE PLACEHOLDERS ------------------------ ####
     ## Knows %fname%, %name% -- not yet %lname%
     known_placeholders <- c("%name%", "%fname%")  # "%lname%"

      ## If there is NOT at least one of the placeholders detected in body, 
      ## then (1) no need to insert (since this will split into individual emails)
      ##  and (2) allow cc when using name  (since no name being used)
      if (!any(sapply(known_placeholders, grepl, body))) {
          dont.insert.names <- TRUE
          allow.cc.when.using.name <- TRUE
     }

     ## Only modify body if flagged to allow
     if (!dont.insert.names) {
          nms <- c(extractNameFromEmail(to))
          fnames <- sapply(strsplit(nms, " "), function(x) ifelse(length(x), x[[1]], ""))

          ## TWO OPTIONS.  (1) Individual emails, each with their own single name. 
          ##               (2) A combined email, with a salution like "All," or "Rick, Josh, Gale, "
          if (isTRUE(use.single.name.instead)) {
               ## Check for blanks, of which there should be none
               if (any(fnames == "")) {
                    warning ("\nWhen use.single.name.instead is TRUE, email() combines all first names into a comma separated list -- eg,  \"Rick, Gail, John,\"\nHowever, one of 'to' names is blank.\nThus defaulting to \"All,\"")
                    use.single.name.instead <- "All"
               } else {
                    ## Collapse all names, but remove myself                    
                    use.single.name.instead <- pasteC(fnames[!grepl("rsaporta", to)], C=", ", sep="")
               }
          }
          if (is.character(use.single.name.instead)) {
               ## There should be *exactly* one placeholder to replace
               if (sum(unlist(sapply(known_placeholders, gregexpr, body)) != -1) > 1)
                    stop ("Selected to use.single.name.instead however, there is more than one placeholder to replace (and that would look weird)")
               ## Not sure which placeholder is used, so just loop over them. 
               for (placebolder in known_placeholders)
                    body <- gsub(placebolder, use.single.name.instead, body)
          } else {
               ## Iterate over body twice. Note that R-recycling rules allows this to work smoothly. 
               body <- mapply(gsub, repl=ifelse(fnames == "", default.name.to.insert.if.to.is.blank, fnames), x=body, MoreArgs=list(pattern="%fname%"))
               body <- mapply(gsub, repl=ifelse(nms == "",    default.name.to.insert.if.to.is.blank, nms),    x=body, MoreArgs=list(pattern="%name%"))               
          }
     }
     #### ------------------------   END: REPLACE PLACEHOLDERS ------------------------ ####



     body <- insertInfoToBody(body, zArchive.whenDone.info=zArchive.whenDone.info)

     if (!is.null(signature.by.name))
          body <- appendSignature(body=body, name=signature.by.name)

     ## Check that all files exist and can be accessed
     if (!is.null(attachments) && length(attachments)) {
          attachments <- unique(attachments)
          exist  <- file.exists(attachments)
          access <- file.access(attachments, 4) == 0  # file.access returns 0 if CAN access, returns -1 if canNOT access
          if (!all(exist & access)) {
               msg.ex <- if (any(!exist)) pasteC(c("The following file(s) do not exist:", sprintf("  '%s'", attachments[!exist])), C="\n\t")
               msg.ac <- if (any(exist & !access)) pasteC(c("The following file(s) exist but cannot be accessed:", sprintf("  '%s'", attachments[exist & !access])), C="\n\t")
               msg <- pasteC("\n", c(msg.ex, msg.ac), C="In addition, ")
               if (fail.if.cannot.attach)
                    stop (msg)
               warning(msg)
               attachments <- attachments[exist & access]
          }
          ## Check for NAs
          if (any(is.na(attachments)))
               warning("'attchments' contains NA values. This could be a sign of an error.")
          attachments <- attachments[!is.na(attachments)]

          ## Check for emptyness
          if (!length(attachments)) {
               attachments <- NULL
          } else {
               ## Check file size 
               limit <- valueIfErr(as.numeric.bytes(limit.on.attachment.size, showWarnings=FALSE), 1e7)
               limit <- ifelse(is.na(limit), 1e7, limit)

               file_sizes <- file.info(attachments)$size
               wh.too_large <- file_sizes > limit

               if (any(wh.too_large)) {
                    stop(warningCols("Some file attachments are too large to email. Consider using quickEmailS3()\nOffending file(s): ", attachments[wh.too_large], cols=1), call.=FALSE)
               }
          }
     }

     ## Format each of to, cc, bcc
     to  <- formatEmailAddresses(to)
     cc  <- formatEmailAddresses(cc)
     bcc <- formatEmailAddresses(bcc)

     ## Confrim that all addresses are email addresses
     for (addr.arg in c("to", "cc", "bcc")) {
          tmp.adr <- get(addr.arg)
          if (any(wh.nonadr <- !grepl("@", tmp.adr)))
               warning ("'", addr.arg, "' appears to contain ", sum(wh.nonadr), " non-email address(es):  ", pasteQ(tmp.adr[wh.nonadr], w=""))
     }

     if (length(subject) > 1)
          stop ("'subject' must have length 1")


     if (verbose) {
          w <- 12 + getWidth(max=max(53, 4+mnchar(c(commaSep(to), commaSep(cc), commaSep(cc), attachments))))
          sfmt <- "\nSending the following email\n %s\n   TO   : %s\n   CC   : %s\n   BCC  : %s\n   SUBJ : %s\n   \n   %s\n %1$s\n  Files : %s\n %1$s\n%s\n %1$s\n  "
          # cat(do.call(sprintf, c(list(fmt=sfmt, pasteR(w)),  lapply(list(to, cc, bcc, subject, gsub("\\n", "\n   ", body[[1]])), commaSep), pasteC(attachments, C="\n          "), showSMTPsettings(smtp.settings, quiet=TRUE, lines=ifelse(w > 87, 2, 3)))), "\n")
          do.call(sprintf, c(list(fmt=sfmt, pasteR(w)),  lapply(list(to, cc, bcc, subject, gsub("\\n", "\n   ", body[[1]])), commaSep), pasteC(attachments, C="\n          "), showSMTPsettings(smtp.settings, quiet=TRUE, lines=ifelse(w > 87, 2, 3)))) %>% gsub("&nbsp;", " ", .) %>% gsub("<UL><LI>", "<UL>\n   <LI>", .) %>% gsub("<LI>", "* ", .) %>% cat("\n")
     }
          
     if (html)
          body <- gsub("\n", "<BR />", body)
  
     ## If SMTP has user settings, we need to set authenticate flag to TRUE
     authenticate <- !is.null(names(smtp.settings)) && any(grepl("user.name", names(smtp.settings)))

     ## Debugging
     browser(expr=inDebugMode(c("email")), text="in email() before calling sendmail")

     ## Normally, I will CC or BCC myself.  These I want to allow through without issue. 
     if (missing(allow.cc.when.using.name))
          allow.cc.when.using.name <- "rsaporta"
     if (is.character(allow.cc.when.using.name)) {
          allow.cc.when.using.name <- all(grepl(allow.cc.when.using.name, c(cc, bcc), ignore.case=TRUE))
          if (!allow.cc.when.using.name && length(to) > 1)
               message("did not find allow.cc in 'to'")
     }

     if (length(body) > 1) {
          if (length(to) != length(body))
               stop("length of 'body' (", length(body), ") must match length of 'to' (", length(to), ")")
          if (!allow.cc.when.using.name && (length(cc) > 0 || length(bcc > 0)) )
               stop ("\nCannot use cc or bcc when using '%name%'\n   unless flag 'allow.cc.when.using.name' is set to TRUE\n(This is a safety catch to prevent an awkward email faux-pas)")

          for (i in seq(body))
               send.mail(from = from,
                         to = to[i],
                         cc = cc,
                         bcc = bcc,
                         subject = subject,
                         body = body[i],
                         html = html,
                         smtp = smtp.settings,
                         attach.files = attachments,
                         authenticate = authenticate,
                         send = TRUE)

     } else {
          send.mail(from = from,
                    to = to,
                    cc = cc,
                    bcc = bcc,
                    subject = subject,
                    body = body,
                    html = html,
                    smtp = smtp.settings,
                    attach.files = attachments,
                    authenticate = authenticate,
                    send = TRUE)
     }
 

}

extractNameFromEmail <- function(to) {
     if (!is.null(names(to)))
          return(names(to))
     splat <- strsplit(to, "\\s+<")
     sapply(splat, function(x) if (length(x) == 2) x[[1]] else "")
}


formatEmailAddresses <- function(to) {
## converts  c(Name = "Addresss@gmail.com")  to  c("Name <Address@gmail.com>")
     nms <- names(to)

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

     ## non blanks and not already contains bracket
     dontModify <- (nms == "")  |  grepl("<|>", to)

     ## Return either original or modified version
     ifelse(dontModify, to, sprintf("%s <%s>", nms, to))
}

appendSignature <- function(body, name=c("SAM", "rick", "Rick", "RICK", "Rbox", "rbox", "")) {
     sig <- getSignaure(name=name)

     needs.endl <- !grepl("\\n\\s*$", body)
     if (any(needs.endl))
          body[needs.endl] <- paste(body[needs.endl], "\n")

     paste(body, sig, sep="\n")
}

getSignaure <- function(name=c("SAM", "rick", "Rick", "RICK", "Rbox", "rbox", "")) {
     name <- try(match.arg(name))

     if (name=="SAM") {
          paste0("S.A.M. :: the Data Science Robot\n\n<I>This email was generated automatically on ", gsub("  ", " ", timeStamp(f="%A, %B %e %Y at %X")), "\nPlease direct all questions to <A HREF=\"mailto:rsaporta+SAM@theorchard.com\">Rick Saporta</A></I>\n")
     } else if (tolower(name) == "rick"  ) {
          paste0("Rick Saporta, Data Scientist, The Orchard\n\n<I>This email was generated automatically on ", gsub("  ", " ", timeStamp(f="%A, %B %e %Y at %X")), " via a computer program\nIf anything seems out of place, please  <A HREF=\"mailto:rsaporta+auto_error@theorchard.com\">contact Rick</A> directly.</I>\n")
     } else if (tolower(name) == "rbox"  ) {
          paste0("The Data Science Team, The Orchard\n\n<I>This email was generated automatically on ", gsub("  ", " ", timeStamp(f="%A, %B %e %Y at %X")), " via a computer program\nIf anything seems out of place, please  <A HREF=\"mailto:rsaporta+rbox_error@theorchard.com\">contact Rick Saporta</A> directly.</I>\n")
     } else
          ""
}

insertInfoToBody <- function(body, info="DEFAULT", folder.info=src.p("emailBody"), fail.on.errorReading.info=TRUE, zArchive.whenDone.info=!{exists("TEST_RUN") && isTRUE(TEST_RUN)}) {
     if (!any(grepl("%info%", body)))
          return(body)

     if (info == "DEFAULT")
          info <- getInfoText(folder=folder.info, fail.on.errorReading=fail.on.errorReading.info, zArchive.whenDone=zArchive.whenDone.info)

     if (!is.character(info))
          stop ("'info' should be a string\nHINT: use info=\"\" to set to blank")
     if (length(info) > 1)
          stop ("'info' should be a string of length exactly 1. It has length = ", length(info))

     gsub("%info%", info, body)
}

getInfoText <- function(folder=src.p("emailBody"), pattern="infoText", ext=c("md", "txt"), endl.max=2, zArchive.whenDone=!{exists("TEST_RUN") && isTRUE(TEST_RUN)}, fail.on.errorReading=TRUE, showWarnings=FALSE) {

     files <- extractFilesFromFolder(folder=folder, pattern=pattern, ext=ext, full.names=TRUE)

     ## Warnings for missing or blanks
     if (!file.exists(folder))
          verboseMsg(showWarnings, "folder '", folder, "' does not exist")
     else if (!length(files))
          verboseMsg(showWarnings, "There are no files with pattern '", pattern, "' in folder '", folder, "'")

     ## return blank string if no files found
     if (!length(files))
          return("")
     
     ## Sort by modified time
     fileusing <- files[order(file.info(files)$mtime, decreasing=TRUE)][[1]]

     ## Try to read the lines 
     info <- try(pasteC(readLines(fileusing), C="\n"), silent=TRUE)
     if (isErr(info)) {
          msg <- sprintf("was unable to read the info file, '%s' from getInfoText() ", fileusing)
          if (fail.on.errorReading)
               stop(msg)
          verboseMsg(showWarnings, msg)
          info <- ""
     }

     if (is.numeric(endl.max)) {
          repl <- pasteR("\n", endl.max)
          pat  <- paste0(escapeRegEx(repl), "(\\s*\\n\\s*)$")
          info <- gsub(pat, repl, info)
     }

     if (zArchive.whenDone)
          zArchive(fileusing)

     return(info)
}


makeIntoInfoFile <- function(file, folder=src.p("emailBody"), pattern="infoText", ext="txt", copy.file=TRUE) {

     if (!file.exists(file))
          stop("file '", file, "' does not exist")

     ## ------------- Check perms ------------- ##
     ## 1 == execute, 2 == write, 4 == read
     ## recall that file.access returns 0 when *CAN* access and -1 when cannot access. 
     if (!copy.file && 0 != file.access(file, 2))
          stop ("You do not have write permissions for file '", file, "' -- necessary to move the file")
     else if (0 != file.access(file, 4))
          stop ("You do not have read permissions for file '", file, "' -- necessary to copy the file")
     if (!exists(folder)) {
          if (0 != file.access(dirname(folder), 2))
               stop ("You do not have write permissions for folder '", dirname(folder), "' -- necessary to create the subfolder")
          dir.create(folder, showWarnings=FALSE)
     }
     if (0 != file.access(folder, 2))
          stop ("You do not have write permissions for destination folder '", folder, "'")
     ## ------------- END Check perms ------------- ##
     
     newFile <- as.path(folder, pattern, ts=TRUE, ext=ext)

     if (copy.file)
          file.copy(from=file, to=newFile)
     else 
          file.rename(from=file, to=newFile)

     return(setNames(nm=file, obj=newFile))
}


getDefaultSMTPsettings <- function(use = c("gmail", "google", "orchard", "localhost")) {
     ## eg: 
    # list(host.name = "smtp.gmail.com", port = 465, user.name = "gmail_username", passwd = "password", ssl = TRUE)

     if (missing(use) && getPfm() == "Linux")
          use <- "orchard"

     use <- match.arg(use)

     ## Synonym
     if (use == "google")
          use <- "gmail"

     settings.ll <- list(
          localhost = list (
               host.name = "localhost"
               , port = 25
               , user.name = ""
               , passwd = ""
               , ssl = FALSE
               )
          ,
          gmail = list (
                 host.name = "smtp.gmail.com"
               , port = 465
               , user.name = "rsMailRobot@gmail.com"
               , passwd = "6Rh058URNN0l9SnmkhVIB89q"
               , ssl = TRUE
               )
          ,
          orchard = list (
                 host.name = "mail.theorchardemail.com"
               , port = 25
               , user.name = "thesam@email.theorchard.com"
               , passwd = "BfA7WJ1LXQzVACb"
               , ssl = FALSE
               )
          )

     return(settings.ll[[use]])
     # if (isTRUE(use.local)) {
     #      return(list(host.name = "localhost", port = 25, user.name = "rsaporta@gmail.com", passwd = "password", ssl = FALSE))
     # }

     # ## ELSE 
     # list(
     #   host.name = "smtp.gmail.com"
     # , port = 25
     # , user.name = "rsMailRobot@gmail.com"
     # , passwd = "6Rh058URNN0l9SnmkhVIB89q"
     # , ssl = FALSE)

     # ## ELSE 
     # list(
     #   host.name = "mail.theorchardemail.com"
     # , port = 25
     # , user.name = "thesam@email.theorchard.com"
     # , passwd = "BfA7WJ1LXQzVACb"
     # , ssl = FALSE)
}


showSMTPsettings <- function(smtp.settings=getDefaultSMTPsettings(), quiet=FALSE, lines.min=2) {
     sfmt <- paste0("   host : %-38s port : %s\n   user : %-38s pw   : ", ifelse("passwd" %in% names(smtp.settings), "********", "NA"), "          %s ssl  : %-5s")

     # if (length(smtp.settings) != 5)
     #      warning ("it looks like smtp.settings does not have exactly 5 elements")

     expected.names <- c("host.name", "port", "user.name", "passwd", "ssl")
     missing.names  <- setdiff(expected.names, names(smtp.settings))
     if (length(missing.names))
          smtp.settings[missing.names] <- NA_character_

     additional.names <- setdiff(names(smtp.settings), expected.names)
     if (length(additional.names))
          sfmt <- pasteC(c(sfmt, "\n", sprintf("\n   %s : %%s", additional.names)))
     
     ## We will remove the password and simultaneously use it as the placeholder for whether
     ##  ssl should be moved down to a new line or not

     smtp.settings[["passwd"]]  <- ifelse(lines.min==2, "", "\n  ")

     ## Reorder
     smtp.settings <- smtp.settings[c(expected.names, additional.names)]
     out <- do.call(sprintf, c(sfmt, smtp.settings))
     if (!quiet)
          cat(out, "\n", sep="")
     return(invisible(out))
}

if (FALSE) {
  ## EXAMPLE
  email_string <- "Data Requests <DataRequests@theorchard.com>, Albina Binyaminova <albina@theorchard.com>, Mike Baldo <mbaldo@theorchard.com>, Gabriella Cantwell <gcantwell@theorchard.com>, Kevin McAdoo <kmcadoo@theorchard.com>"
  email_string_to_r_vector(email_string)
}

email_string_to_r_vector <- function(email_string, sep=",", verbose=TRUE) {
## Useful for copying a set of emails from, say, Gmail, and parsing into a vector useful in R
##  that can then be added to getToGroup  etc
##
## The list of email addresses is in the file: 
##      ~/git/misc/rscripts/utils/Orchard_Specific/Email Addresses for quickemail.r
##

  if (!is.character(email_string))
    stop("email_string should be a string")


  splat <- strsplit(email_string, escapeRegEx(sep)) %>% unlist %>% trim

  pat.letters_etc <- "[A-Za-z0-9_\\.\\+\\-]"
  pat.name_and_email <- sprintf("(%1$s+\\s*)+\\s+<%1$s+@%1$s+>", pat.letters_etc)
  (grepl(pat.name_and_email, splat))
  {
    the_names <- gsub("\\s+<.*", "", splat)
    ret_splat <- 
      mapply(function(n, s) gsub(paste0(escapeRegEx(n), "\\s+"), "", s), n=the_names, s=splat) %>% 
        gsub("^\\s*(<)(.+)(>)\\s*$", "\\2", .) %>% 
        setNames(nm=the_names, obj=.)
  }
  {
    ret_self <- splat %>% gsub("^\\s*(<)(.+)(>)\\s*$", "\\2", .) %>% setNames(nm=., obj=.)
  }

  emails <- ifelse(grepl(pat.name_and_email, splat), ret_splat, ret_self)
  nms    <- ifelse(grepl(pat.name_and_email, splat), names(ret_splat), names(ret_self))
  ret <- setNames(obj=emails, nm=nms)

  if (verbose) {
    dictAlign(ret, collect="c", header.key="name", header.value="email")
    catn("\n")
  }

  return(ret)
}


### ------ TEST BELOW --------- ####


ARGS.TEST_EMAIL <- {
     list (
       to  = c(Rick_GMAIL = "rsaporta@gmail.com", Rick_work = "rsaporta@theorchard.com")
     , cc  = c("CC-rick-CC" = "rsaporta+cc@theorchard.com")
     , bcc = c("blind rick" = "rsaporta+bcc@theorchard.com")
     , subject  = "Oh, Hi There. It looks like I work. High Five"
     , msg = paste0("Sure, this email may only be a test, but I am still a living, breathing machine, am I not?\n\nI was sent from ", ifelse(.Pfm=="Linux", "the cloud -- ooooo fancy!", "some goon's local machine"))
     , attachments = c("~/itsalive.jpeg")
)}

if (FALSE) 
{
     .g()
     source("~rsaporta/git/misc/rscripts/utils/notify/email_with_mailR.r")
     ## EXECUTE: 
     do.call(email, ARGS.TEST_EMAIL)

     ## Command line execution of this test
     #     su rsaporta
     #     cd ~/git
     #     git pull origin master
     #     Revoscript -e 'source("~rsaporta/git/misc/rscripts/utils/notify/email_with_mailR.r"); cat("\n\n"); do.call(email, ARGS.TEST_EMAIL)'
}


