Bash脚本发送邮件时无法附加全部.xlsx文件的问题求助
问题排查与修复方案
第一段代码仅部分附件被添加的原因
第一个循环里,"$attachment_dir"/*.xlsx的写法虽给目录加了引号,但通配符*.xlsx在引号外。当文件名包含空格或特殊字符时,Bash会按默认的IFS(空格、制表符、换行符)拆分文件名,导致循环中出现非文件元素,[ -f "$attachment" ]判断失败后跳过这些文件,最终出现部分文件未被附加的情况。
第二段代码仅单个附件被添加的原因
- 重名文件被覆盖:用
find复制所有.xlsx文件到临时目录时,如果原目录(含子目录)中有同名文件,cp {} "$temp_dir"会直接覆盖旧文件,最终临时目录只剩每个同名文件的最后一个副本,循环自然只处理到一个文件。 - 边界收尾的换行符问题:
email+="\n--boundary_1234--"用双引号包裹时,\n不会被解析为换行符,导致邮件MIME结构损坏,可能影响附件识别。
修复后的完整脚本
#!/bin/bash # 附件目录 attachment_dir="." # HTML邮件正文文件 html_file="abc.html" # 邮件信息 recipient="abc@abc.com" subject="Email Subject" sender="abc@abc.com" body=$(cat "$html_file") # 生成唯一边界字符串,避免与邮件内容冲突 boundary="$(uuidgen)" # 初始化邮件头部与正文 email=$(cat <<EOF To: $recipient From: $sender Subject: $subject Content-Type: multipart/mixed; boundary="$boundary" --$boundary Content-Type: text/html $body EOF ) # 安全遍历所有.xlsx文件,兼容带空格/特殊字符的文件名 while IFS= read -r -d '' attachment; do if [ -f "$attachment" ]; then filename=$(basename "$attachment") # 生成base64编码的附件内容 attachment_data=$(base64 -w 0 "$attachment") # 追加附件到邮件 email+=$(cat <<EOF --$boundary Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; name="$filename" Content-Disposition: attachment; filename="$filename" Content-Transfer-Encoding: base64 $attachment_data EOF ) fi done < <(find "$attachment_dir" -name "*.xlsx" -type f -print0) # 添加结尾边界,确保换行符生效 email+=$'\n--'"$boundary"'--' # 发送邮件 echo -e "$email" | sendmail -t
关键修复点说明
- 安全遍历文件:用
find ... -print0配合while IFS= read -r -d '',完美处理带空格、特殊字符的文件名,不会拆分或遗漏文件。 - 避免重名覆盖:直接遍历原文件,无需复制到临时目录,从根源解决重名覆盖问题。
- 唯一边界字符串:用
uuidgen生成随机边界,避免与邮件内容中的字符串冲突,保证MIME结构正确。 - 正确换行处理:结尾边界用
$'\n'生成真实换行符,确保邮件结构完整可被邮件客户端正确解析。
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

