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

简介:

       在上一篇《基于Mozilla Thunderbird的扩展开发(三)---如何获取邮件的完整信息》中给出了一种简单的获取邮件的完整信息(包括正文和附件等)的方法,但仔细考虑后发现离实际需求还有一段距离。
      Thunderbird中已经有保存附件的功能,但需要手动去操作,既然手头有它的源代码,为什么我们不自己尝试对它进行修改,从而使得它能自动保存所有附件呢?Ok,这篇文章就是基于这样思想的一个尝试。
      首先明确一个前提,本文并不想开发一个扩展,而是尝试直接修改Thunderbird的源代码,但你也可以将它修改为一个扩展,这里为了调试开发简单起见,因此我选择了直接修改其代码。
      要想自动保存附件,首先需要知道在它源代码中的哪个点去执行保存附件这样一个动作,在多次试验后发现可以msgMail3PaneWindow.js中的177行处的folderListener对象进行修改如下:
    
var folderListener = {

    OnItemIntPropertyChanged: function(item, property, oldValue, newValue) {
      if (item == gMsgFolderSelected) {
        if(property.toString() == "TotalMessages" || property.toString() == "TotalUnreadMessages") {
            
          
          UpdateStatusMessageCounts(gMsgFolderSelected);
         
          UpdateFolderLocationPicker(item);
//***************************************************************************
//Author: phinecos
//Date : 2008/5/8
//Description:自动保存邮件到指定文件夹下
//Contact:phinecos@163.com
//***************************************************************************
          if(property.toString()=="TotalMessages" && newValue>oldValue){//保存邮件到指定文件夹下
                if(messenger!=null && gDBView!=null){
                 try{
                     SaveAllMessages(saveFolderName);
                  }
                  catch(err){
                  }
              }
          }
        }      
      }
    },
//***************************************************************************
//Author: phinecos
//Date : 2008/5/8
//Description:保存所有邮件
//Contact:phinecos@163.com
//***************************************************************************
function SaveAllMessages(folerName)
{//保存所有邮件,folerName是文件夹名称
    if(gDBView==null)
    {//gDBView是空的
        return;
    }
    var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
    var count = treeView.rowCount;    
    if (!count)
        return;
    gDBView.doCommand(nsMsgViewCommandType.expandAll);//展开所有的邮件
    var messageUri;
    var msgKey = null;
    for (var i = 0; i < count; ++i)
    {//保存第i个邮件
        try 
        {
              messageUri = gDBView.getURIForViewIndex(i);//邮件Uri
            msgKey = gDBView.getKeyAt(i);//邮件key
            
            try
            {
                gDBView.loadMessageByMsgKey(msgKey);//加载邮件
            }
            catch(err)
            {
                alert("sory");
            }
            var msgHdr = messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
            var result  = true;
            result = msgHdr.folder.hasMsgOffline(msgHdr.messageKey);
            if(result==false)
            {//本地数据源中读取邮件
                readOffline(msgHdr,messageUri,folerName);
            }
            else
            {//从服务器上读邮件
                //to be do future
            }            
        }
        catch (ex) 
        {// blow off errors for dummy rows
            continue;
        } 
    }
}

接下来那些具体保存邮件的代码这里就省略了,具体可以参考上一篇文章,要重点提的一点是这一句代码:
gDBView.loadMessageByMsgKey(msgKey);//加载邮件


当执行它时,会加载邮件信息,从而会触发对附件的处理函数,因此我们可以在附件的处理函数中进行保存附件的处理。
      msgHdrViewOverlay.js文件中第425行处的handleAttachment方法就是我们需要修改的地方。
        handleAttachment: function(contentType, url, displayName, uri, isExternalAttachment) 
    {
        ….(省略)
        //保存当前邮件的附件信息
      var currentAttachment = new createNewAttachmentInfo(contentType, url, displayName, uri, isExternalAttachment);
….(省略)
//      
//***************************************************************************
//Author: phinecos
//Date : 2008/5/17
//Description:保存附件
//Contact:phinecos@163.com
//***************************************************************************
   var actionIndex = 0;
//   for (index in currentAttachment) {
       // exclude all attachments already deleted
                var attachment = currentAttachment;//当前待处理的附件
                if (attachment.contentType != 'text/x-moz-deleted') {
                    var path = getDefaultSaveFolder();//附件保存目录路径

                    var destFolder=makeFile(); 
                    destFolder.initWithPath(path);                    
                    var folder=destFolder;
                    var proposedfileobject = makeFile();
                    proposedfileobject.initWithFile(folder);

                    proposedfileobject.appendRelativePath(attachment.displayName);//附件的目标文件

                     if (proposedfileobject && proposedfileobject.parent && !proposedfileobject.parent.exists()) 
                     {//若父目录不存在,则先创建父目录
                         proposedfileobject.parent.create(proposedfileobject.DIRECTORY_TYPE, 0600);
                     }
                    aeMessenger.saveAttachmentToFolder(attachment.contentType, attachment.url,proposedfileobject.leafName, attachment.uri, proposedfileobject.parent, index);//保存当前待处理的附件
                }
//            }
    },

真正完成保存附件的是下面的aeMessenger对象:
var aeMessenger = 
{
    Cc:Components.classes,
    Ci:Components.interfaces,

/* ************************************* saving ************************************* */
  saveAttachmentToFolder:function(contentType,url,displayName,messageUri,aDestFolder,attachmentindex)
  {
    var out=aDestFolder.clone();
    out=out.QueryInterface(Components.interfaces.nsILocalFile);
    out.append(displayName);
    if (this.saveAttachment(out, url, messageUri, contentType, attachmentindex)) return out;//保存附件的实际动作
    else return null;
  }, //##

  // simplied version of this function, taking out all fetchservice stuff.
  saveAttachment:function(file, url, messageUri, contentType, attachmentindex)
  {
    try{
    // strip out ?type=application/x-message-display because it confuses libmime
    if (url.indexOf("?type=application/x-message-display")!=-1) {
        url=url.replace("?type=application/x-message-display","").replace('&','?');
    }
    url=url.replace("/;section","?section");
    
    var saveListener = new aeSaveMsgListener(file, messenger,contentType,null,null,false);
      
    var convertedListener=saveListener.QueryInterface(Components.interfaces.nsIStreamListener);//流监听器

      var messageService=messenger.messageServiceFromURI(messageUri);//邮件服务提供者
      var openAttArgs=new Array(contentType,file.leafName,url,messageUri,convertedListener,null,null);//apply方法所需要的参数
       messageService.openAttachment.apply(null,openAttArgs); //真正去保存附件
    }
     catch (e)
     {
        return false;
    }
    return true;
  },
};


注:这里设置了一个流监听器的作用是为了对文件流的写入进行监控,并不是必须的
   好了,这下就可以用make命令重新编译thunderbird源代码了,测试时先启动thunderbird,当接收到新邮件并且其含有附件时,就会自动下载并保存。
如果需要完整的源代码,请发email至:phinecos#163.com(#改为@)
 
 Reference:
1, http://www.eviljeff.com/?page=moz-extensions
 



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/05/18/1202095.html,如需转载请自行联系原作者
目录
相关文章
|
5月前
|
Web App开发 Windows
Windows【Chrome浏览器 01】首次安装的谷歌Chrome浏览器出现无法打开此页面问题处理(详细图文步骤)
Windows【Chrome浏览器 01】首次安装的谷歌Chrome浏览器出现无法打开此页面问题处理(详细图文步骤)
72 0
|
9月前
|
缓存 API C++
客户端在线更新-QT
最近在做客户端的时候,需要将客户端在线更新,所以整理一下在线更新的思路,希望对你有帮助。 首先在线更新是利用了文件解压之后会自动替换的原理,因此具体需要做的就是从服务器上下载到在线更新的压缩包,之后在对下载到的压缩包进行解压缩替换现有程序内的文件即可。
102 0
|
Web App开发 安全 内存技术
新版谷歌Chrome取消对PPAPI插件支持后,浏览器网页打开编辑保存微软Office、金山WPS文档解决方案
最近陆续看到一些大学发布公告,谷歌Chrome取消了对PPAPI插件支持,导致某些在线Office厂家产品将无法在谷歌Chrome107及以上版本运行,被迫更换360浏览器或者使用低版本Chrome浏览器苟延残喘。
286 0
新版谷歌Chrome取消对PPAPI插件支持后,浏览器网页打开编辑保存微软Office、金山WPS文档解决方案
|
网络安全 数据安全/隐私保护
MAC使用Charles,代理后,部分网页无法打开解决方法
关闭charles,重新打开,可正常访问日常网站。访问时,提示:您的连接不是私密连接,多半是因为,MAC系统未安装charles证书导致,解决方法如下: 1. 打开Charles,选择Help-&amp;gt;SSL Proxy→Install Charles Root Certificate 2. 在弹出的添加证书窗口中,选择添加,可以看到在钥匙串访问窗口中,该证书已成功添加,但是此时该证书仍然不被信任 3.双击此证书,在弹出的Charles Proxy CA窗口中,点击信任按钮,使用此证书时,选择始终信任后关闭窗口,使用账号和密码授权后,即可看到此证书已经被信任了。。。
4748 0
MAC使用Charles,代理后,部分网页无法打开解决方法
win10显示此设备不支持接收miracast的解决办法【【百度的方法均不好使,自己发现的,亲测有效!!!!】】
win10显示此设备不支持接收miracast的解决办法【【百度的方法均不好使,自己发现的,亲测有效!!!!】】
win10显示此设备不支持接收miracast的解决办法【【百度的方法均不好使,自己发现的,亲测有效!!!!】】
Redmine系统通过bug号解析页面内容及下载附件
Redmine系统通过bug号解析页面内容及下载附件
95 0
|
安全
IE设置主页一直无果,尝试了右键软件看目标路径后缀无效,注册表也无效,最后在电脑管家里的工具浏览器保护搞定
IE设置主页一直无果,尝试了右键软件看目标路径后缀无效,注册表也无效,最后在电脑管家里的工具浏览器保护搞定
137 0
IE设置主页一直无果,尝试了右键软件看目标路径后缀无效,注册表也无效,最后在电脑管家里的工具浏览器保护搞定