RedHat Linux 5.5 x86 系統Sendmail 郵件服務器搭建

     本文檔的重點在過濾器的配置,以及sample的生成,其他儘量從簡,相應章節的安裝過程可以參考相應的操作文檔。 

一、從簡架設裸Linux服務器

1、爲了節約系統資源,採用文本安裝的方式,輸入 Linux text 按 回車 鍵,這樣系統安裝完畢後,會默認工作在 init 3 的級別下,同時不會使用RedHat 的圖形界面安裝,可以節約安裝時間及效率。裏面有個地方涉及到需要輸入 installation number ,經過驗證,可以輸入:550dd56b51499bd

2、下面簡單說下分區分區要求:通常情況安裝系統是/boot; /; swap 三個分區。

序號

掛載點

容量

說明

1

/boot 

200M

作爲單獨的/boot系統引導區,即使主要的root分區出了問題,計算機依然能夠啓動。同時將容量調整爲200M,以備後用

2

swap

8G

交互分區,大小一般設定爲機器物理內存的1-2倍。

3

/

15G

是根目錄“/的所在地,啓動系統所須的文件和系統配置文件

5

/home

20G

用戶的home目錄所在地,用戶登錄分區,同時可以對用戶或者用戶分組實行硬盤限額功能,這樣當進行升級或者安裝新版本的linux操作系統時,就不會覆蓋原有的用戶登錄數據了。這個分區的大小取決於有多少用戶,根用戶可以很好地控制普通用戶使用計算機,如對用戶或者用戶組實行硬盤限量使用,限制普通用戶訪問哪些文件等。

6

/var

10G

主要存放系統日誌,設立單獨分區,即使系統日誌文件出現問題,也不影響系統主分區。也就不會使計算機崩潰。如WEB服務器,可分20GB或根據實際情況加大

7

/tmp

4G

存放臨時文件。對於多用戶系統或網絡服務器是有必要的。即使程序運行時生成大量的臨時文件,或用戶對系統進行了錯誤操作,文件系統的其它部分仍是安全的。因爲文件系統的這一部分仍然還承受着讀寫操作,所以它通常會比其它的部分更快地發生問題。

8

/u01

剩餘空間

存放數據庫文件,或同類的大量的數據文件

注:上表中的容量只是參考值,或者說是最小值,具體部署時要根據業務數據要求來調整容量。

3、將下面默認都進行安裝的組件都取消。原因:下面的組件經過確認都是不常用的組

件。其實下面的組件取消後,幾乎已經沒有會被安裝的組件了。

         4、計算機會自動開始安裝系統。 至此裸系統安裝完畢

一、設置網絡

1、使用setup命令,圖形化設置

201404071618001388.png

201404071618008109.png

201404071618005355.png

201404071618001862.png

設置完畢後,保存退出即可,如果需要設置DNS服務器地址,可以在下圖所示的“Edit

DNS configuration”處設置。

201404071618008109.png

2、使用命令行,手工錄入

命令行模式,要比圖形界面方便快捷,如下圖所示。輸入“vi /etc/sysconfig/network-

scripts/ifcfg-eth0” 即可對網卡1進行配置

201404071618003011.png

201404071618002671.png

示例說明:

               DEVICE                         設備名稱,禁止修改

               BROADCAST               廣播地址

               IPADDR                        IP地址

               NETMASK                    子網掩碼

               NETWORK                   網絡地址

               GATEWAY                     網關地址

               ONBOOT                      是否隨系統啓動

               TYPE                              網卡類型

201404071618008465.png

設置完成後,需要手工對網卡進行重新啓動。

 DNS地址設置路徑爲 /etc/resolv.conf ,這裏所說的DNS與我們要架設的DNS服務器的配置不一樣。這裏只是告訴系統DNS服務器的IP地址是多少而已。

201404071618005346.png

至此,裸系統安裝完畢,網絡也能夠連通了。配置yum需要外網的,如果在公司內部架設,不僅需要外網,還需要能夠不受行爲管理設備的控制。

二、設置yum

1、刪除Linux系統自帶的yum

201404071618002513.png

