使用Bash和ssmtp发送含变量的邮件失败问题排查
解决ssmtp发送邮件时变量无法传递、内容为空的问题
问题场景
在DietPi系统中使用Bash结合ssmtp发送邮件,已从dropbear服务日志收集登录数据并生成邮件内容,但发送时变量无法正常传递,邮件内容完全为空。使用mail命令执行相同逻辑可正常发送,尝试过sync、wait命令及echo -e参数均无效。
脚本示例:
#!/bin/bash # Gather login data login_data=$(journalctl -u dropbear.service | grep "Password") # Generate email content email_content="Login Data:\n${login_data}" # Send email using ssmtp sync ssmtp -m nodododi@example.com < <(echo "${email_content}")
补充信息:
- 用ssmtp发送的邮件完全为空,连'Login Data'标签都没有
- echo中的
\n无法换行,但mail命令可正常换行 set -x输出的登录数据正常- 使用Bash 5.2.15(1)-release版本
- 直接用ssmtp发送固定文本可正常工作
问题原因及解决方法
1. ssmtp的核心要求:标准邮件格式
ssmtp必须接收包含完整邮件头的输入(如From:、To:、Subject:),缺少这些字段会导致ssmtp无法正确解析内容,直接丢弃输入。这是和mail命令的核心差异——mail会自动补全必要的邮件头,而ssmtp完全依赖用户提供的完整格式。
2. echo转义字符的处理问题
默认echo不会解析\n这类转义字符,即使加-e参数,若邮件格式不完整也无法解决内容为空的问题。
修正后的脚本
#!/bin/bash # Gather login data login_data=$(journalctl -u dropbear.service | grep "Password") # 用Here Document生成带完整邮件头的内容,避免转义字符问题 email_content=$(cat <<EOF From: DietPi-Server <sender@example.com> To: nodododi@example.com Subject: Dropbear 登录记录通知 Login Data: ${login_data} EOF ) # 管道传递内容给ssmtp echo "${email_content}" | ssmtp nodododi@example.com
关键调整点
- 强制添加
From:、To:、Subject:邮件头,这是ssmtp处理邮件的必填项 - 使用Here Document(
<<EOF)生成内容,无需手动处理\n转义,格式更直观 - 改用管道传递内容,替代进程替换写法,避免子shell变量传递的潜在问题
- 若仍需使用
echo,需配合-e参数解析转义字符,但必须保证邮件头完整
验证步骤
- 先测试ssmtp基础功能是否正常:
echo -e "From: test@example.com\nTo: nodododi@example.com\nSubject: 测试邮件\n\n测试内容" | ssmtp nodododi@example.com
能收到邮件则说明ssmtp配置正常,问题出在脚本内容格式。
- 检查
login_data是否含特殊字符:
echo "${login_data}" | cat -A
若存在不可见字符或异常换行,可使用sed 's/[^a-zA-Z0-9: -]//g'或tr -d '\r'清理。
内容的提问来源于stack exchange,提问作者pedante
相关产品推荐
相关产品推荐

