且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-09-18 13:30:43

 
 20080506.bmp
Mozilla扩展系列链接:
1,浅谈基于MozillaThunderBird的扩展开发
2,基于Mozilla平台的扩展开发(续)----XPCOM组件篇
3,基于Mozilla ThunderBird的扩展开发(三)---如何获取邮件的完整信息
 

    如果你没有读过ThunderBird的源代码,也许会和我一样想当然地认为里面肯定有某个数据结构用于存储邮件的正文和附件等信息,但如果你读过了代码,那么也会和我一样感到遗憾,居然没有这样完整的数据结构!里面有一个表示邮件头的XPCOM 组件 nsIMsgHdr , 但mozilla这帮人却没有定义一个用来表示邮件(包括邮件头,正文,附件等信息)的组件” nsIMsg”呢,问题更进一步,你会发现它里面采用了一个gDBView,一个msgWindow,这两个对象的具体含义这里就不多说了,反正是让我们想获取到邮件的完整信息这件事更加困难了。
      好的,那我现在就要结合自己的实际开发讲解下如何去获取指定邮件的完整信息了,let’s go!

      首先要明确的是你要获取的邮件是离线的(存储在本地)还是在线的(在服务器上),要实现这个判断,我们可以用如下代码:
if (mail.folder.hasMsgOffline(mail.messageKey)) {
       readOffline(mail);//从本地读
   } else {
       readOnline(mail);//从服务器读
   } 

      如果邮件在本地,我们可以直接让它所在的文件夹给我们一个代表整个邮件的输入流对象,要完成这个工作,你得创建一个nsIInputStream,它的作用是用来“包含”邮件信息,nsIMsgFolder的getOfflineFileStream方法可以返回这样一个流对象,这个方法有一个输入参数(表示邮件key),两个输出参数.
function readOffline(mail) {
        var key = mail.messageKey;
        var offset = new Object();
        var messageSize = new Object();
        var is;
          var bodyAndHdr;

        try{ is = mail.folder.getOfflineFileStream(key,offset,messageSize); }
        catch(e){ alert("message: "+e.message); }
        try{
            var sis = factory.createInstance(
                Components.interfaces.nsIScriptableInputStream
            );
            sis.init(is);
             bodyAndHdr = sis.read(mail.messageSize);
               sis.close();
               is.close();       
             } catch(e){ alert("message: "+e.message); }
        doSomethingWith(bodyAndHdr);
    }


      如果你要在线读取邮件,那就有点复杂了,因为你得让IMAP服务器端告诉你邮件的信息,而这是一个异步的事件,也就是你发出指令,然后等待来自服务器的反馈信息。因此你得监听来自服务器端的反馈信息。
      首先,我们获取邮件的URI,这可以通过其所在的文件夹获得,然后我们查找邮件服务提供者---IMAP,POP等,让它来处理邮件信息:
function readOnline(folder, mail) {
        var key = mail.messageKey;
        var uri = mail.folder.generateMessageURI(key);
        var messenger = Components.classes['@mozilla.org/messenger;1']
                        .createInstance();
        messenger = messenger.QueryInterface(
                        Components.interfaces.nsIMessenger
                    );
        var messageService = messenger.messageServiceFromURI(uri);//邮件服务提供者

   ok,现在我们已经有一个处理邮件URI的邮件服务提供者了,接下来就可以通过它一个方法CopyMessage来从服务器端获取邮件了,并且可以将邮件放入一个输入流中,从而使得我们可以传入一个nsIStreamListener来监听这个输入流是否有数据到来。
var aurl = new Object();
        messageService.CopyMessage(uri,
            myStreamListener, false, null, msgWindow, aurl);
    }

   输入流监听器会负责处理来自服务器端的数据的:
var myStreamListener = {
         onDataAvailable: 
            function(request, context, inputStream, offset, count){
                try {
                    var sis= Components.
                             classes["@mozilla.org/scriptableinputstream;1"]
                             .createInstance(
                                Components.interfaces.nsIScriptableInputStream
                             );
                    sis.init(inputStream);
                    bodyAndHdr += sis.read(count);
                }
                catch(ex) { alert("exception caught: "+ex.message+"\n"); }
         },
         onStartRequest: function(request, context) { },
         onStopRequest: function(aRequest, aContext, aStatusCode) {
             doSomethingWith(bodyAndHdr);
         }
    };

onDataAvailable函数会一直被调用,直到服务器告诉我们已经拿到整个邮件的信息了,此时,onStopRequest就会被调用,从而让我们开始处理邮件信息。
     
   好了,这样我们就可以取得邮件的完整信息了,接下来要做的就是对邮件的解析了,这个我还在研究,以后有机会再和大家分享心得。
附:还有另外一种思路可以获取邮件的正文信息,有时间我再写篇文章介绍。
 
 Reference:
1,http://simon-cozens.org:81/programmer/articles/thunderbird-js.pod
2,http://thunderbirddocs.blogspot.com/



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/05/05/1184110.html,如需转载请自行联系原作者