基于Mozilla Thunderbird的扩展开发(四)---修改Thunderbird源代码实现自动保存附件...

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><lock v:ext="edit" aspectratio="t"></lock></shapetype>

20080506.bmp

Mozilla扩展系列链接:

1浅谈基于Mozilla Thunderbird的扩展开发

2基于Mozilla平台的扩展开发(续)----XPCOM组件篇

3基于MozillaThunderbird的扩展开发(三)---如何获取邮件的完整信息

4基于MozillaThunderbird的扩展开发(四)---修改Thunderbird源代码实现自动保存附件


在上一篇《基于Mozilla Thunderbird的扩展开发(三)---如何获取邮件的完整信息

》中给出了一种简单的获取邮件的完整信息(包括正文和附件等)的方法,但仔细考虑后发现离实际需求还有一段距离。

Thunderbird已经有保存附件的功能,但需要手动去操作,既然手头有它的源代码,为什么我们不自己尝试对它进行修改,从而使得它能自动保存所有附件呢?Ok,这篇文章就是基于这样思想的一个尝试。

首先明确一个前提,本文并不想开发一个扩展,而是尝试直接修改Thunderbird的源代码,但你也可以将它修改为一个扩展,这里为了调试开发简单起见,因此我选择了直接修改其代码。

要想自动保存附件,首先需要知道在它源代码中的哪个点去执行保存附件这样一个动作,在多次试验后发现可以msgMail3PaneWindow.js中的177行处的folderListener对象进行修改如下:

None.gif
ExpandedBlockStart.gifContractedBlock.gif
varfolderListener=dot.gif{
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gifOnItemIntPropertyChanged:
function(item,property,oldValue,newValue)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(item==gMsgFolderSelected)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(property.toString()=="TotalMessages"||property.toString()=="TotalUnreadMessages")dot.gif{
InBlock.gif
InBlock.gif
InBlock.gifUpdateStatusMessageCounts(gMsgFolderSelected);
InBlock.gif
InBlock.gifUpdateFolderLocationPicker(item);
InBlock.gif
//***************************************************************************
InBlock.gif//
Author:phinecos
InBlock.gif//
Date:2008/5/8
InBlock.gif//
Description:自动保存邮件到指定文件夹下
InBlock.gif//
Contact:phinecos@163.com
InBlock.gif//
***************************************************************************
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(property.toString()=="TotalMessages"&&newValue>oldValue)dot.gif{//保存邮件到指定文件夹下
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(messenger!=null&&gDBView!=null)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
trydot.gif{
InBlock.gifSaveAllMessages(saveFolderName);
ExpandedSubBlockEnd.gif}

ExpandedSubBlockStart.gifContractedSubBlock.gif
catch(err)dot.gif{
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}
,
InBlock.gif
//***************************************************************************
InBlock.gif//
Author:phinecos
InBlock.gif//
Date:2008/5/8
InBlock.gif//
Description:保存所有邮件
InBlock.gif//
Contact:phinecos@163.com
InBlock.gif//
***************************************************************************
InBlock.gif
functionSaveAllMessages(folerName)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//保存所有邮件,folerName是文件夹名称
InBlock.gif
if(gDBView==null)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//gDBView是空的
InBlock.gif
return;
ExpandedSubBlockEnd.gif}

InBlock.gif
vartreeView=gDBView.QueryInterface(Components.interfaces.nsITreeView);
InBlock.gif
varcount=treeView.rowCount;
InBlock.gif
if(!count)
InBlock.gif
return;
InBlock.gifgDBView.doCommand(nsMsgViewCommandType.expandAll);
//展开所有的邮件
InBlock.gif
varmessageUri;
InBlock.gif
varmsgKey=null;
InBlock.gif
for(vari=0;i<count;++i)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//保存第i个邮件
InBlock.gif
try
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifmessageUri
=gDBView.getURIForViewIndex(i);//邮件Uri
InBlock.gif
msgKey=gDBView.getKeyAt(i);//邮件key
InBlock.gif

InBlock.gif
try
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifgDBView.loadMessageByMsgKey(msgKey);
//加载邮件
ExpandedSubBlockEnd.gif
}

InBlock.gif
catch(err)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gifalert(
"sory");
ExpandedSubBlockEnd.gif}

InBlock.gif
varmsgHdr=messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
InBlock.gif
varresult=true;
InBlock.gifresult
=msgHdr.folder.hasMsgOffline(msgHdr.messageKey);
InBlock.gif
if(result==false)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//本地数据源中读取邮件
InBlock.gif
readOffline(msgHdr,messageUri,folerName);
ExpandedSubBlockEnd.gif}

InBlock.gif
else
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//从服务器上读邮件
InBlock.gif
//tobedofuture
ExpandedSubBlockEnd.gif
}

ExpandedSubBlockEnd.gif}

