@@ -566,53 +566,178 @@ write_info_log_entry <- function(conn, target_db_name, table_written = NULL, df,
566
566
567
567
# ' A wrapper function that sends an email (via sendmailR) reporting the outcome of another function
568
568
# '
569
+ # ' This function sends an email via `sendmailR`, optionally including a dataframe(s) or zip files(s) as attachments.
570
+ # '
569
571
# ' @param email_body The contents of the email
570
572
# ' @param email_subject The subject line of the email
571
573
# ' @param email_to The email addresses of the primary recipient(s), separate recipient addresses with spaces
572
574
# ' @param email_cc The email addresses of cc'd recipient(s), separate recipient addresses with spaces
573
575
# ' @param email_from The email addresses of the sender
574
- # ' @return No returned value
576
+ # ' @param df_to_email (Optional) A dataframe or a list of dataframes to be included as file attachment(s). If this parameter is used, `file_name` must also be specified.
577
+ # ' Each dataframe in the list must have a corresponding file name in the `file_name` parameter to ensure a one-to-one match between dataframes and file names.
578
+ # ' @param file_name (Optional) A character vector specifying the file name(s) of the attachment(s). Valid file extensions are `.csv`, `.xlsx`, and `.zip`. Each file name must be unique.
579
+ # ' @param ... Additional arguments passed directly to the file writing functions: `write.csv` for CSV files, and `writexl::write_xlsx` for XLSX files.
580
+ # '
581
+ # ' @return No returned value. It performs an action by sending an email.
575
582
# ' @examples
576
583
# '
577
584
# ' \dontrun{
578
- # ' message <- paste("Failed REDCap data import to", project_title,
585
+ # ' email_body <- paste("Failed REDCap data import to", project_title,
579
586
# ' "\nThe reason given was:", error_message)
580
587
# '
581
588
# ' email_subject <- paste("FAILED |", script_name, "|",
582
589
# ' Sys.getenv("INSTANCE"), "|", script_run_time)
583
590
# '
584
- # ' send_email(message, email_subject)
591
+ # ' # email without attachemnts
592
+ # ' send_email(email_body, email_subject)
593
+ # '
594
+ # ' email_to <- c("email1@example.com email2@example.com")
595
+ # ' dfs_to_email <- list(head(cars), tail(cars))
596
+ # ' file_names <- c("file1.csv", "file2.xlsx")
597
+ # '
598
+ # ' # single attachment and at least one email address
599
+ # ' send_email(
600
+ # ' email_subject = email_subject,
601
+ # ' email_body = email_body,
602
+ # ' email_from = email_from,
603
+ # ' email_to = email_to,
604
+ # ' df_to_email = head(cars),
605
+ # ' file_name = "file1.csv"
606
+ # ' )
607
+ # '
608
+ # ' # multiple attachments and at least one email address
609
+ # ' send_email(
610
+ # ' email_subject = email_subject,
611
+ # ' email_body = email_body,
612
+ # ' email_from = email_from,
613
+ # ' email_to = email_to,
614
+ # ' df_to_email = dfs_to_email,
615
+ # ' file_name = file_names
616
+ # ' )
617
+ # '
618
+ # ' send_email(
619
+ # ' email_subject = email_subject,
620
+ # ' email_body = email_body,
621
+ # ' email_from = email_from,
622
+ # ' email_to = email_to,
623
+ # ' file_name = c("file1.zip", "<path_to_file>file2.zip")
624
+ # ' )
625
+ # '
626
+ # ' # single attachment for each email group
627
+ # ' email_to <- c("email1@example.com", c("email2@example.com email3@example.com"))
628
+ # '
629
+ # ' args_list <- list(
630
+ # ' email_subject = email_subject,
631
+ # ' email_body = email_body,
632
+ # ' email_to = email_to,
633
+ # ' email_from = email_from,
634
+ # ' df_to_email = dfs_to_email,
635
+ # ' file_name = file_names
636
+ # ' )
637
+ # '
638
+ # ' purrr::pmap(args_list, send_email)
639
+ # '
640
+ # ' # multiple attachments for each email group
641
+ # ' email_to <- c(
642
+ # ' c("email1@example.com email2@example.com"),
643
+ # ' c("email3@example.com email4@example.com")
644
+ # ' )
645
+ # '
646
+ # ' args_list <- list(
647
+ # ' email_subject = email_subject,
648
+ # ' email_body = email_body,
649
+ # ' email_to = email_to,
650
+ # ' email_from = email_from,
651
+ # ' df_to_email = list(dfs_to_email, dfs_to_email),
652
+ # ' file_name = list(file_names, file_names)
653
+ # ' )
654
+ # '
655
+ # ' purrr::pmap(args_list, send_email)
656
+ # '
585
657
# ' }
586
658
# ' @importFrom sendmailR "sendmail"
659
+ # ' @importFrom writexl write_xlsx
587
660
# ' @export
588
- send_email <- function (email_body , email_subject = " " , email_to = " " , email_cc = " " , email_from = " " ) {
589
- # email credentials
590
- email_server <- list (smtpServer = Sys.getenv(" SMTP_SERVER" ))
591
- if (email_from == " " ) {
592
- email_from <- Sys.getenv(" EMAIL_FROM" )
593
- }
594
- if (email_cc == " " ) {
595
- email_cc <- unlist(strsplit(Sys.getenv(" EMAIL_CC" ), " " ))
596
- } else {
597
- email_cc <- unlist(strsplit(email_cc , " " ))
598
- }
599
- if (email_subject == " " ) {
600
- email_subject <- paste(Sys.getenv(" EMAIL_SUBJECT" ), get_script_run_time())
601
- }
661
+ send_email <-
662
+ function (email_body ,
663
+ email_subject = " " ,
664
+ email_to = " " ,
665
+ email_cc = " " ,
666
+ email_from = " " ,
667
+ df_to_email = NULL ,
668
+ file_name = NULL ,
669
+ ...
670
+ ) {
671
+
672
+ email_server <- list (smtpServer = Sys.getenv(" SMTP_SERVER" ))
673
+ if (email_from == " " ) {
674
+ email_from <- Sys.getenv(" EMAIL_FROM" )
675
+ }
676
+ if (email_cc == " " ) {
677
+ email_cc <- unlist(strsplit(Sys.getenv(" EMAIL_CC" ), " " ))
678
+ } else {
679
+ email_cc <- unlist(strsplit(email_cc , " " ))
680
+ }
681
+ if (email_subject == " " ) {
682
+ email_subject <-
683
+ paste(Sys.getenv(" EMAIL_SUBJECT" ), get_script_run_time())
684
+ }
602
685
603
- if (email_to == " " ) {
604
- email_to <- unlist(strsplit(Sys.getenv(" EMAIL_TO" ), " " ))
605
- } else {
606
- email_to <- unlist(strsplit(email_to , " " ))
607
- }
686
+ if (email_to == " " ) {
687
+ email_to <- unlist(strsplit(Sys.getenv(" EMAIL_TO" ), " " ))
688
+ } else {
689
+ email_to <- unlist(strsplit(email_to , " " ))
690
+ }
608
691
609
- # # TODO: consider toggling bypass of printing if interactive and local env detected
610
- # # if (interactive()) {
611
- # # print(email_body)
612
- # # return(email_body)
613
- # # }
614
- # TODO: consider replacing sendmailR with mRpostman
615
- sendmailR :: sendmail(from = email_from , to = email_to , cc = email_cc ,
616
- subject = email_subject , msg = email_body ,
617
- control = email_server )
618
- }
692
+ if (! is.null(file_name )) {
693
+ output_dir <- tempdir()
694
+ email_content <- list ()
695
+
696
+ if (! is.null(df_to_email ) && is.data.frame(df_to_email )) {
697
+ df_to_email <- list (df_to_email )
698
+ }
699
+
700
+ if (! is.null(df_to_email ) &&
701
+ length(df_to_email ) != length(file_name )) {
702
+ stop(" The number of dataframes and file names must match." )
703
+ }
704
+
705
+ for (i in seq_along(file_name )) {
706
+ file_extension <- tolower(sub(" .*\\ .(.*)$" , " \\ 1" , file_name [[i ]]))
707
+ file_fullpath <- file.path(output_dir , basename(file_name [[i ]]))
708
+
709
+ if (! is.null(df_to_email )) {
710
+ if (file_extension == " csv" ) {
711
+ readr :: write_csv(df_to_email [[i ]], file_fullpath , ... )
712
+ } else if (file_extension == " xlsx" ) {
713
+ writexl :: write_xlsx(df_to_email [[i ]], file_fullpath , ... )
714
+ } else {
715
+ stop(" Unsupported file format. Use 'csv' or 'xlsx'." )
716
+ }
717
+ }
718
+
719
+ if (file_extension == " zip" &&
720
+ ! file.copy(file_name [[i ]], output_dir , overwrite = TRUE )) {
721
+ stop(paste(" Failed to move" , file_name [[i ]]))
722
+ }
723
+
724
+ attachment_object <- sendmailR :: mime_part(file_fullpath , basename(file_fullpath ))
725
+ email_content <- c(email_content , attachment_object )
726
+ }
727
+ }
728
+
729
+ # # TODO: consider toggling bypass of printing if interactive and local env detected
730
+ # # if (interactive()) {
731
+ # # print(email_body)
732
+ # # return(email_body)
733
+ # # }
734
+ # TODO: consider replacing sendmailR with mRpostman
735
+ sendmailR :: sendmail(
736
+ from = email_from ,
737
+ to = email_to ,
738
+ cc = email_cc ,
739
+ subject = email_subject ,
740
+ msg = email_content ,
741
+ control = email_server
742
+ )
743
+ }
0 commit comments