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

使用CURL Shell脚本发邮件部分收件人未收到附件的问题排查

Shell脚本通过CURL发邮件:部分收件人丢失附件的问题分析

问题背景

我通过Shell脚本实现自动化发送带附件的邮件,流程如下:

  1. 使用tabcmd命令从私有Tableau服务器下载仪表盘并保存到本地目录
  2. 通过私有SMTP服务器,调用CURL将下载的文件发送给对应收件人

环境信息:

  • Tableau Server与SMTP服务器均部署在CentOS 7容器中
  • CURL版本为7.29
  • 脚本遍历仪表盘URL列表和对应收件邮箱列表,针对每个仪表盘完成下载后发送给指定收件人

当前问题:部分收件人能正常收到附件,但另一些仅收到邮件正文,附件丢失。CURL返回状态正常,邮件已进入SMTP队列,且本地目录中确实存在对应的附件文件。自身邮箱测试无问题,但替换为客户邮箱后出现差异,且无法直接用客户邮箱复现问题。

核心代码

发送邮件函数send_pdf

send_pdf(){
   
    receiver="$1"
    subject="$2"
    message="$3"
    num_file_attaches=$(expr $# - 3)

    eval body=$(cat parameters/data.txt)

    for file in "${@:4}"; do
        add_file "$body" "$file"
    done

    body+="--MULTIPART-MIXED-BOUNDARY--"
    echo -e "$body" | curl -s "$SMTP_SERVER" \
        --mail-from "$SENDER" \
        --mail-rcpt "$receiver"\
        -T -

}

添加附件函数add_file

add_file() {
    body="$1"
    file_attach="$2"
    name_file_attach=$(basename $file_attach)
    file_base64=$(cat $file_attach | base64)

    MIMEType=`file --mime-type "$file_attach" | sed 's/.*: //'`
    body+="--MULTIPART-MIXED-BOUNDARY\nContent-Type: $MIMEType;name=${name_file_attach}\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment;filename=${name_file_attach}\n\n\n${file_base64}\n\n\n"
}

可能的问题原因

  • Shell函数变量传递错误:这是最关键的问题——add_file函数中接收的body是值传递,函数内部对body的修改不会同步到send_pdf函数中的全局body变量。也就是说,所有附件的内容根本没被添加到最终的邮件正文中,仅当测试场景无附件或存在变量传递巧合时才会表现正常。
  • MIME格式不规范:
    • 边界字符串MULTIPART-MIXED-BOUNDARY无唯一性,部分邮件服务器/客户端对边界唯一性要求严格,重复边界会导致附件解析失败
    • 头信息与内容之间的换行符不符合标准(当前用了\n\n\n),正确的MIME格式要求头信息后用单个空行分隔内容
  • Base64编码兼容性问题:base64命令默认将编码内容按每行76字符换行,部分老旧邮件客户端无法正确解析带换行的Base64附件;另外如果tabcmd下载文件未完成就读取,会导致Base64编码残缺,附件无法识别
  • MIME类型识别偏差:file --mime-type可能将PDF文件识别为application/octet-stream而非标准的application/pdf,部分邮件客户端会忽略非预期MIME类型的附件
  • 邮箱服务商规则差异:不同企业/公共邮箱的反垃圾邮件、MIME解析规则不同,部分服务商对不符合严格标准的邮件会自动过滤附件

复现与验证方法

  • 修复变量传递问题后测试:修改add_file函数,让它返回附件的MIME片段,再拼接到全局body中,示例修改如下:
    add_file() {
        file_attach="$1"
        name_file_attach=$(basename "$file_attach")
        file_base64=$(base64 "$file_attach")
        MIMEType=$(file --mime-type "$file_attach" | sed 's/.*: //')
        echo -e "--MULTIPART-MIXED-BOUNDARY\nContent-Type: $MIMEType;name=\"${name_file_attach}\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment;filename=\"${name_file_attach}\"\n\n${file_base64}\n"
    }
    
    # 在send_pdf中修改拼接逻辑
    body=$(cat parameters/data.txt)
    for file in "${@:4}"; do
        body+=$(add_file "$file")
    done
    body+="--MULTIPART-MIXED-BOUNDARY--"
    
    用该版本脚本测试之前出问题的客户邮箱,看是否解决附件丢失问题
  • 模拟多样化测试环境:使用不同服务商的邮箱(企业邮箱、Gmail、Outlook、QQ邮箱等)进行批量测试,重点覆盖之前出现问题的邮箱类型
  • 验证文件读取完整性:在tabcmd下载完成后添加延迟(如sleep 3)或检查文件大小是否稳定,再执行发送操作,排除文件未完全写入导致的编码问题
  • 构造不规范MIME格式:故意使用重复边界、错误换行符、残缺Base64编码,测试是否会触发附件丢失的情况,验证格式规范对解析的影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 12:54:19