首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

qmailadmin + vpopmail + MySQL 郵件過濾器實戰配置:自動初始化與 Webmail 聯動

     編輯:MySQL 綜合教學

qmailadmin + vpopmail + maildrop 郵件過濾器全自動化配置實戰

本文解決三大核心痛點:① 用戶創建時自動初始化過濾規則 ② Webmail (sqwebmail) 定義的規則生效機制 ③ 權限與腳本執行陷阱。基於 qmail-local (MDA) + maildrop 架構,實現從賬號創建到規則生效的全鏈路自動化。

架構圖解

qmailadmin (CGI) 
    │ 創建用戶 → 觸發 .qmailadmin-hooks
    ▼
inituser.sh (腳本) 
    ├── 創建 .qmail-user → |maildrop $DOMAIN/$USER/.mailfilter
    ├── 創建 .mailfilter → include $USER/.userfilter
    ├── 創建 .userfilter (默認規則 + sqwebmail 標記)
    └── 創建 Maildir/maildirfilterconfig → 指向 ../.userfilter
    ▼
sqwebmail 讀取 maildirfilterconfig → 編輯 .userfilter → 即時生效
maildrop 執行 .mailfilter → 包含 .userfilter → 規則生效

第一步:配置 qmailadmin Hooks 自動初始化

域目錄由 /var/qmail/users/assign 定位,例:+domain.com-:domain.com:515:511:/home/vpopmail/domains/domain.com:-::

在域目錄下創建 .qmailadmin-hooks(屬主 vpopmail:vchkpw,權限 644):

adduser: /home/vpopmail/bin/inituser.sh
deluser: /home/vpopmail/bin/deluser.sh
moduser: /home/vpopmail/bin/moduser.sh

第二步:核心初始化腳本 inituser.sh

#!/bin/bash
# 參數位置修正:qmailadmin 1.0.6+ 傳參順序 $1=User $2=Domain $3=Password $4=RealName
User=$1
Domain=$2
Passwd=$3
RealName=$4
DomainPath=/home/vpopmail/domains/$Domain
umask 0177

exec 1> /tmp/adduser.log
exec 2>&1

echo "Initializing $User@$Domain"

# 1. .qmail-user → 管道給 maildrop
cat > $DomainPath/.qmail-$User <<EOF
|maildrop $DomainPath/$User/.mailfilter
EOF

# 2. .mailfilter → 包含用戶可編輯的 .userfilter
cat > $DomainPath/$User/.mailfilter <<EOF
include $User/.userfilter
EOF

# 3. .userfilter → 默認規則 + sqwebmail 識別標記(關鍵!)
cat > $DomainPath/$User/.userfilter <<EOF
#MFMAILDROP=2
# DO NOT EDIT THIS FILE. This is an automatically generated filter.
FROM='$User@$Domain'
import SENDER
if (\$SENDER ne "")
{
    FROM=\$SENDER
}
to "$DomainPath/$User/Maildir/."
EOF

# 4. maildirfilterconfig → 指向 .userfilter(而非 .mailfilter,便於擴展)
cat > $DomainPath/$User/Maildir/maildirfilterconfig <<EOF
MAILDIRFILTER=../.userfilter
MAILDIR=$DomainPath/$User/Maildir
EOF

第三步:刪用戶清理腳本 deluser.sh

#!/bin/bash
User=$1; Domain=$2; Passwd=$3; RealName=$4
DomainPath=/home/vpopmail/domains/$Domain
rm -f $DomainPath/.qmail-$User
# 注意:不刪除 Maildir 內容,由 vpopmail 主流程處理

第四步:修復 qmailadmin 源碼 Bug(必須!)

文件:qmailadmin-1.0.6/user.c 函數 call_hooks() 的 fork() 前插入權限提升,修正參數傳遞邏輯:

// 權限提升:http 用戶 → root → vpopmail 用戶
setuid(0);
setgid(VPOPMAILGID);
setuid(VPOPMAILUID);

pid = fork();
#ifdef DEBUG
fprintf(actout, "Hook params: %s, %s, %s, %s, %s\n", cmd, hooks[hook_type], Newu, Domain, Password1);
#endif
if (pid == 0) {
    // 修正:新建用戶用 Newu,修改/刪除用 ActionUser
    if (Newu && *Newu) {
        error = execl(cmd, cmd, Newu, Domain, Password1, Gecos, NULL);
    } else {
        error = execl(cmd, cmd, ActionUser, Domain, Password1, Gecos, NULL);
    }
    _exit(error);
}

編譯替換:make clean && make,將生成的 qmailadmin.cgi 複製至 CGI 目錄,設置 chown root:root qmailadmin.cgi && chmod 4755 qmailadmin.cgi (SUID root)。

第五步:關鍵細節避坑指南

問題原因解決
sqwebmail 報錯無法識別過濾器.userfilter 缺少 #MFMAILDROP=2 標記行腳本中強制寫入首行標記,不可刪除
為何 maildirfilterconfig 指向 .userfilter 而非 .mailfilter便於在 .mailfilter 中包含系統級規則(如病毒掃描、全局黑名單),用戶僅編輯 .userfilter架構分層:.mailfilter(系統+用戶) → include .userfilter(用戶自定義)
Hook 腳本權限失敗qmailadmin 以 Apache 用戶運行,fork 子進程無權寫 vpopmail 目錄源碼注入 setuid(0)/setgid/setuid 提權,或編寫 SUID 包裝程序
為何不用 su 執行腳本Apache 重定向了 stdin,su 檢測非 tty 拒絕執行;fork+exec 不複製 euid/egid源碼提權是唯一可靠方案
moduser/deluser 取不到用戶名原代碼 execl 參數錯誤,Gecos 只有新建時有值區分 Newu/ActionUser 參數傳遞(見上文修正代碼)

擴展建議

  • 將 hook_type (adduser/moduser/deluser...) 作為參數傳給腳本,單腳本內部 case 分發,減少腳本文件數量
  • 整合 MySQL 存儲過濾規則:.userfilter 可為 SQL 查詢生成的動態規則文件
  • 監控 /tmp/adduser.log 排查初始化失敗
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved