寻找严肃、沉默和专注的力量。
分类: 服务器与存储
2013-02-22 15:16:42
本文主要说明了通过Sendmail+Dovecot+Openwebmail+procmail搭建邮件服务器的方法,并包括简单的备份策略和一个上传备份邮件的程序MailUpload。
Sendmail实现协议,是邮件传输代理程序,作为发送邮件服务器。
Dovecot 是一个开源的 和 邮件服务器,支持 Linux/Unix 系统,作为接收邮件服务器。
Openwebmail是一个perl语言编写的web邮件系统。
Procmail是一个可以自定义的强大的邮件过滤工具。
操作系统:more /etc/redhat-release 显示:Red Hat Enterprise Linux Server release 6.3 (Santiago)
第52、53行:
dnl TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN’)dnl
dnl define(`confAUTH_MECHANISMS’, `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
改成
TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN’)dnl
define(`confAUTH_MECHANISMS’, `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
(去掉前面的dnl)
第116 行:
DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
改成
DAEMON_OPTIONS(`Port=smtp,Addr=0.0.0.0, Name=MTA')dnl
( 将127.0.0.1改成0.0.0.0)
其中dnl是配置文件中的m4宏,它表示丢弃直到下一个换行为止的字符(包括那个换行符)的意思。这里sendmail.mc文件修改的第一处如果不修改的话,后面发送邮件会发送失败;第二处如果不改动话系统只监听本机的127.0.0.1这个lo接口,修改之后将监听的接口开启到整个internet上,否则无法接收来自Internet的信件。
sendmail.mc是模板文件,sendmail.cf才是真正的配置文件,但是sendmail.cf配置文件比较复杂,一般不直接修改sendmail.cf文件而是通过sendmail.mc文件来生成sendmail.cf文件。sendmail.mc文件修改好之后,通过
m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf命令来生成sendmail.cf文件
sendmail.cf文件生成之后,直接启动sendmail服务的话,会报错,提示sendmail.cf文件第39行有错误。定位到39行之后,发现其实第39行就是一空行,直接删掉该行即可。
如果要收到形如xxx@abc.com、abc@mail.hzly.com的邮件的话,就要设置正确的主机名,主机名的设置在/etc/mail/local-host-names文件里添加:
mail.hzly.com
配置文件设置完毕后,即可启动sendmail服务了,用service sendmail start命令来启动
修改邮箱位置,如果不修改的话,后面在发邮件的时候会提示跟mail_location相关的错误,修改操作如下:
第25行:
# mail_location = mbox:~/mail:INBOX=/var/mail/%u
修改成
mail_location = mbox:~/mail:INBOX=/var/mail/%u
(去掉前面的#号)
修改是否允许简单信息验证,如果不修改的话,后面发邮件会提示验证错误而不能通过验证,操作如下:
第9行:
#disable_plaintext_auth = yes
修改成
disable_plaintext_auth = no
(去掉前面的#号,将yes改成no)
修改是否使用ssl验证,如果不修改的话,同样在发送邮件的时候会提示不能通过验证,操作如下:
第6行:
#ssl = yes
修改成
ssl = no
(去掉前面的#,yes改成no)
用useradd 用户名(如useradd userone)添加用户,用passwd 用户名(如 passwd userone)来修改密码,这样就添加了一个叫userone的用户。
添加用户之后,需要在用户目录下建立INBOX文件夹,否则后面在收信的时候会报错。切换到userone用户下,然后用mkdir /home/userone/mail/.imap/INBOX -p命令创建文件夹。
为了方便避免每新建一个用户就要建一个INBOX文件夹,可以在/etc/skel/.bash_profile文件中添加脚本来自动建立INBOX文件夹,如下所示:
在末尾添加:
if [ ! -d ~/mail/.imap/INBOX ];then mkdir -p ~/mail/.imap/INBOX fi
配置文件修改完毕后,就可以启动dovecot服务了。用service dovecot start命令启动。
sendmail和dovecot都安装完毕,服务都启动好了之后,这时一个基本的邮件服务器搭建完成,可以用foxmail客户端来进行连接。
openwebmail的rpm包可以到上下载,同样,openwebmail安装是也有依赖关系,它是依赖如下两个包:perl-Text-Iconv-1.7-6.el6.x86_64.rpm和perl-suidperl-5.10.1-119.el6_1.1.x86_64.rpm,因此要先安装这两个包后才能安装openwebmail,当然运行openwebmail还需要perl环境,一般系统都默认安装了perl环境,如果没有安装就要先装perl环境了。
在初始化之前要修改/var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf这个配置文件,如果不修改该文件的话,在后面运行openwebmail-tool.pl --init初始化的时候会报错,修改如下:
第30行:
dbm_ext .db
修改成
dbm_ext .pag
安装好了之后,修改dbm.conf配置文件之后,就开始初始化,输入/var/www/cgi-bin/openwebmail/openwebmail-tool.pl --init命令进行初始化操作
初始化之后,还需要修改/var/www/cgi-bin/openwebmail/etc/openwebmail.conf文件,主要是修改openwebmail的语言以及邮件使用的域名修改如下:,
第62行:
修改为zh_CN.GB2312
第85行:
修改为Cool3D.Chinese.Simplified
第12行:
修改为邮件使用的域名
修改/var/www/cgi-bin/openwebmail/etc/defaults/openwebmail.conf
第26行:
smtpserver要改为相应的主机名或ip
安装好openwebmail之后,就可以启动http服务来访问了。需要注意的是,openwebmail是依赖于http服务的,所以服务器必须要安装http服务才行。如果httpd装好了,只需要用service httpd start命令启动即可。
在访问openwebmail之前,需要disable系统的SELinux设置。
打开浏览器,在浏览器中输入:
即可访问openwebmail了。
首先确定系统已安装procmail。
mkdir /etc/procmail
touch /var/log/procmail.log
mkdir /var/mail/backup
MAILDIR=/var/mail VERBOSE=off PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin LOGFILE=/var/log/procmail.log INCLUDERC=/etc/procmail/rc.localcopy
:0c /var/mail/backup/
收发的邮件就会备份到/var/mail/backup/目录下面,里面还有子目录,具体可以看一下
MailUpload是一个可以将备份的邮件上传到指定服务器的小程序,服务器端通过一个jsp解析出主题和内容,然后插入数据库以供查询。下面贴出MailUpload的代码,主要是监测指定目录的文件变化情况,然后通过curl提交数据。
#include#include #include #include #include #include #include #define ERROR(text) error(1, errno, "%s", text) struct EventMask { int flag; const char *name; }; int freadsome(void *dest, size_t remain, FILE *file) { char *offset = (char*)dest; while (remain) { int n = fread(offset, 1, remain, file); if (n==0) { return -1; } remain -= n; offset += n; } return 0; } int main(int argc, char *argv[]) { const char *target; if (argc == 1) { target = "."; } else { target = argv[1]; } struct EventMask event_masks[] = { {IN_ACCESS , "IN_ACCESS"} , {IN_ATTRIB , "IN_ATTRIB"} , {IN_CLOSE_WRITE , "IN_CLOSE_WRITE"} , {IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE"} , {IN_CREATE , "IN_CREATE"} , {IN_DELETE , "IN_DELETE"} , {IN_DELETE_SELF , "IN_DELETE_SELF"} , {IN_MODIFY , "IN_MODIFY"} , {IN_MOVE_SELF , "IN_MOVE_SELF"} , {IN_MOVED_FROM , "IN_MOVED_FROM"} , {IN_MOVED_TO , "IN_MOVED_TO"} , {IN_OPEN , "IN_OPEN"} , {IN_DONT_FOLLOW , "IN_DONT_FOLLOW"} , //{IN_EXCL_UNLINK , "IN_EXCL_UNLINK"} , {IN_MASK_ADD , "IN_MASK_ADD"} , {IN_ONESHOT , "IN_ONESHOT"} , {IN_ONLYDIR , "IN_ONLYDIR"} , {IN_IGNORED , "IN_IGNORED"} , {IN_ISDIR , "IN_ISDIR"} , {IN_Q_OVERFLOW , "IN_Q_OVERFLOW"} , {IN_UNMOUNT , "IN_UNMOUNT"} , }; int monitor = inotify_init(); if ( -1 == monitor ) { ERROR("monitor"); } int watcher = inotify_add_watch(monitor, target, IN_ALL_EVENTS); if ( -1 == watcher ) { ERROR("inotify_add_watch"); } FILE *monitor_file = fdopen(monitor, "r"); char last_name[1024]; char name[1024]; /* event:inotify_event -> name:char[event.len] */ //while (true) { while (1) { struct inotify_event event; if ( -1 == freadsome(&event, sizeof(event), monitor_file) ) { ERROR("freadsome"); } if (event.len) { freadsome(name, event.len, monitor_file); } else { sprintf(name, "FD: %d\n", event.wd); } if (strcmp(name, last_name) != 0) { puts(name); //int ret = system("ls -l"); strcpy(last_name, name); } /* 显示event的mask的含义 */ int i; for (i=0; i