2、下載指定的yum安裝包,從下圖可以看出,yum-*yum-fastestmirror-*yum-metadata-parser*-這三個安裝包都是從http://centos.ustc.edu.cn/centos/5/os/x86_64/CentOS/ 下載得來的,還有就是需要注意,本次下載都是64的安裝包。32位的安裝包在這裏http://centos.ustc.edu.cn/centos/5/os/i386/CentOS/ 

201404071618004506.png

201404071618009357.png

201404071618009661.png

3、或者從其他機器複製安裝包,如果知道哪臺linux機器裏有上面所說的安裝包,linux之間互拷更快。示例只演示其中的一條拷貝命令,舉一反三,真的很好用,強烈推薦。

201404071618008384.png

示例說明:

               Scp                linux間互相拷貝的命令

               -r                    可以傳輸整個文件夾,沒有這個參數,只能拷貝單個文件

源文件在前,需指定絕對路徑,系統會補全,後邊同樣是絕對路徑,系統不能補全,只要指定需要複製到的文件夾即可

[email protected]:   root是目標主機有管理權限的賬戶,172.16.10.99是目標主機IP地址,ip地址前面的@符號和地址後邊的冒號必須有,命令格式如此,無解釋。

命令執行過程中,可能會讓你選擇yes或者no,個人理解應該是yes ,[email protected]'s password: 需要輸入的是目標主機的root賬戶的密碼。

另外需要注意的是,當同一個IP地址用在不同的linux主機上時,SCP會出現如下錯誤提示

201404071618003614.png

解決方法很簡單,進入 /root/.ssh/ 目錄下,rm - rf(刪除)掉 known_hosts 即可。

4、安裝yum安裝包

201404071618005269.png

如上圖所示,我們首先需要到安裝包所在位置才能使用rpm進行安裝,這個道理Windows也是一樣的。之所以用rpm –ivh yum-* 是因爲我這裏所要安裝的三個包有依賴關係,使用yun-* 系統自己就可以搞定了。

5、確認安裝信息

201404071618005740.png

6、下載源配置文件CentOS-Base.repo

201404071618007373.png

需要到上圖所示的路徑下載源配置文件,並且該配置文件需要放在 /etc/yum.repos.d/目錄下,千萬不要搞錯了哦。

201404071618005237.png

7、激活yum (看命令“i386”應該是32位的,但是激活後也可以用)

64位系統激活:rpm –import http://ftp.sjtu.edu.cn/centos/5/os/x86_64/RPM-GPG-KEY-CentOS-5

32位系統激活:rpm –import http://ftp.sjtu.edu.cn/centos/5/os/i386/RPM-GPG-KEY-CentOS-5

需要補充說明一下,複製上面的激活地址,import 前面是 兩個 --,最好是自己輸入

201404071618007553.png

8、更新yum

201404071618003082.png

更新的過程是個漫長的過程,根據網速可能需要10到15分鐘可能還會更長時間,不過好在系統會給你個動態的窗口顯示出來,讓你知道,系統還沒死,在活着。

9、清空yum緩存

201404071618002374.png

三、Sendmail 安裝

A、 RPM包安裝(推薦)

1、首先需要掛載光盤

201404071618001337.png

示例說明:

              cd /mnt                 切換到根目錄下的 mnt下面

              mkdir     cdrom    新建文件夾cdrom,這個目錄是爲了給光盤掛載的路徑,必須得有才行。

201404071618001922.png

        mount                  掛載的命令,無解釋

        iso9660                光盤

         -t                           掛載的類型還是什麼東東,忘了啥意思,反正掛載的時候需要

         /dev/cdrom         是光盤原位置,雷打不動,絕大部分都是用這個。光盤的話

        /mnt/cdrom         這是我們剛纔新設的掛載點,類似於Windows的文件夾。光盤內容就到這裏找。

2、Sendmail安裝

201404071618005996.png

示例說明:

               rpm –qa | grep sendmail 查詢sendmail是否安裝或者說已經安裝了哪些包

需要說明的是,上面顯示的是5個包,其中2個看上去以上,實際是1個32位、1個64位。

201404071618006859.png

示例說明:

    cd  /mnt/cdrom/Server           切換到/mnt/cdrom/Server目錄,其中Server是所有安裝包的位置

     rpm –ivh                                   rpm包的安裝方法,-ivh必須有

