Postfix环境下Python脚本获取邮件信息及优化收件文件夹咨询
我来帮你搞定这两个问题,先从Python获取邮件信息说起,再聊聊创建独立邮件目录的更优方案。
一、在Python脚本中获取邮件主题、正文等信息
你现在的核心问题是Python脚本没拿到完整的邮件数据——原来的a.sh里,ripmime读取了标准输入的邮件内容后,stdin就空了,Python脚本自然读不到东西。我们需要先把邮件内容保存到临时文件,让ripmime和Python都能访问到,再用Python自带的email模块解析邮件(无需额外安装依赖)。
步骤1:修改a.sh脚本,保留邮件内容
把你的a.sh改成这样,确保邮件内容能同时给到ripmime和Python:
#!/usr/bin/bash # 创建临时文件存储邮件内容 temp_email=$(mktemp) # 将stdin的邮件写入临时文件 cat > "$temp_email" # 用ripmime提取附件 /usr/bin/ripmime -i "$temp_email" -d Maildir/ --prefix # 把临时文件作为Python脚本的输入 /usr/bin/python3 /home/ali/Maildir/a.py < "$temp_email" # 清理临时文件,避免磁盘占用 rm "$temp_email"
步骤2:编写Python邮件解析脚本
用email模块解析邮件,处理主题的编码问题(比如中文/特殊字符的RFC2047编码),示例代码如下:
import sys from email import policy from email.parser import BytesParser def extract_email_details(): # 读取临时文件中的原始邮件内容 raw_email = sys.stdin.read().encode('utf-8') # 使用现代邮件规则解析(支持复杂格式) msg = BytesParser(policy=policy.default).parsebytes(raw_email) # 解析并解码邮件主题 subject = msg['Subject'] if subject: decoded_subject = subject.encode('utf-8').decode('unicode-escape') print(f"邮件主题: {decoded_subject}") else: print("邮件无主题") # 提取基础邮件头信息 print(f"发件人: {msg.get('From', '未知')}") print(f"收件人: {msg.get('To', '未知')}") print(f"邮件ID: {msg.get('Message-ID', '未知')}") # 提取邮件正文(区分纯文本和HTML) print("\n=== 邮件正文 ===") if msg.is_multipart(): # 多部分邮件(带附件),跳过附件部分 for part in msg.walk(): content_disposition = str(part.get("Content-Disposition")) if "attachment" not in content_disposition: content_type = part.get_content_type() if content_type == "text/plain": print("【纯文本正文】") print(part.get_content()) elif content_type == "text/html": print("【HTML正文】") print(part.get_content()) else: # 单部分邮件(无附件) content_type = msg.get_content_type() if content_type == "text/plain": print(msg.get_content()) elif content_type == "text/html": print(msg.get_content()) if __name__ == "__main__": extract_email_details()
运行后,你就能看到完整的邮件主题、发件人、正文等信息了。如果需要把这些信息保存到文件,只需在Python脚本里添加文件写入逻辑即可。
二、为每封邮件创建独立目录的更优方案
每封邮件的Message-ID是全局唯一的,用它来命名目录是最稳妥的选择(不会重复)。我们可以直接在Procmail里处理目录创建,效率更高。
方案:利用Procmail的$MSGID变量生成唯一目录
修改你的.procmailrc,先基于Message-ID生成合法的目录名(去掉特殊字符),再把邮件处理到这个目录:
VERBOSE=on LOGFILE=/home/ali/procmail.log # 生成唯一目录名:时间戳+清理后的Message-ID(避免特殊字符) EMAIL_DIR="$HOME/Maildir/emails/$(date +%Y%m%d-%H%M%S)-$(echo "$MSGID" | tr -d '<>@.')" # 创建目录(如果不存在) :0 * ? mkdir -p "$EMAIL_DIR" { # 将当前处理目录指向这个唯一目录 MAILDIR="$EMAIL_DIR" # 调用处理脚本 :0 | /home/ali/Maildir/a.sh }
然后修改a.sh,让ripmime把附件提取到这个MAILDIR目录,同时让Python把邮件信息保存到该目录下的文件:
#!/usr/bin/bash temp_email=$(mktemp) cat > "$temp_email" # 把附件提取到Procmail指定的唯一目录 /usr/bin/ripmime -i "$temp_email" -d "$MAILDIR" --prefix # 把邮件信息写入目录下的email_info.txt文件 /usr/bin/python3 /home/ali/Maildir/a.py < "$temp_email" > "$MAILDIR/email_info.txt" rm "$temp_email"
这样处理后,每封邮件都会在~/Maildir/emails/下生成一个类似20240520-143022-12345abcdef的独立目录,里面存放提取的附件和email_info.txt(包含邮件主题、正文等信息)。
额外优化建议
- 如果担心
Message-ID清理后仍有特殊字符,可以用sed替换所有非字母数字字符:echo "$MSGID" | sed 's/[^a-zA-Z0-9]/_/g' - 可以在目录名里加上收件人前缀,方便分类:
$(echo "$TO" | cut -d'@' -f1)-$(date +%Y%m%d-%H%M%S)-$(echo "$MSGID" | tr -d '<>@.') - 如需同步到其他服务器,可在
a.sh末尾添加rsync命令:rsync -avz "$MAILDIR" user@remote-server:/path/to/backup/
内容的提问来源于stack exchange,提问作者alireza

