You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言MailR发送邮件问题:单邮件多CSV附件而非多邮件

解决方案:单封邮件发送对应收件人的所有CSV附件

核心思路

  1. 先批量生成所有需要的CSV文件,同时记录每个文件对应的收件人邮箱
  2. 按收件人邮箱分组,收集每个收件人对应的所有本次新生成的CSV文件
  3. 对每个收件人仅发送一封包含其所有对应附件的邮件

修正后的代码

library(mailR)
library(data.table)
library(dplyr)

parent_dir <- "location of the parent_dir path"

df <- data.frame(
  city = c("New York", "Los Angeles", "New York", "Chicago", "Los Angeles", "Chicago"),
  year = c(2023, 2023, 2023, 2022, 2022, 2022),
  week = c(1, 2, 1, 1, 2, 2),
  value = c(100, 200, 150, 300, 250, 400),
  email = c("email1@example.com", "email1@example.com", "email3@example.com", 
            "email4@example.com", "email3@example.com", "email4@example.com")
)

# 初始化列表,存储邮箱与对应附件路径的映射
email_attachments <- list()

# 批量生成CSV并记录附件与邮箱的关联
lapply(split(df, list(df$city, df$year, df$week), drop = TRUE), function(sub_df) {
  city <- unique(sub_df$city)
  year <- unique(sub_df$year)
  week <- unique(sub_df$week)

  # 创建层级文件夹(recursive=TRUE自动创建父级目录)
  city_folder <- paste0(parent_dir, city)
  year_folder <- file.path(city_folder, year)
  if (!dir.exists(city_folder)) dir.create(city_folder, recursive = TRUE)
  if (!dir.exists(year_folder)) dir.create(year_folder, recursive = TRUE)

  # 处理收件人邮箱(支持逗号分隔的多邮箱)
  sub_df$email <- strsplit(sub_df$email, ",") 
  email_list <- unique(unlist(sub_df$email))

  # 整理数据(移除不需要的列)
  remove_year_email <- sub_df %>% select(-c(year, email))
  csv_file_path <- file.path(year_folder, paste0(city, " ", week, "-", year, ".csv"))

  # 仅生成不存在的文件(避免重复生成,确保仅本次新文件被作为附件)
  if (!file.exists(csv_file_path)) {
    fwrite(remove_year_email, csv_file_path, sep = ";")
  }

  # 将当前CSV路径关联到对应的每个邮箱
  for (email in email_list) {
    if (is.null(email_attachments[[email]])) {
      email_attachments[[email]] <- c()
    }
    email_attachments[[email]] <- c(email_attachments[[email]], csv_file_path)
  }
})

# 按邮箱分组,发送包含所有对应附件的单封邮件
for (email in names(email_attachments)) {
  send.mail(
    from = "sender",
    to = email,
    subject = "City files",
    body = "test",
    html = TRUE,  
    smtp = list(host.name = "example", port = 1234, 
                user.name = "example",            
                passwd = "example", ssl = TRUE),
    authenticate = TRUE,
    send = TRUE,
    attach.files = email_attachments[[email]],
    debug = TRUE
  )
}

关键修改点

  • 新增附件映射列表:用email_attachments收集每个收件人对应的所有CSV路径,彻底解决"一个附件一封邮件"的问题
  • 移除即时发送逻辑:将原代码中生成一个文件就发邮件的逻辑改为先记录所有附件,最后统一发送
  • 文件存在检查:通过!file.exists(csv_file_path)判断,仅生成新文件,确保附件只包含本次任务生成的内容,排除文件夹中已有文件
  • 批量关联邮箱与附件:遍历每个子数据框对应的收件人,把CSV路径绑定到对应邮箱的列表中

内容的提问来源于stack exchange,提问作者MartijnB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:33:23