後邊跟的一長串不解釋,有大概名字之後,tab鍵可以補全這裏只演示了一個安裝包,另外四個用同樣的方法舉一反三

B、 YUM安裝

201404071618001127.png

示例說明:

     yum install         是yum安裝的命令,後邊跟上要安裝的包的名稱即可,yum會自動解決掉所有的包依賴性。方便!

C、 源碼安裝

1、編譯安裝準備

201404071618005813.png

卸載系統自帶的sendmail

201404071618008998.png

確認sasl是否已經安裝,如果沒有,需要重新安裝一下sasl

201404071618004307.png

掛載光盤

201404071618002011.png

201404071618006715.png

201404071618006318.png

201404071618001022.png

201404071618005003.png

201404071618007318.png

2、下載源碼包

201404071618008713.png

通過官方服務器下載:wget ftp://ftp.sendmail.org/pub/sendmail/sendmail.8.14.6.tar.gz

示例說明:

        [root@sendmail ~]#   根據此提示,下載後的root賬戶的家目錄下。以root賬戶登錄,cd後就是家目錄,其他賬戶以此類推,或者在下載前,pwd,看下自己處在哪個目錄下面。

3、解壓tar.gz包

201404071618003797.png

201404071618001097.png

示例說明:

          tar –zxvf              不要搞錯,解壓後的在同級目錄下面,會有個sendmail.8.14.6 的子目錄4、編譯源碼

201404071618008107.png

201404071618005332.png

備份site.config.m4.sample文件至此,三種不同方式的安裝方式都介紹結束,在linux不太熟悉

情況下,類似我這樣的,可以使用rpm安裝或者yum安裝。編譯不太建議!!

四、Sendmail配置

其實Sendmail的需要配置的內容真的不是很多,/etc/mail/access /etc/mail/sendmail.mc

這兩個文檔之外貌似就只有/etc/hosts 了。下面逐一截圖說明一下需要修改的地方。

       1、/etc/mail/access

201404071618001694.png

201404071618008076.png

示例說明:

                            vi /etc/mail/access 使用vi編輯器打開/etc/mail/access

                            Connect:17.16 RELAY轉發來自172.16.0.0網段的所有郵件

修改完成後,需要使用makemap hash將access轉換爲access.db

201404071618005542.png

       2、/etc/mail/sendmail.mc

201404071618004959.png

如果在m4的時候出現上圖這樣的錯誤,是因爲沒有安裝sendmail-cf,通過yun安裝一下就可以了

201404071618007396.png

       3、/etc/hosts

本次配置,該文檔不用修改:

1、重啓sendmail服務並測試sendmail發送

重啓sendmail

201404071618000668.png

測試sendmail發送郵件

201404071618009328.png

示例說明:

                      helo                     與sendmail服務器連接,後邊的ddd 隨便輸入都可以

                      mail from:          發件箱,同樣可以隨便寫,Sender ok 表示成功

                      rcpt to:                 收件箱                              Recipient ok 表示成功

                      data                     郵件正文開始,換行 .表示結束

                      quit                      退出發件狀態

2、設置sendmail隨系統自動啓動

201404071618003715.png

示例說明:

              -bd         表示將sendmail你daemon(可以想成常駐內存)的類型啓動

              -q           後邊跟着時間表示每隔多少時間,會將放置在郵件隊列(一般在/var/spool/mqueue)的郵件嘗試郵寄一次。

3、遠程客戶端測試

類似於本章節步驟4,只需要在非sendmail服務器本機上的其他機器,通過telnet

172.16.10.99  25 測試即可,具體細節與步驟4一致。

五、自定義Mail Filter

A、 安裝GCC

1、檢查gcc的安裝情況:

201404071618000240.png

示例說明:

上圖的命令在安裝sendmail的時候解釋過,這裏飄過

圖示中的兩個libgcc不是我們要的,所以要在下一個步驟通過yum安裝。

2、通過yum安裝gcc:

201404071618009519.png

201404071618002598.png

示例說明:

當出現gcc-4.1.2-54.el5時表示已經安裝上去,同事也滿足需求了。

