Qmail短信提醒
m}…………………?…
实用第一智慧密集
,.…………j!…?…
Qmai1短稿提l腥lt
:
金掷|
摘要在EDI电子报文流转的过程中,及时准确地接收和处理报文对港口生产来说至关
重要.为了方便EDI用户及时得到新邮件的到达提醒,收取和处理报文邮件,本 文介绍了在Linux+Qmail环境下,采用C语言和Java语言,实现新邮件到达时向
用户发送短信提醒的过程.此
在连云港港口EDI中心得到了实际应用,取得 了良好的效果.
关键词EDI,Qmail,EPS,报文,短信提醒
一
,引言
Qmail是DanBernstein开发的可以自由下载的一个因特网 邮件传送代理,它运行在Unix兼容系统下,是一个直接代替U— NIX下Sendmail软件的邮件传送程序,其第一个beta版本0.7 发布于1996年1月24日,1997年2月发布了1.0版,当前版 本是1.03.Qmail使用简单报文传送代理协议SMTP传输邮件 (SimpleMailTransferProtoco1),具有良好的安全性和可靠性, 支持虚拟域管理.
在EDI中心的实际报文流转过程中,Qmail系统应用效果 良好.但由于口岸用户对报文的实时性要求较高,存在一些需 要改进的地方:
1.报文业务量较少的用户采用的是邮件接收方式来接收 EDI报文,当新报文邮件到达时需要即时得到通知. 2.邮件到达通知需要过滤,只有报文邮件才需要发送短 信提醒.
本文正是基于上述用户的实际需求,提供了这样一个在 Linux环境中将Qmail与短信平台结合起来实现新邮件到达提 醒的完整的解决方案.
二,实现技术
1.Qmail新邮件到达的接管
Qmail新邮件到达时,会按照Qmail的邮件流转流程写入 接收用户的
中.如图1所示.
在整个邮件流转的流程中,最后一个进程是programdeliv— ery,它负责将邮件写入目标用户的邮件目录中.在Qmail 中,这个进程是由/h0me/vpopmail/d0mains/easid0.com/
.
qmail—default文件中的命令确定的.缺省的命令如下: /home/vpopmail/bin/vdelivermailbounce—no—mailbox Qmail系统将上一个进程处理过的邮件句柄通过管道传递给 vdelivermail来处理.
一嚣与lI|
图1
为了得到新邮件的发送者,接收者,发送时间,主
,附 件信息等相关信息,我们需要在此处接管,插入我们的程序模 块来截取相关的信息,然后再交由vdelivermail继续处理. 2.原始邮件内容及其分析
……*
眦删ORK&C0啊MUNIC盯
ION…………………………………………………………………………………
接收到原始邮件数据后,需要对原始数据进行分析和分
解,以便取得From,To,CC,Subject,Attachments等数据. 因为邮件原始数据是以编码形式传输的,所以需要对邮件数据 进行解析.此处使用EPS所提供的基础库函数进行解析.EPS 提供了面向C语言的解析函数,可以将邮件中的主题,附件文 件名等数据解析到预定义好的数据结构中去.
得到邮件的发送方,接收方,主题以及附件文件名之后, 就可以按照我们自己设定的过滤
,进行初步过滤:凡是不 符合我们制定的规则的邮件,被认为是恶意的垃圾邮件,可以 直接丢弃,不再向下一个环节传递.
正常的邮件则通过TCP连接到我们的邮件提醒监听服务程 序,将此邮件的主题,接收方,抄送方,邮件到达时间写入邮 件提醒服务的数据库中,等待短信系统来处理发送. 这部分程序使用C语言编写,在LinuxAS3上编译后嵌入 Qmail系统,作为短信提醒系统的客户端部分.
3.短消息的发送
(1)短信提醒系统的服务端程序是用Java编写的,提供 了TcpSocketlistener,用来监听邮件服务器的短信连接请求. (2)客户端连接上之后,将邮件相关信息发送至服务 器.
(3)服务器解析邮件主题,然后匹配接收方邮箱地址, 得到用户的移动终端设备号码MSISDN.
(4)将上述
得到的完整的短信数据作为任务,写入 短信系统的任务队列中.
(5)短信系统将此任务发送至用户的移动终端设备上. 三,方案设计
1.设计模型
图2所示的各个组成模块描述如下:
Milterproject,qmailfilterintegration Qmai!MyFi|terSMSplatform
l卜
l:燮!}l一————__I
宦
<>.—:\.
\/,,之芝/
llMqalld—i~,'llII;
0
lSMSPiatf~m{
图2
(1)DelieryScript:是Qmail邮件系统新邮件处理流程的最 后环节,也是本方案的处理流程入口.通过修改/home/vpop— mail/domains/easido.com/.qmail—default配置文件,使用编译 后的myfilter程序代替原来的vdelivermail程序接管原始邮件信 息.
(2)EmailParsing:解析原始邮件信息,获得Subject/From/ To/AttachmentFileName等数据.
(3)FilterInit:从配置文件中读取过滤条件,初始化过滤 器.
(4)FilterComparison:将(2),(3)步骤中得到的数据进行对 比,置accepted标志.
(5)SMSSender:负责将邮件主题,发送方,接收方等数据 发往短信平台,本方案中只发送通过filter校验的正常邮件信 息.
(6)SMSPlatform:短信平台,将短消息发送至移动通信用 户的接收终端.
(7)DeliveryProgram:缺省的Qmail系统的邮件落地处理程 序.本方案中将通过filter校验后的正常邮件交给DeliveryPro— gram处理,送入用户邮箱目录.
2.部分代码
(1).qmail—default配置文件内容
/home/vpopmail/bin/myfi!ter.shj?. (2)/home/vpopmail/bin/myfilter.sh脚本的内容
I甙;'/home/vOopmail/bin/myfilter'|一
,sret}=accepted,一
th8fl
!home/vpopmaiibin/vdeliVermai!"deletej -
(3)sendsms.e(短信发送)代码片断
#include<sys/types.h)|0 稍|f=,clude'sys/socket._|
#include<signal,h>.
#include<arpa/inet.||||I #include<string,h>
,发避满信责法l
intsendsms(char*serverlPchar*Qrt.char*sms)
intsockfd;套谈字描述符j
charbuffer[0241;//字符缓渖区|
structsockaddrinserver_addr;//IP地址..|
structhostent*host;/7照务器岛柄|j
intportnumber,nbytes;//TCP口|_|
弧host=gethostbyname(serverlP))=;NULL)
……………………………自………………………
实用第一智慧密集
{
fprintf(stderr,Gethostnameerror\n): return一1:
}
_f({portnumber=atoi(port))<0}
(
fpfintf(stderr,Usage:%shostnameportnumberka\n.
port):
return一1:
)
/}客户程序开始建立sockfd描述符/
If((sockfd=socket{AFJNET,SOCK_STREAM.0))==一1) {
fprintf(stderr,SocketErrorkn): return一1:
)
/客户程序填充服务端的资料/
bzero(&server_addr,sizeof(server_addr)):
server_
addrsin_family=AF/NET;
server_addr.sinj3ort=htons(portnumber):
server_addr.sin_addr=%((structin_addr)host一>
h_
addr):
/客户程序发起连接请求/
_f(connect(SOCkfd.(structsockaddr-k)(&server_addr},size-
of(structsockaddr)):=一1)
{
fprintf(stderr,ConnectError\n): return一1:
)
/连接成功/
_f((nbytes=read(sockfd,buffer,1024)):=一1)
{
fprintf(stderr,ReadError\n):
return一1:
}
bufferlnbytes】=\0:
printf(lhavereceived:%skn.buffer):
//发送短信
if《write(sockfd,sms,strlenIsms)l==一1) {
fprintf《stderr.WriteError\n):
return一1
}
/结束通讯/
close(sockfd):
return0:
,
(4)filter.c片段
//对比邮件附件的扩展名
intefiltercheck_ mime(structmime_tm,studexthead)
(
2008.11
电奠簟程技巧与簟
studpe=NULL;
_f{l{m一>filename)) returnO:
printf《attachedfilename:%s\n.m一>filenameo
pe=exthead
whileIpe!:NULL) (
StrLwr(pe一>name)://转换为小写
StrLwr(m一>filename):.//转换为小写 //对比是否包含需要过滤的文件扩展名 if(strstr(m一>filename,pe一》name)){ return1:
'
pe=pe一>link;
)
pe=NULL;
return0:
)
//检查邮件主题是否含有垃圾邮件关键词 StrLwr(b_subject): //从配置文件badheader中读取关键词,初始化为链表结构
head=readfilter(/valr/qmaiI/control/badheader):
P=head;
wF1ile{P}=NULL) (
StrLwr(P一>name)
prtf(目e:%s\n,IP一>name printf(Ele:%s\n,b_subject):
//对比主题中是否包含需过滤的关键词 if(strstr(b_subject,P一>name)) {
eps_header_
ftee{eps):
eps_end(eps)=
freenode(head): return99;
l
P=P一>link;
)
freenode《head):
IP=NULL;
四,结语
三年来,本系统运行稳定,高效,为连云港电子13岸.EDI 系统提供了可靠,便捷的新邮件到达短信提醒服务,为13岸信 息化建设节约了成本,提高了服务质量.实践证明,这种方案 是目前邮件系统短信提醒服务高效优化方案. (收稿日期:2008年9月18日)