<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Mozilla扩展系列链接:

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

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

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

4基于MozillaThunderbird的扩展开发(四)---修改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

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

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

    源代码下载:HelloWorld示例.rar 在<浅谈基于Mozilla ThunderBird的扩展开发>这篇入门文章中简单介绍了基于Mozllia平台进行扩展开发的基础知识,但仍然欠缺 ...

  2. 于Mozilla平台的扩展开发

    [url]http://www.cnblogs.com/phinecos/archive/2008/04/25/1171614.html[/url] 于Mozilla平台的扩展开发(续)----XPC ...

  3. firefox扩展开发(四) : 更多的窗口控件

    firefox扩展开发(四) : 更多的窗口控件 2008-06-11 17:00 标签盒子 标签盒子是啥?大家都见过,就是分页标签: 对应的代码: <?xml version="1. ...

  4. php7 定义变量,基于PHP7的PHP扩展开发之七(定义变量)

    目的:熟悉在PHP扩展里面如何定义变量 要实现的PHP代码如下: class lostphp{} $lng = 2; $str = "abc"; $arr = array(1,'a ...

  5. php 扩展 返回字符串,基于PHP7的PHP扩展开发之四(字符串的处理)

    目的:熟悉字符串在PHP扩展里面如何处理 要实现的PHP代码如下: 1.当字符串不包含指定前缀字符串时,把前缀字符串和被检测字符合并返回. 2.当字符串包含指定前缀字符串时,原样返回. 我们将使用PH ...

  6. php7 ext skel_基于PHP7的PHP扩展开发之一(hello word)

    为什么要学PHP扩展开发?学会PHP扩展开发后,能增加你解决问题的能力.如,别人用PHP实现了一个功能.执行一次需要耗时10毫秒.而你用扩展实现了同样的功能,可能就只用1毫秒. PHP扩展的应用场景 ...

  7. 保存时自动加分号_CAD自动保存文件扩展名是什么?如何快速恢复自动保存文件?...

    下面是本公众号文章分类目录,点击标题文字可打开分类文章列表: 安装卸载  异常.退出  文件及输入输出  基本操作技巧  各种设置及相关问题  界面和显示相关问题  快捷键  视图设置和调整  图层  ...

  8. 【php7扩展开发四】函数的参数 ,引用传参 ,返回值

    函数参数解析 之前我们定义的函数没有接收任何参数,那么扩展定义的内部函数如何读取参数呢?用户自定义函数在编译时会为每个参数创建一个zend_arg_info结构,这个结构用来记录参数的名称.是否引用传 ...

  9. ibm java 工具_Eclipse是由IBM开发的一款功能完整且成熟的IDE集成开发环境,它是一个开源的、基于Java的可扩展开发平台,是目前最流行的Java语言开发工具。...

    [判断题]由运放组成的任何应用电路都可以采用 " 虚短 " 和 " 虚断 " 分析法.( ) [单选题]某污水厂初沉池设计流量为10000m2/d,进水悬浮物浓 ...

最新文章

  1. tflearn 中文汉字识别,训练后模型存为pb给TensorFlow使用——模型层次太深,或者太复杂训练时候都不会收敛...
  2. oracle 树状结构一直出现不了_SEO站内优化:网站结构优化(十一)
  3. 【C++】 C++标准模板库(九) Bitsets
  4. 视觉SLAM十四讲学习笔记-第七讲-视觉里程计-对极几何和对极约束、本质矩阵、基础矩阵
  5. 马云后悔创办阿里:想停根本停不下来;人民日报评“滴滴顺风车争议”;jQuery 曝漏洞|极客头条...
  6. 《中国人工智能学会通讯》——12.44 分类型数据的定义
  7. android连接airprint打印机,AirPrint:iOS的打印机
  8. vue检测是不是360浏览器兼容模式_Vue项目兼容IE11
  9. 极路由+锐捷校园网小白使用教程
  10. 百度网盘偷偷更新,终于实现免费不限速了!
  11. 计算机一级仿宋gb2312,2016年计算机一级Office考试题(带答案)
  12. 2019年12月7日pmp考试成都在哪考
  13. MacBook Pro 屏幕黑线、条纹、线条、舞台灯、残影、横线这样的排线门问题你遇到了吗?很有可能源于官方的设计缺陷,你该何去何从?
  14. 【逻辑思维训练 二】系统思维训练
  15. FairMOT多目标跟踪(安装+代码解读)
  16. Object-based superresolution land cover Mapping From Remotely sensed imagery
  17. SEO优化 网站结构优化
  18. Win11系统启动文件夹是空的怎么解决?
  19. Android应用安装流程理解
  20. if条件语句基本语法

热门文章

  1. [python教程入门学习]python学习笔记(CMD执行文件并传入参数)
  2. js截屏代码_JavaScript网页截屏方法,你get到了嘛?
  3. telegraf监控mysql数据库_部署Telegraf+Influxdb+Grafana 架构来监控 MySQL
  4. 本科刚毕业有点迷茫,想入门单片机,应该怎么开始?
  5. 单片机是否为嵌入式技术,单片机和嵌入式学哪个?
  6. JavaScript初学者编程题(18)
  7. 字符串 内存 函数的介绍与模拟实现
  8. tkinter实现滚动文本框
  9. 线段树区间扫描线超详解,一篇文章搞懂扫描线
  10. java field setfont_Java JTextField.setFont方法代碼示例