3、通過rpm包安裝:

gcc的安裝依賴5個不同的安裝包,本操作不方便,建議yum安裝。

B、 編譯sendmail

1、下載sendmail

本部分在第三章節第三小節裏有介紹,本段跳過

2、解壓sendmail

本部分在第三章節第三小節裏有介紹,本段跳過

3、

C、 編譯libmilter

1、sh Build

201404071618002432.png

示例說明:

多個目錄下都有Build,一定要看清楚再運行 sh Build ,以免對後續操作造成影響。當出現下圖

所示時,表示命令已經完成。

201404071618012875.png

2、sh Build install

201404071618018298.png

3、find  /-name libmilter.a

201404071618016036.png

201404071618013876.png

示例說明:

對照上圖的路徑,執行上圖的命令,對照上圖的結果,無誤表示運行成功。無其他解釋。

D、編譯libsm

1、sh Build

201404071618019477.png

示例說明:

出現上圖結果,表示已經運行成功!

2、find /-name libsm.a

201404071618016036.png

201404071618016958.png

示例說明:

對照上圖輸入命令,對照上圖查看執行情況,無解釋。

E、新建mliter

1、新建mliter

201404071618014220.png

示例說明:

在root家目錄下新建子目錄mliter

2、拷貝libmilter.a 和 libsm.a 以及 libmilter 目錄

201404071618011695.png

201404071618019805.png示例說明:

               Linux的基本命令,主要用於複製粘貼,源文件在前,目標文件在後。