InBlock.gif
catch(ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//blowofferrorsfordummyrows
InBlock.gif
continue;
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif

接下来那些具体保存邮件的代码这里就省略了,具体可以参考上一篇文章,要重点提的一点是这一句代码:

None.gifgDBView.loadMessageByMsgKey(msgKey);//加载邮件
None.gif


当执行它时,会加载邮件信息,从而会触发对附件的处理函数,因此我们可以在附件的处理函数中进行保存附件的处理。
msgHdrViewOverlay.js
文件中第425行处的handleAttachment方法就是我们需要修改的地方。

None.gifhandleAttachment:function(contentType,url,displayName,uri,isExternalAttachment)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif….(省略)
InBlock.gif
//保存当前邮件的附件信息
InBlock.gif
varcurrentAttachment=newcreateNewAttachmentInfo(contentType,url,displayName,uri,isExternalAttachment);
InBlock.gif….(省略)
InBlock.gif
//
InBlock.gif//
***************************************************************************
InBlock.gif//
Author:phinecos
InBlock.gif//
Date:2008/5/17
InBlock.gif//
Description:保存附件
InBlock.gif//
Contact:phinecos@163.com
InBlock.gif//
***************************************************************************
InBlock.gif
varactionIndex=0;
InBlock.gif
//for(indexincurrentAttachment){
InBlock.gif
//excludeallattachmentsalreadydeleted
InBlock.gif
varattachment=currentAttachment;//当前待处理的附件
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(attachment.contentType!='text/x-moz-deleted')dot.gif{
InBlock.gif
varpath=getDefaultSaveFolder();//附件保存目录路径
InBlock.gif

InBlock.gif
vardestFolder=makeFile();
InBlock.gifdestFolder.initWithPath(path);InBlock.gif
InBlock.gif
varfolder=destFolder;
InBlock.gif
varproposedfileobject=makeFile();
InBlock.gifproposedfileobject.initWithFile(folder);
InBlock.gif
InBlock.gifproposedfileobject.appendRelativePath(attachment.displayName);
//附件的目标文件
InBlock.gif

InBlock.gif
if(proposedfileobject&&proposedfileobject.parent&&!proposedfileobject.parent.exists())
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{//若父目录不存在,则先创建父目录
InBlock.gif
proposedfileobject.parent.create(proposedfileobject.DIRECTORY_TYPE,0600);
ExpandedSubBlockEnd.gif}

InBlock.gifaeMessenger.saveAttachmentToFolder(attachment.contentType,attachment.url,proposedfileobject.leafName,attachment.uri,proposedfileobject.parent,index);
//保存当前待处理的附件
ExpandedSubBlockEnd.gif
}

InBlock.gif
//}
ExpandedBlockEnd.gif
}
,
None.gif

真正完成保存附件的是下面的aeMessenger对象:

None.gifvaraeMessenger=
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gifCc:Components.classes,
InBlock.gifCi:Components.interfaces,
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//**************************************saving**************************************/
InBlock.gifsaveAttachmentToFolder:
function(contentType,url,displayName,messageUri,aDestFolder,attachmentindex)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
varout=aDestFolder.clone();
InBlock.gifout
=out.QueryInterface(Components.interfaces.nsILocalFile);
InBlock.gifout.append(displayName);
InBlock.gif
if(this.saveAttachment(out,url,messageUri,contentType,attachmentindex))returnout;//保存附件的实际动作
InBlock.gif
elsereturnnull;
ExpandedSubBlockEnd.gif}
,//##
InBlock.gif

InBlock.gif
//simpliedversionofthisfunction,takingoutallfetchservicestuff.
InBlock.gif
saveAttachment:function(file,url,messageUri,contentType,attachmentindex)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
trydot.gif{
InBlock.gif
//stripout?type=application/x-message-displaybecauseitconfuseslibmime
ExpandedSubBlockStart.gifContractedSubBlock.gif
if(url.indexOf("?type=application/x-message-display")!=-1)dot.gif{
InBlock.gifurl
=url.replace("?type=application/x-message-display","").replace('&','?');
ExpandedSubBlockEnd.gif}

InBlock.gifurl
=url.replace("/;section","?section");
InBlock.gif
InBlock.gif
varsaveListener=newaeSaveMsgListener(file,messenger,contentType,null,null,false);
InBlock.gif
InBlock.gif
varconvertedListener=saveListener.QueryInterface(Components.interfaces.nsIStreamListener);//流监听器
InBlock.gif

InBlock.gif
varmessageService=messenger.messageServiceFromURI(messageUri);//邮件服务提供者
InBlock.gif
varopenAttArgs=newArray(contentType,file.leafName,url,messageUri,convertedListener,null,null);//apply方法所需要的参数
InBlock.gifmessageService.openAttachment.apply(
null,openAttArgs);//真正去保存附件
ExpandedSubBlockEnd.gif
}

InBlock.gif
catch(e)
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
returnfalse;
ExpandedSubBlockEnd.gif}

InBlock.gif
returntrue;
ExpandedSubBlockEnd.gif}
,
ExpandedBlockEnd.gif}
;
None.gif


注:这里设置了一个流监听器的作用是为了对文件流的写入进行监控,并不是必须的

好了,这下就可以用make命令重新编译thunderbird源代码了,测试时先启动thunderbird,当接收到新邮件并且其含有附件时,就会自动下载并保存。

如果需要完整的源代码,请发email:phinecos#163.com(#改为@)


Reference:

1,http://www.eviljeff.com/?page=moz-extensions

阅读更多
换一批

没有更多推荐了,返回首页