基于贝叶斯算法的JavaMail垃圾邮件过滤实现
刘岚,贾跃伟
武汉理工大学信息工程学院,武汉(430070)
E-mail: simon_jia_2005@163
摘要:JavaMail 在中小型企业的邮件系统中有着广泛的应用,谨以贝叶斯算法为基础,提出并实现一套简单,高效的自适应垃圾邮件的过滤方案。它采用基于词熵的特征提取方法,在过滤的过程中不断的进行自学习,具有较强的自适应能力,最终通过阈值来判别邮件是否为垃圾邮件。
关键词:JavaMail;贝叶斯算法;垃圾邮件;自学习
1.引言
JavaMail是Sun发布的处理的应用程序接口,预置了常用的邮件传送协议(如SMTP、POP、IMAP、NNTP)的实现方法,与JSP和QMAIL 结合开发出稳定可靠的企业级web mail系统,可以满足中小型企业的日常办公需求。
但目前这种办公邮箱最大的困扰是来自internet的大量以广告为目的垃圾邮件,尤其是在网站上对外公布的邮箱,其垃圾邮件的比例甚至达到了90%以上,日平均有20封以上的垃圾邮件,对邮箱使用造成了很大的不便,这是邮箱系统的开发和维护首要解决的问题。
2.反垃圾邮件过滤技术
2.1 基于黑白名单的过滤技术
此技术使用最早也最为常用,即是对于地址在白名单的服务器的邮件全部接收,对地址在黑名单的服务器的邮件全部拒收,国际和国内的一些反垃圾邮件组织会实时更新和提供一种实时的黑名单(Real Time Black List)的邮件服务器IP数据库,简称RBL,任何邮件服务器都可以订阅RBL以达到过滤垃圾邮件的目的[1]。
但这种方法缺点很也很明显:处理陌生邮件无能为力;需要不断更新和维护;效率不高容易误判。
2.2 基于加密信息的过滤技术
加密信息过滤技术主要是采用类似于公钥密码的一类方法,主要目的是对邮件发送者进行验证,防止目前泛滥的伪造域名和木马发送,域名密钥体制利用公钥技术和DNS构建一个域名层次的来源和内容认证框架,简单的讲,即为发送邮件时候同时产生密钥和公钥,密钥跟随邮件,收件服务器
从密钥中获取签名和域名,然后通过网络公钥验证通过后完成邮件的发送。
此种方法的缺点也显而易见,即使得邮件的网络传递负担加重,同时缺乏大规模的认证标准,使得目前阶段难以大范围的推广。
2.3 基于规则和统计的过滤技术
规则是指预设垃圾邮件关键词进行的邮件过滤,而其最大的缺点是实效性较差,不易维护,垃圾邮件往往通过关键词中增加特殊符号来躲避规则,同时也会使过滤缺乏弹性。
而贝叶斯过滤算法是一种典型的基于统计的垃圾邮件过滤技术,这种理论的基础是通过对大量垃圾邮件的常见关键词进行分析后得出其分布的统计模型,并由此推算目标是垃圾邮
件的概率,再根据所设阈值来判断是否接受邮件,它最大的特点是自学习功能,不断的自我更新过滤规则,保证了不需维护即可获得长期稳定的过滤效率。
但贝叶斯算法其缺点也同样明显,它同时需要一定量的垃圾邮件数据库完成初始自学习过程,同时需要用来匹配的大量的汉字和英文单词样本库,而且对于基于JavaMail 中小型规模的企业邮件服务器,其初始大量的自学习过程所耗费的系统资源是办公环境无法忍受的,基于此,本文将结合规则过滤的优点,将两个种方法进行互补的整合,在初始预设一定规则的情况下,由贝叶斯算法所实现的模块完
成对垃圾邮件的判断并且不断的通过自学习功能对规则进行完善和修改,以达到自我维护的目的。
3. 贝叶斯过滤算法推理
根据贝叶斯公式[5]:
1(|)()
(|)(|)()i i j j
j P A B P B P B A P A B P B ==∑
把两种邮件看作是两个随机事件A 、B ,其中A 为垃圾邮件,B 为正常邮件,是全部自学习E 的样本空间S 的全部随机事件。T 为邮件单词的集合,其中i T 为T 的元素。根据贝叶斯公示有:
(|)*()(|)(|)*()(|)*()
i i i i P T A P A P A T P T A P A P T B P B =+ 而样本空间中垃圾邮件的数量与正常邮件相当,故()()0.5P A P B ==,又令()(|)A i i f T P T A =、()(|)B i i f T P T B =,由此推导出由一个单词的出现的情况下,判断邮件是否为垃圾邮件的概率:
()(|)()()
A i i A i
B i f T P A T f T f T =+                          (公式3.1) 当拒收关键词列表学习完毕,在多关键词过滤的情况下,由合并概率公式(Combining Probabilities )可得:
1211211(|)*(|)*.....(|)
(|,...,)[(|)*(|)*.....(|)][(1(|))*(1(|))*......(1(|))]
n n n n n P A T P A T P A T P A T T P A T P A T P A T P A T P A T P A T −=
+−−−                                                                    (公式3.2) 由此,我们很容易算出所收到邮件时垃圾邮件的概率,再根据所设阈值判定是否为垃圾邮件。
4. 本算法实现的JavaMail 环境
本次是实现的贝叶斯算法的JavaMail 系统逻辑架构如下图所示:
图1 JavaMail服务器系统架构图
但由于是中小企业级邮件系统,数据库服务器没有专门配置,而是将邮件,和配置文件数据一起存放在应用服务器上,邮件文件存放在根目录下的domain文件夹中。
5.贝叶斯过滤算法的java实现
贝叶斯过滤算法在企业应用的邮件系统的具体实现中,会遇到以下几个关键问题:
关键字表单等数据的存储问题;邮件箱中大量邮件的读取;收邮件的同时邮件内容解码分析的问题;对邮件内容进行关键词的遍历比较并进行自学习。下面便分别实现上述功能:5.1 关键字表单数据的存储问题
由于本系统是中小型企业的邮件服务器,所以并未使用大型的数据库如:oracle等,而是采用xml文件的形式进行数据的存储,它的优点是系统架构简单,便于修改和维护[3]。
import org.dom4j.document;
import org.dom4j.Element;
import org.dom4j.Element;
//完成对xml文件的操作需要org.dom4j 的开发包
this.m_FileName = pPath + "/" + Domain + "/" + Name + "/l" ;
doc = DocumentHelper.parseText("<root/>");
OutputFormat format = atePrettyPrint();  //格式化输出
format.setEncoding("GBK"); //指定XML编码
writer = new XMLWriter(new FileWriter(new File(pFileName)), format);
El =Root.addElement("Filter");                      //增加“Filter”的节点
El.setText("");
// 完成对xml文件的创建
El = (Element)doc.selectSingleNode("root/Filter");
this.Filter = El.getText();
//完成对xml文件的读取
5.2 邮箱中大量邮件的读取
由本文第四部分可知,本系统的邮件文件的存储是放在根目录下的文件夹中。
import java.io.FileInputStream;
File f = new File(BoxDir); File[] files = f.listFiles();
// BoxDir 为邮件所存放文件夹的路径,如:“/maildir/inbox”
for (int i = files.length-1; i >= 0; i--) {
FileInputStream in = new FileInputStream(files[i]);
}
//这样变利用java.io的fileinputStream将所有邮件从文件夹中循环的读入内存
5.3 收邮件并对邮件内容进行解码分析
由于邮件发送是根据SMTP(Simple Mail Transfer Protocol)协议,而smtp服务器只能接受7bit字节流,所以要根据MIME(Multipurpose Internet Mail Extensions)协议将邮件内容进行编码,所以再解码端也要对应的将信件内容的格式作出判断,如图1:
图 2 MIME解码过程示意图
import javax.mail.* ;
Store store = Store("pop3");
folder.open(Folder.READ_WRITE);          //打开收件箱文件夹
Message message[] = Messages();
//通过以上几个步骤,已经把邮件从服务器中收到系统中。
for (int i = 0; i < message.length; i++)
{ String ContentString = new String();
Object object = message[i].getContent(); //获得邮件内容
if ( message[i].isMimeType("text/plain")|| message[i].isMimeType("text/html"))
{  ContentString=" "+(String)object+" ";}  //判断是否为“text/html”
if ( message[i].isMimeType("multipart/*"))
{  Multipart mp = (Multipart)object;        //判断是否为 “Multipart”
for (int j = 0; j < mp.getCount(); j++) {
ContentString =ContentString+"\t"+ mp.getContent ();  //将所有邮件内容放入一个字符串 }
//邮件内容分析完毕
5.4 根据规则对邮件样本进行遍历自学习
由第2节可知,鉴于实用资源和效率的考虑,本模块将预设一定的规则。
String[] banword = BanWord(); //由5.2模块获得xml 配置文件的预设规则 for(int k=0;k<banword.length;k++){
boolen contain =FilterKeyWord(ContentString, banword [k]);
//关键词对比过滤器,返回ture
if(contain == true) { Spam=Spam+1; SpamAll=SpamAll+1;} else {Legit=Legit+1; LegitAll=LegitAll+1;}
//根据过滤结果,自学习更改判断数据,即将本次查询记录在案,作为下次概率判断的依据 }
private boolean FilterKeyWord(String strContent,String strKeyWord) {
boolean retVal = false;
for(int i =0;i<=(strContent.length()-strKeyWord.length());i++) {
int end = i+strKeyWord.length();
if(strContent.substring(i,end).equalsIgnoreCase(strKeyWord))
{ retVal =true;
break;}
}
return retVal;
}
//将banword 的关键字词与邮件类容逐字比较[2],若邮件内容中包含,则返回ture
5.5 根据历史数据的概率和贝叶斯公式对收到的邮件进行评估
String[] banword = BanWord(); //由5.2模块获得xml 配置文件的预设规则 double[] Pbanword = null;
double[] Pmail = null;
for(int k=0;k<banword.length;k++){
double Spam = Spam(banword[k]);
double SpamAll = SpamAll(banword[k]);
double Legit = Legit (banword[k]);
double LegitAll = LegitAll (banword[k]);
//由5.2模块获得xml 配置文件的对应Banword 的历史数据
for(int k=0;k<banword.length;k++){
Pbanword[k] = (Spam*LegitAll)/( Spam*LegitAll+ Legit*SpamAll)
//根据(公式3.1)
}
//所有已有的banword 的12(|),(|),.....(|)n P A T P A T P A T ,都已经算出放入Pbanword[]
double Pup = Pbanword[0]; double Pdown = (1-Pbanword[0]);
for(int j=1;j<Pbanword.length;j++){
Pup= Pup* Pbanword[j];
Pdown= Pdown* (1-Pbanword[j]);
}
Pmail = Pup/(Pup+Pdown);使用dom4j解析xml文件
/
/根据(公式3.2)
if(Pmail < 0.8) //将阈值设为0.8
{ OutputStream out = new FileOutputStream(“/newbox”);}
else{OutputStream out = new FileOutputStream("/delbox");
String newBanword = strContent.substring(indexof(“票”)-2,indexof(“票”))} Boolen add = ture;
for(m=0,m<banword[].length,m++){
if(newBanword.equal(banword[m]))
add = false}
if(add) Xml.setdata(newBanword); //其中setdata函数为5.2的写xml文件模块message[i].writeTo(out);
out.close();}
//当收到的这封mail的概率Pmail>0.8时候,便被存放到垃圾邮件箱delbox 同时把邮件中含有的历史记录里所没有的易干扰字的样本存入记录中
5.6 总结
贝叶斯过滤算法的java实现的流程图[4]如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。