下面截圖用的 /* 表示該目錄下的所有文件都在複製粘貼的範圍之內。

3、新建sample.c文件

201404071618013606.png

示例說明:

               sample.c 文檔的源碼在附件一中。

F、配置加載Filter文件(最爲關鍵

201404071618012139.png

示例說明:

上句命令是指通過sample.c libmitler.a libsm.a 生成一個新的sample程序文件

201404071618015509.png

201404071618017485.png

201404071618013862.png

G、啓動Fiter(關鍵步驟

201404071618016922.png

示例說明:

       ./sample                     是/root/mliter目錄下面的一個程序,是上一個步驟生成的。

       9876@localhost        是在上一個步驟新增的端口(9876)監聽,在文擋/etc/mail/sendmail.mc的最後一行

                       &                                在後臺運行

H、測試Filter(關鍵步驟

1、測試Filter是否成功,需要首先在/root/mliter目錄下新增一個類似於白名單的whiteuser.list,該文件裏面的內容如下截圖所顯示,每個授權外發郵箱新增一行。沒有的郵箱只能發公司內部郵箱或者goldendragobus.com。

201404071618012790.png

示例說明:

每個郵箱地址一行

3、在測試前完成添加whiteuser.list名單後,同時開啓兩個ssh窗口,一個運行

201404071618016922.png 另一個窗口則是通過telnet localhost 25 的方式發送郵件,分別測試白名單內有的郵箱地址和白名單內沒有的地址。當出現下圖所示,即表示fiter測試成功201404071618011964.png

201404071618016331.png

示例說明:

以上兩個截圖,是在不同的SSH窗口同時顯示出來的結果。

測試過程中,如果出現意外導致linux長時間無響應,可以通過如下命令殺死相關進程。

201404071618016130.png

至此,Sendmail的配置全部結束。後邊的附件一位sample.c的源碼,附件二爲一些服務器優化數據,僅供參考。

六、遠程控制SSHD配置

這裏說明一下,本段配置之選擇了設置於sendmail.xmjl.com這臺服務器上的功能選項,更多細節,參考Redhat Linux 5 x64 SSHD配置

1、備份sshd_config配置文件

201404071618014328.png

201404071618016607.png

示例說明:

       pwd              查看當面所處目錄

       cp                 備份,前部分爲源文件,後部分爲目標文件

需要注意的是,在/etc/ssh 目錄下還有另外一個類似於 sshd_config的 文件ssh_config,在編輯的時候一定要注意,不要搞錯了。

2、配置sshd_config

201404071618016147.png

示例說明:

              port                                SSHD開放端口

              protocol                        SSHD所使用的協議版本,一般用版本2

              listenaddress              這裏只能單個多行添加IP地址,不能添加網段。

201404071618016263.png

示例說明:

              Logingracetime          登錄時不輸入密碼的等待時間

              Permitrootlogin no     表示禁止root賬戶直接通過sshd登陸,yes表示可以

              Maxauthtries                忘了啥意思了,反正這裏配置了

七、防火牆iptables配置

這裏說明一下,本段配置之選擇了設置於sendmail.xmjl.com這臺服務器上的功能選項,更多細

節,參考Redhat Linux 5 x64 iptables配置

201404071618017291.png

              Iptables的所有策略都保存在/etc/sysconfig/iptables裏,修改完畢後直接重啓iptables即可生效。

201404071618019041.png

示例說明:

              #                   註釋此條策略,不使其生效

拒絕所有流入本機的數據

拒絕所有通過本機轉發的數據

允許所有流出本機的數據

允許172.16.28.0/24網段使用tcp協議通過eth0網口以目的端口爲56088的數據進入本機

允許172.16.28.0/24網段使用udp協議通過eth0網口以目的端口爲56088的數據進入本機

允許使用tcp協議通過eth0網口以目的端口爲25的數據進入本機

允許使用udp協議通過eth0網口以目的端口爲25的數據進入本機

允許使用tcp協議通過eth0網口以源端口爲53的數據進入本機

允許使用tcp協議通過eth0網口以目的端口爲53的數據進入本機

允許使用icmp協議(俗稱ping)通過eth0網口的數據進入本機

允許使用icmp協議(俗稱ping)通過eth0網口的數據進入本機

              ……………….

允許所有的數據流出本機

如果想看到iptables是否已經生效,可以通過下面命令查看

201404071618017435.png

示例說明:

              -L                          查看當前表的所有規則,默認查看的是filter表

              --line-nu              顯示帶有序號的防火牆策略

201404071618016615.png

示例說明:

1、允許172.16.28.0/24段IP地址通過tcp協議目的端口56088流量進入eth0網口

2、允許172.16.28.0/24段IP地址通過udp協議目的端口56088流量進入eth0網口

3、允許通過tcp協議目的端口25流量進入eth0網口

4、允許通過udp協議目的端口25流量進入eth0網口

5、允許通過udp協議源端口53流量進入eth0網口

6、允許通過udp協議目的端口53流量進入eth0網口

7、允許通過icmp 協議(俗稱ping)流量進入本機

8、允許通過icmp協議(俗稱ping)流量進入本機

。。。。。。。。

9、拒絕通過本機轉發的所有數據流量

10、允許通過本機流出的所有數據流量

有時候iptables未能生效,service iptables restart 也不行,這樣就需要重啓系統了。

八、安全管控

1、/etc/hosts.deny配置

由於sshd只能逐行添加IP地址,在生產環境中操作非常不便,所以在這裏通過服務器系統層面來管控可以接入這臺服務器的IP地址。建議如此,比較好用!

201404071618016802.png

201404071618011485.png

201404071618012356.png

示例說明:

              pwd                     查看

              cp                        複製文檔

              vi                          編輯文檔

最後一行的意思是允許172.16.28.0/255.255.255.0 網段的主機通過sshd連接服務器,除此之外的所有IP地址全部拒絕。

2、/etc/services配置

本文檔可以修改各個服務默認的端口號信息,本次配置修改了sshd的默認端口號,所以在iptables裏,本來是要顯示dport是56088的,因爲修改後,變成了sshd了。

201404071618014644.png

201404071618018954.png

九、sendmail日常維護

1、查看隊列

#mailq      查看MTA隊列的滯留情況(等價於sendmail -bp)     

#mailq -Ac  查看MSP隊列的滯留情況(等價於sendmail -bp -Ac)

2、強制發送隊列郵件

#/usr/sbin/sendmail -q -v                  對MTA隊列強制送信

#/usr/sbin/sendmail -q -v -Ac               對MSP隊列強制送信

3、郵件日誌

#tail –f /var/log/maillog實時查看linux日誌

#tail -1000 /var/log/maillog查看linux日誌的最後1000行

#cat /var/log/maillog | grep ‘[email protected]’查看與某個指定賬戶有關的記錄

#egrep ‘[email protected]|[email protected]’ /var/log/maillog 以兩個關鍵詞來查詢日誌

附件一:sample.c 源碼

#include <sys/param.h>

#include <netinet/in.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <sysexits.h>

#include <string.h>

#include <time.h>

#include "mfapi.h"

#include "mfdef.h"

#define MAXADDRESS 128

#define MAXHEADER 1024

#define MAXHEADERS 32

#define MAXIP      16

#define MAXRCPTS   32

#define TMPPATH    "/tmp/exfiXXXXXX"

FILE *fp;

struct private {

        int nhdrs;

        int nrcpts;

        int fd;

        FILE *fp;

        char *jobid;

        char tf[MAXPATHLEN];

        char host[MAXHOSTNAMELEN];

        char ip[MAXIP];

        char sender[MAXADDRESS];

        char hdrs[MAXHEADERS][MAXHEADER];

        char rcpts[MAXRCPTS][MAXADDRESS];

};

/*

 * Copy src to string dst of size siz. At most siz-1 characters

 * will be copied. Always NUL terminates (unless siz == 0).

 * Returns strlen(src); if retval >= siz, truncation occurred.

 */

size_t strlcpy(dst, src, siz)

char *dst;

const char *src;

size_t siz;

{

        register char *d = dst;

        register const char *s = src;

        register size_t n = siz;

        /* Copy as many bytes as will fit */

        if (n != 0 && --n != 0) {

                do {

                        if ((*d = *s ) == 0)

                                break;

                } while (--n != 0);

        }

        /* Not enough room in dst, add NUL and traverse rest of src */

        if (n == 0) {

                if (siz != 0)

                        *d = '\0';      /* NUL-terminate dst */

                while (*s )

                        ;

        }

        return(s - src - 1);    /* count does not include NUL */

}

int exfi_connect(SMFICTX *ctx, char *host,

                 _SOCK_ADDR *addr)

{

        struct private *prv;

        struct sockaddr *sa;

        prv = malloc(sizeof *prv);

        if (prv == NULL)

                return SMFIS_TEMPFAIL;

        memset(prv, '\0', sizeof *prv);

        prv->fd = -1;

        smfi_setpriv(ctx, prv);

        strlcpy(prv->host, host,

                sizeof prv->host);

        /*sa = addr;

        if (sa != NULL &&

            sa->sa_family == AF_INET) {

                struct sockaddr_in *sin;

                sin = addr;

                strlcpy(prv->ip,

                        inet_ntoa(sin->sin_addr),

                        sizeof prv->ip);

        }

*/

        fp = fopen("/tmp/mail.log","a ");

        if(fp) {

                time_t rec_time;

                time(&rec_time);

                fprintf(fp,"%s hostname: %s    ip_address: %s \r\n", ctime(&rec_time),prv->host,prv->ip);

                printf("%s hostname: %s        ip_address: %s \r\n", ctime(&rec_time),prv->host,prv->ip);

        }

        return SMFIS_CONTINUE;

}

int exfi_envfrom(SMFICTX *ctx,

                 char **args)

{

        struct private *prv;

        prv = smfi_getpriv(ctx);

        strlcpy(prv->sender,

                args[0],

                sizeof prv->sender);

        prv->jobid =

            smfi_getsymval(ctx, "i");

        prv->nrcpts = 0;

        prv->nhdrs = 0;

        prv->fd = -1;

        return SMFIS_CONTINUE;

}

char *substr_right(char *dst,char *src, int n)

{

    char *p = src;

    char *q = dst;

    int len = strlen(src);

    if(n>len) n = len;

    p = (len-n);

    while(*(q ) = *(p ));

    return dst;

}

int user_check(char *usermail)

{

        FILE *fp;

        fp = fopen("whiteuser.list", "r");

        if(fp == NULL) {

                return 0;

        }

        fseek( fp , 0 , SEEK_END );

        int file_size;

        file_size = ftell( fp );

        if(file_size<=0)

                return 0;

        char *filetmp;

        fseek( fp , 0 , SEEK_SET);

        filetmp = (char *)malloc( file_size * sizeof( char ) );

        fread( filetmp , file_size , sizeof(char) , fp);

        char *p;

        p=strstr(filetmp,usermail);

        if(p) {

                /*printf("user check sucess!%s",p);*/

                return 1;

        }

        else {

                /*printf("user check fail!");*/

                return 0;

        }

//2013-07-13 newadd “free(filetmp);”

              free(filetmp);

//2013-07-13 end

        fclose(fp);

}

int indexOf(char *str1,char *str2)

{

        char *p=str1;

        int i=0;

        p=strstr(str1,str2);

        if(p==NULL)

                return -1;

        else {

                while(str1!=p) {

                        str1 ;

                        i ;

                }

        }

        return i;

}

void trim_char(char s[],int c)

{

        int i,j;

        for (i = 0, j = 0; s[i] != '\0'; i ) {

                if (s[i] != c) {

                        s[j ] = s[i];

                }

        }

        s[j] = '\0';

}

int exfi_envrcpt(SMFICTX *ctx, char **args)

{

        char mail_passerver1[50]="@goldendragonbus.com";

        char mail_passerver2[20]="@test.com";

        char mail_buf[50];

        char send_user[50];

        struct private *prv;

        prv = smfi_getpriv(ctx);

        if (prv->nrcpts >= MAXRCPTS)

                return SMFIS_TEMPFAIL;

        strlcpy(prv->rcpts[prv->nrcpts],

                args[0],

                sizeof prv->rcpts[prv->nrcpts]);

        int rcpt_len=strlen(prv->rcpts[prv->nrcpts]);

        int e_pos=indexOf(prv->rcpts[prv->nrcpts],"@");

        strncpy(mail_buf,prv->rcpts[prv->nrcpts] e_pos,rcpt_len);

        trim_char(mail_buf,'>');

        strlcpy(send_user,prv->sender,sizeof send_user);

        trim_char(send_user,'<');

        trim_char(send_user,'>');

        /*printf("send_user:%s\r\n",send_user);*/

        /*printf("rcpt :%s,lenth is:%d,pos is:%d,mail_buf is:%s\r\n" ,prv->rcpts[prv->nrcpts],rcpt_len,e_pos,mail_buf);*/

        int sender_check= user_check(send_user);

        if(strcasecmp(mail_buf,mail_passerver1)!=0 && sender_check==0)

        {

                if(fp) {

                        fprintf(fp," sender:%s reciver[%d] is : %s     send Fail!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                        printf(" sender:%s     reciver[%d] is : %s     send Fail!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                }

                return SMFIS_REJECT;

              //return SMFIS_TEMPFAIL;

        }

        if(fp) {

                fprintf(fp," sender:%s reciver[%d] is : %s     send Sucess!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

                printf(" sender:%s     reciver[%d] is : %s     send Sucess!\r\n", prv->sender,prv->nrcpts,prv->rcpts[prv->nrcpts]);

        }

        prv->nrcpts ;

        return SMFIS_CONTINUE;

}

int exfi_close(SMFICTX *ctx)

{

        struct private *prv;

        prv = smfi_getpriv(ctx);

        free(prv);

        smfi_setpriv(ctx, NULL);

        if(fp) {

                fclose(fp);

        }

        return SMFIS_CONTINUE;

}

struct smfiDesc filter = {

        "Example Filter",

        SMFI_VERSION,

        SMFIF_ADDHDRS,

        exfi_connect,

        NULL,

        exfi_envfrom,

        exfi_envrcpt,

        NULL,

        NULL,

        NULL,

        NULL,

        NULL,

        NULL

};

int main(int argc, char **argv)

{

        if (argc != 2) {

                fprintf(stderr,

                        "usage: %s socket\n",

                        argv[0]);

                return EX_USAGE;

        }

        smfi_setconn(argv[1]);

        smfi_register(filter);

        if (smfi_main() == 0)

                return EX_OK;

        else

                return EX_OSERR;

}

附錄二:批量執行腳本

A、 單臺轉發

併發數量

郵件處理

50

正常

80

正常

100

失敗

因爲我們的環境是單臺服務器的轉發,所以併發數量爲80個數量左右,而郵件服務器,

正常是由隊列發出的,郵件服務器domino需要控制併發發送的數量。

B、 多臺轉發

併發數量

郵件處理

20

正常

30

正常

50

失敗

爲了測試,在2臺客戶端機器上執行該腳本,在2臺客戶端上上執行,如果循環50次的話,會出現內存問題,而退出過濾條件,而穩定在30個循環,即併發數量在每秒50個郵件左右。後續需要改進程序,加強效率。

附錄三:SMTP交互指令說明

SMTP基本命令集:

命令

描述

HELO

向服務器標識用戶身份

MAIL

初始化郵件傳輸 mail from:

RCPT

標識單個的郵件接收人;常在MAIL命令後面,可有多個rcpt to:

DATA

在單個或多個RCPT命令後,表示所有的郵件接收人已標識,並初始化數據傳輸,以.結束

QUIT

結束會話

MAIL FROM

命令中指定的地址是稱作envelope from地址,不需要和發送者自己的地址是一致的

RCPT TO

與之等同,指明的接收者地址稱爲envelope to地址,而與實際的to:行是什麼無關

現在的SMTP服務器一般都需要身份驗證,下面是一個telnet發送郵件的例子:

C:\>telnet smtp.163.com 25    //登陸 smtp.163.com 端口號爲 25

220 163.com Anti-spam GT for Coremail System(163com[071018])

HELO localhost // 與服務器打招呼,並告知客戶端使用的機器名字,可以隨便填寫

250 OK 

AUTH LOGIN  //使用身份認證登陸指令

334 dXNlcm5hbWU6

cmVkc25zMw== //輸入base64_encode()過的用戶名,只輸入用戶名,不需要帶@163.com

334 UGFzc3dvcmQ6

MbM2MMQ35Q== //輸入base64_encode()過的密碼

235 Authentication successful

MAIL FROM:<[email protected]//告訴服務器發信人的地址,必須和前面輸入的用戶名一致。

附錄四:自動發送腳本

A、 腳本代碼

                          [root@Sendmail ~]# vi telnet.sh

#!/usr/bin/expect

set smtp    [lindex $argv 0]

set from    [lindex $argv 1]

set to      [lindex $argv 2]

set title   [lindex $argv 3]

set content [lindex $argv 4]

spawn telnet $smtp 25

expect "220"

send "HELO xinhua.org\r"

expect "250 OK"

send "MAIL FROM: $from\r"

expect "250 Mail OK"

send "RCPT TO: $to\r"

expect "250 Mail OK"

send "DATA\r"

expect "354"

send "TO: $to\r"

send "FROM: $from\r"

send "SUBJECT: $title\r"

send "\r"

send "$content\r"

send ".\r"

expect "250"

send "QUIT"

B、 腳本測試(stmp的意義參考附錄三)

[root@Sendmail ~]# ./telnet.sh  localhost [email protected] [email protected] subjects content spawn  telnet  localhost  25

Trying 127.0.0.1...

Connected to localhost.localdomain (127.0.0.1).

Escape character is '^]'.

220 localhost.localdomain ESMTP Sendmail 8.14.6/8.13.8; Wed, 27 Feb 2013 16:14:40 0800

HELO xinhua.org

250 localhost.localdomain Hello localhost.localdomain [127.0.0.1], pleased to meet you

MAIL FROM: <[email protected]>

250 2.1.0 < [email protected] >... Sender ok

RCPT TO: [email protected]

250 2.1.5 [email protected]... Recipient ok

DATA

354 Enter mail, end with "." on a line by itself

TO: [email protected]

FROM: [email protected]

SUBJECT: subjects

content

.

250 2.0.0 r1R8EeNW025980 Message accepted for delivery

附錄五:批量發送腳本

                     [root@xml-ora1 ~]# vi parasend.sh

#!/bin/sh

for((i=0;i<50;i ));do

{

echo "$i send start `date` pid:$!.";

echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content`

echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content$i`

echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content`

echo `./telnet.sh 172.16.28.127 [email protected] [email protected] subjects$i content$i`

echo 1>> aa && echo "$i send complete `date` pid:$!.";

} &

done

wait

cat aa | wc -l

rm aa



 原文轉載自:http://www.pangshayu.com/html/8366.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章