基于gmime2.0库的邮件解码程序实现 [摘要] Gmime 库是一套非常强大MIME(Multipurpose Internet Mail Extension)工具库,用来创建、编辑、分解MIME消息和结构。Gmime本身基于Glib2.0的Gobject,具有良好的扩展性。GMIME遵循GPL许可,源代码公开。本文通过一个最简单的程序,讲解了如何利用该库去实现对一封邮件进行内容还原。 一、测试邮件生成 在outlook收件箱中新建一邮件,仅包含正文内容,没有附件等其他东西。 标题为: test mail 发件人为: [email protected] 收件人为:[email protected] 正文内容是: hello billy. 这是一封测试信. 石冬雪 然后,另存为testmail.eml。这就是我们将要分析的邮件,通过INTERNET捕包或者邮件代理程序接收到的邮件原始信息跟它是一样的。它的内容如下: From: "billy shi" <[email protected]> To: "[email protected]" Subject: test mail Date: Mon, 9 May 2005 15:18:53 +0800 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_000C_01C554AA.7B713F40" X-Priority: 3 X-MSMail-Priority: Normal X-Unsent: 1 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 This is a multi-part message in MIME format. ------=_NextPart_000_000C_01C554AA.7B713F40 Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: base64 aGVsbG8gYmlsbHkuDQoNCtXiysfSu7fisuLK1NDFLg0KDQrKr7as0ak= ------=_NextPart_000_000C_01C554AA.7B713F40 Content-Type: text/html; charset="gb2312" Content-Transfer-Encoding: base64 PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgaHR0cC1lcXVpdj1Db250ZW50LVR5cGUgY29udGVu dD0idGV4dC9odG1sOyBjaGFyc2V0PWdiMjMxMiI+DQo8TUVUQSBjb250ZW50PSJNU0hUTUwgNi4w MC4yODAwLjE0OTgiIG5hbWU9R0VORVJBVE9SPg0KPFNUWUxFPjwvU1RZTEU+DQo8L0hFQUQ+DQo8 Qk9EWSBiZ0NvbG9yPSNmZmZmZmY+DQo8RElWPjxGT05UIHNpemU9Mj5oZWxsbyBiaWxseS48L0ZP TlQ+PC9ESVY+DQo8RElWPjxGT05UIHNpemU9Mj48L0ZPTlQ+Jm5ic3A7PC9ESVY+DQo8RElWPjxG T05UIHNpemU9Mj7V4srH0ru34rLiytTQxS48L0ZPTlQ+PC9ESVY+DQo8RElWPjxGT05UIHNpemU9 Mj48L0ZPTlQ+Jm5ic3A7PC9ESVY+DQo8RElWPjxGT05UIHNpemU9Mj7Kr7as0ak8L0ZPTlQ+PC9E SVY+PC9CT0RZPjwvSFRNTD4NCg== ------=_NextPart_000_000C_01C554AA.7B713F40-- 我们看到,经编码过之后,邮件标题和发信人/收信人还可读,但邮件内容变得不可读。 二、邮件原始结构分析 此邮件是一个混合体,混合的两部分是等价的,其中一部分是采用PLAIN明文方式,另一部分是采用HTML网页方式,任一部分内容分析出来都可以; 每部分都采用了BASE64来编码; 各部分均采使用了gb2312字符集; 各部分的分界线为:”----=_NextPart_000_000C_01C554AA.7B713F40”; 另外,将该邮件上传到linux服务器可看出,它每行是以/r/n结尾的,跟LINUX下的邮件内容有区别,需要对CRLF进行特别处理。 三、Gmime2.0简介 a)框架 i.GMime Streams GMime Streams Name GMime Streams -- How to use GMime Streams Overview of Streams Streams are the fundamental method for reading and writing data used by GMime. You'll probably notice that the basic API is similar to that of the low-level Unix I/O layer (read(), write(), lseek(), etc) with some additional nicities such as a printf-like function. The three (3) basic stream types are: GMimeStreamFile, GMimeStreamFs and GMimeStreamMem. You can manipulate all three streams using the GMimeStream interfaces. In addition, some of these streams have extended interfaces to allow more fine grained manipulation. GMimeStreamFile and GMimeStreamFs are very similar in that they are both meant for reading and writing data to the file system (in the form of files). Since GMimeStreamFile is an abstracted layer above the standard libc FILE type, one of the added benefits is buffered I/O. GMimeStreamFs, on the other hand, is an abstracted layer above Unix file descriptors. While a GMimeStreamFs can be used on top of a UNIX socket or pipe, you must be careful because sockets and pipes are not seekable. Unlike the previous 2 stream types, GMimeStreamMem does not interact with the file system at all (except maybe the swap partition/file indirectly). Memory streams are handy when you want reads and writes to be nearly instantaneous and/or if you don't want to create a temporary file on disk. The four (4) advanced stream types are GMimeStreamMmap, GMimeStreamNull, GMimeStreamBuffer and GMimeStreamFilter. Our most simple stream, GMimeStreamNull, is the stream equivalent of /dev/null on Unix systems. The main difference is that GMimeStreamNull records the number of bytes written to it - you may find this useful if you need to know the number of bytes a GMimeObject (for example) will require. GMimeStreamMmap is a memory-mapped stream. This isn't guarenteed to work on all systems since not all systems support the POSIX mmap system call, but for those that do - this might present a faster stream than GMimeStreamFs and/or GMimeStreamFile. You'll have to do some experimentation to know for sure. The GMimeStreamBuffer can be used on top of any other type of stream and has 3 modes: block reads, block writes, and cached reads. Block reads are especially useful if you will be making a lot of small reads from a stream that accesses the file system. Block writes are useful for very much the same reason. The final mode, cached reads, can become memory intensive but can be very helpful when inheriting from a stream that does not support seeking (Note: this mode is the least tested so be careful using it). Our final stream type, GMimeStreamFilter, can also be used on top of another stream. This stream, as you may have guessed, filters reads and writes to its inherited stream. For example, one could write a compression filter and apply it to a GMimeStreamFilter and any further reads or writes would be (un)compressed. ii.GMime Stream Filters GMime Stream Filters Name GMime Stream Filters -- How to use GMime Stream Filters Overview of Filters Stream filters are an efficient way of converting data from one format to another. To use a stream filter, you must first construct a GMimeStreamFilter stream and then add the desired filters to it. GMime comes equipped with some basic filters such as GMimeFilterBasic, GMimeFilterCharset, GMimeFilterCRLF, GMimeFilterFrom and GMimeFilterHTML. The GMimeFilterBasic filter is actually a collection of filters for common transfer encodings used by MIME. So far, it is able to handle encoding and decoding of base64, quoted-printable and (x-)uuencode. For internationalization support, GMime also includes a filter for converting between any 2 charsets, GMimeFilterCharset. With this filter, mail user agents can allow the user to read the message content in his or her own charset. A common conversion needed for text is CRLF -> LF and LF -> CRLF which is needed for most (all?) internet protocols. Luckily, GMime comes equipped with a filter to handle this for you, GMimeFilterCRLF. You'll notice that GMimeFilterCRLF can also handle dot-escaping, which is especially useful for SMTP (rfc821). On Unix systems, mail often resides in spools in mbox format. Mbox uses a line that starts with "From " to delimit messages which means that message bodies are forbidden to contain lines starting with "From ". The common way to escape these from lines in message bodies is to prepend the line with a greater-than character ('>') producing ">From ". You'll find GMimeFilterFrom handy when dealing with this. The GMimeFilterHTML filter converts a normal text stream into an html stream. This is especially useful if you are using a widget such as GtkHTML to display the contents of an email message. b)Gmime对象 i.对象层次图 Class hierarchy GMimeContentType GMimeDisposition GMimeHeader GMimeParam GObject GMimeDataWrapper GMimeObject GMimeMessage GMimeMessagePart GMimeMessagePartial GMimeMultipart GMimeMultipartEncrypted GMimeMultipartSigned GMimePart GMimeParser GMimeStream GMimeStreamBuffer GMimeStreamCat GMimeStreamFile GMimeStreamFilter GMimeStreamFs GMimeStreamMem GMimeStreamMmap GMimeStreamNull GMimeFilter GMimeFilterBasic GMimeFilterBest GMimeFilterCharset GMimeFilterCRLF GMimeFilterFrom GMimeFilterHTML GMimeFilterMd5 GMimeFilterStrip GMimeFilterYenc GMimeCipherContext GMimeGpgContext GMimeSession InternetAddress 各对象细节详见《GMime Reference Manual》。 c)GMIME库的编译 Compiling the GMime libraries Name Compiling the GMime Libraries -- How to compile GMime itself Building GMime on UNIX-like systems This chapter covers building and installing GMime on UNIX and UNIX-like systems such as Linux. Compiling GMime on Microsoft Windows is not a goal of the project, however if you are able build on a Microsoft Windows platform, do send me building and installing instructions and I will add them to this document. Before we get into the details of how to compile GMime, I should mention that binary packages of GMime prebuilt for your operating system may be available either from your operating system vendor or from independent sources such as <a href="http://rpmfind.net.%C2%A0if%C2%A0you%C2%A0can%C2%A0find%C2%A0them%2C%C2%A0it%C2%A0may%C2%A0be%C2%A0the%C2%A0easiest%C2%A0way%C2%A0of%C2%A0getting%C2%A0started%C2%A0developing%C2%A0gmime.%C2%A0%3Cbr%3Eon%C2%A0unix-like%C2%A0systems%C2%A0gmime%C2%A0uses%C2%A0the%C2%A0standard%C2%A0gnu%C2%A0build%C2%A0system%2C%C2%A0using%C2%A0autoconf%C2%A0for%C2%A0package%C2%A0configuration%C2%A0and%C2%A0resolving%C2%A0portability%C2%A0issues%2C%C2%A0automake%C2%A0for%C2%A0building%C2%A0makefiles%C2%A0that%C2%A0comply%C2%A0with%C2%A0the%C2%A0gnu%C2%A0coding%C2%A0standards%2C%C2%A0and%C2%A0libtool%C2%A0for%C2%A0building%C2%A0shared%C2%A0libraries%C2%A0on%C2%A0multiple%C2%A0platforms.%C2%A0%3Cbr%3Eif%C2%A0you%C2%A0are%C2%A0building%C2%A0gmime%C2%A0from%C2%A0the%C2%A0distributed%C2%A0source%C2%A0packages%2C%C2%A0then%C2%A0you%C2%A0won/" t need these tools installed; the necessary pieces of the tools are already included in the source packages. but it?s useful to know a bit about how packages that use these tools work. a source package is distributed as a tar.gz file which you unpack into a directory full of the source files as follows: tar -zxvf gmime-2.0.0.tar.gz In the toplevel of the directory that is created, there will be a shell script called configure which you then run to take the template makefiles called Makefile.in in the package and create makefiles customized for your operating system. The configure script can be passed various command line arguments to determine how the package is built and installed. The most commonly useful argument is the --prefix argument which specifies where the package is installed. To install a package into /opt/gmime you would run configure as: ./configure --prefix=/opt/gmime A full list of options can be found by running configure with the --help argument. In general, the defaults are right and should be trusted. After you've run configure, you then run the make command to build the package and install it. make make install If you don't have permission to write to the directory you are installing in, you may have to change to root temporarily before running make install. A quick way to do this is to use the su command with the -c option (ex. su -c "make install"). Also, if you are installing in a system directory, on some systems (such as Linux), you will need to run ldconfig after make install so that the newly installed libraries will be found. Several environment variables are useful to pass to set before running configure. CPPFLAGS contains options to pass to the C compiler, and is used to tell the compiler where to look for include files. The LDFLAGS variable is used in a similar fashion for the linker. Finally the PKG_CONFIG_PATH environment variable contains a search path that pkg-config (see below) uses when looking for a file describing how to compile programs using different libraries. If you were installing GMime and it's dependencies into /opt/gmime, you might want to set these variables as: CPPFLAGS="-I/opt/gmime/include" LDFLAGS="-L/opt/gmime/lib" PKG_CONFIG_PATH="/opt/gmime/lib/pkgconfig" export CPPFLAGS LDFLAGS PKG_CONFIG_PATH You may also need to set the LD_LIBRARY_PATH environment variable so the systems dynamic linker can find the newly installed libraries, and the PATH environment program so that utility binaries installed by the various libraries will be found. LD_LIBRARY_PATH="/opt/gtk/lib" PATH="/opt/gmime/bin:$PATH" export LD_LIBRARY_PATH PATH Dependencies Before you can compile the GMime library, you need to have various other tools and libraries installed on your system. The two tools needed during the build process (as differentiated from the tools used in when creating GMime mentioned above such as autoconf) are pkg-config and GNU make. •pkg-config is a tool for tracking the compilation flags needed for libraries that are used by the GMime libraries. (For each library, a small .pc text file is installed in a standard location that contains the compilation flags needed for that library along with version number information.) The version of pkg-config needed to build GMime is mirrored in the dependencies directory on the GTK+ FTP site. •The GMime makefiles will mostly work with different versions of make, however, there tends to be a few incompatibilities, so the GMime team recommends installing GNU make if you don't already have it on your system and using it. (It may be called gmake rather than make.) GMime depends on the existance of two (2) libraries: GLib and iconv. •The GLib library provides core non-graphical functionality such as high level data types, Unicode manipulation, and a object and type system to C programs. It is available from the GTK+ FTP site. •The GNU libiconv library is needed to build GLib and GMime if your system doesn't already have the iconv() function for doing conversion between character encodings. Most modern systems should have iconv(). Building and testing GMime First make sure that you have the necessary external dependencies installed: pkg-config, GNU make, and, if necessary, libiconv. To get detailed information about building these packages, see the documentation provided with the individual packages. On a newer Linux system, it's quite likely that you'll have all of these installed already. Then build and install the GMime libraries in the order: libiconv, GLib, then GMime. For each library, follow the steps of configure, make, make install mentioned above. If you're lucky, this will all go smoothly, and you'll be ready to start compiling your own GMime applications. You can test your GMime installation by running pkg-config --modversion gmime-2.0 and making sure that it can both find GMime and reports the correct version. If one of the configure scripts fails or running make fails, look closely at the error messages printed; these will often provide useful information as to what went wrong. When configure fails, extra information, such as errors that a test compilation ran into, is found in the file config.log. Looking at the last couple of hundred lines in this file will frequently make clear what went wrong. If all else fails, you can ask for help by emailing me, [email protected]. Extra Configuration Options In addition to the normal options, the configure script for the GMime library supports a number of additional arguments. (Command line arguments for the other GMime libraries are described in the documentation distributed with the those libraries.) configure ' target=_blank>http://rpmfind.net. If you can find them, it may be the easiest way of getting started developing GMime. On UNIX-like systems GMime uses the standard GNU build system, using autoconf for package configuration and resolving portability issues, automake for building makefiles that comply with the GNU Coding Standards, and libtool for building shared libraries on multiple platforms. If you are building GMime from the distributed source packages, then you won't need these tools installed; the necessary pieces of the tools are already included in the source packages. But it's useful to know a bit about how packages that use these tools work. A source package is distributed as a tar.gz file which you unpack into a directory full of the source files as follows: tar -zxvf gmime-2.0.0.tar.gz In the toplevel of the directory that is created, there will be a shell script called configure which you then run to take the template makefiles called Makefile.in in the package and create makefiles customized for your operating system. The configure script can be passed various command line arguments to determine how the package is built and installed. The most commonly useful argument is the --prefix argument which specifies where the package is installed. To install a package into /opt/gmime you would run configure as: ./configure --prefix=/opt/gmime A full list of options can be found by running configure with the --help argument. In general, the defaults are right and should be trusted. After you've run configure, you then run the make command to build the package and install it. make make install If you don't have permission to write to the directory you are installing in, you may have to change to root temporarily before running make install. A quick way to do this is to use the su command with the -c option (ex. su -c "make install"). Also, if you are installing in a system directory, on some systems (such as Linux), you will need to run ldconfig after make install so that the newly installed libraries will be found. Several environment variables are useful to pass to set before running configure. CPPFLAGS contains options to pass to the C compiler, and is used to tell the compiler where to look for include files. The LDFLAGS variable is used in a similar fashion for the linker. Finally the PKG_CONFIG_PATH environment variable contains a search path that pkg-config (see below) uses when looking for a file describing how to compile programs using different libraries. If you were installing GMime and it's dependencies into /opt/gmime, you might want to set these variables as: CPPFLAGS="-I/opt/gmime/include" LDFLAGS="-L/opt/gmime/lib" PKG_CONFIG_PATH="/opt/gmime/lib/pkgconfig" export CPPFLAGS LDFLAGS PKG_CONFIG_PATH You may also need to set the LD_LIBRARY_PATH environment variable so the systems dynamic linker can find the newly installed libraries, and the PATH environment program so that utility binaries installed by the various libraries will be found. LD_LIBRARY_PATH="/opt/gtk/lib" PATH="/opt/gmime/bin:$PATH" export LD_LIBRARY_PATH PATH Dependencies Before you can compile the GMime library, you need to have various other tools and libraries installed on your system. The two tools needed during the build process (as differentiated from the tools used in when creating GMime mentioned above such as autoconf) are pkg-config and GNU make. •pkg-config is a tool for tracking the compilation flags needed for libraries that are used by the GMime libraries. (For each library, a small .pc text file is installed in a standard location that contains the compilation flags needed for that library along with version number information.) The version of pkg-config needed to build GMime is mirrored in the dependencies directory on the GTK+ FTP site. •The GMime makefiles will mostly work with different versions of make, however, there tends to be a few incompatibilities, so the GMime team recommends installing GNU make if you don't already have it on your system and using it. (It may be called gmake rather than make.) GMime depends on the existance of two (2) libraries: GLib and iconv. •The GLib library provides core non-graphical functionality such as high level data types, Unicode manipulation, and a object and type system to C programs. It is available from the GTK+ FTP site. •The GNU libiconv library is needed to build GLib and GMime if your system doesn't already have the iconv() function for doing conversion between character encodings. Most modern systems should have iconv(). Building and testing GMime First make sure that you have the necessary external dependencies installed: pkg-config, GNU make, and, if necessary, libiconv. To get detailed information about building these packages, see the documentation provided with the individual packages. On a newer Linux system, it's quite likely that you'll have all of these installed already. Then build and install the GMime libraries in the order: libiconv, GLib, then GMime. For each library, follow the steps of configure, make, make install mentioned above. If you're lucky, this will all go smoothly, and you'll be ready to start compiling your own GMime applications. You can test your GMime installation by running pkg-config --modversion gmime-2.0 and making sure that it can both find GMime and reports the correct version. If one of the configure scripts fails or running make fails, look closely at the error messages printed; these will often provide useful information as to what went wrong. When configure fails, extra information, such as errors that a test compilation ran into, is found in the file config.log. Looking at the last couple of hundred lines in this file will frequently make clear what went wrong. If all else fails, you can ask for help by emailing me, [email protected]. Extra Configuration Options In addition to the normal options, the configure script for the GMime library supports a number of additional arguments. (Command line arguments for the other GMime libraries are described in the documentation distributed with the those libraries.) configure [--enable-gprof] [--enable-warnings] --enable-gprof . Normally GMime will not pass the -pg flag to gcc when building. This option will enable the use of that flag thus building profiling information into the GMime libraries. Odds are you do not care about this option unless you are either me or desire to profile GMime and/or your program. --enable-warnings . This option enabled more verbose warnings to be used during compilation of the libraries. Again, it is unlikely you will care to use this option. d) 四、解码程序开发 a)例程 1 #include <stdio.h> 2 #include <gmime/gmime.h> 3 void Walk(GMimeObject* pPart,int nDepth) 4 { 5 printf("Geting %d part content type.../n",nDepth); 6 const GMimeContentType* pContentType = g_mime_object_get_content_type(pPart) ; 7 char* szContentType = g_mime_content_type_to_string(pContentType); 8 printf("The content type is: %s or direct get from the object(%s/%s)/n",szContentType,pContentType->type,pCont entType->subtype); 9 g_free(szContentType); 10 11 char* szObject = g_mime_object_to_string(pPart); 12 // printf("The object is :%s/n",szObject); 13 g_free(szObject); 14 15 const char* szHeader = g_mime_object_get_headers(pPart); 16 printf("The object's header is:%s/n",szHeader); 17 const char* szContentId = g_mime_object_get_content_id (pPart); 18 printf("The object's content id is:%s/n",szContentId); 19 20 if(GMIME_IS_MULTIPART(pPart)) 21 { 22 GMimeMultipart* pMultipart = GMIME_MULTIPART(pPart); 23 printf("The GMimeObject can convert to GMimeMultiPart object.../n"); 24 printf("The multipart preface is: %s/n",g_mime_multipart_get_preface (GMIME_MULTIPART(pPart))); 25 printf("The multipart number is %d/n",g_mime_multipart_get_number (pMultipart)); 26 printf("The multipart boundary is:%s/n",g_mime_multipart_get_boundary (pMultipart)); 27 28 GList* pSubParts = pMultipart->subparts; 29 30 if(pSubParts==NULL) 31 printf("The multipart has no subparts, wrong mail????/n"); 32 int j=0; 33 while(pSubParts) 34 { 35 pSubParts = pSubParts->next; 36 printf("multi part no%d/n",j++); 37 } 38 39 } 40 } 41 void Analyze(GMimeMessage* pMessage) 42 { 43 printf("analyze the message begin.../n"); 44 Walk(pMessage->mime_part,0); 45 } 46 int main(int argc,char** argv) 47 { 48 g_mime_init(0); 49 if(argc<2) 50 { 51 printf("error open file to parser. hello <file>/n"); 52 return 0; 53 } 54 printf("hello, gmime! please/n"); 55 56 FILE* fp = fopen(argv[1],"rb"); 57 GMimeStream* pStream = g_mime_stream_file_new(fp); 58 59 60 printf("[main] g_mime_stream_file_new success!/n"); 61 62 GMimeFilter* pCrlfFilter = g_mime_filter_crlf_new (GMIME_FILTER_CRLF_DECODE,GMIME_FILTER_CRLF_MODE_CRLF_ONLY); 63 printf("[main] new crlf filter success!/n"); 64 65 GMimeStream* pFilterStream = g_mime_stream_filter_new_with_stream (pStream); 66 printf("[main] create filter stream with file stream success!/n"); 67 printf("unref the stream object./n"); 68 g_mime_stream_unref(pStream); 69 70 g_mime_stream_filter_add (GMIME_STREAM_FILTER (pFilterStream), pCrlfFilter); 71 g_object_unref (pCrlfFilter); 72 printf("[main] add crlf filter to decode success!/n"); 73 74 GMimeParser* pParser = g_mime_parser_new(); 75 if(!pParser) 76 { 77 printf("error new parser./n"); 78 } 79 printf("new parser success!/n"); 80 81 82 83 g_mime_parser_init_with_stream(pParser,pFilterStream); 84 GMimeMessage* pMessage = g_mime_parser_construct_message(pParser); 85 if(!pMessage) 86 { 87 printf("error construct the message!/n"); 88 return 0; 89 } 90 printf("construct message with filter stream success!/n"); 91 92 printf("unref the filter stream./n"); 93 g_mime_stream_unref(pFilterStream); 94 printf("unref the parser object./n"); 95 g_object_unref(pParser); 96 97 printf("sender:%s/n",g_mime_message_get_sender(pMessage)); 98 printf("rcpt to:%s/n",g_mime_message_get_reply_to (pMessage)); 99 printf("subject:%s/n",g_mime_message_get_subject (pMessage)); 100 gboolean is_html; 101 printf("body:%s/n",g_mime_message_get_body (pMessage,true,&is_html)); 102 103 Analyze(pMessage); 104 printf("unref the pMessage object./n"); 105 g_object_unref(GMIME_OBJECT(pMessage)); 106 return 1; 107 } b)编译方法: c++ `pkg-config --cflags --libs gmime-2.0` hello.cpp -o hello c)代码介绍 第2行,必须包含<gmime/gmime.h>,才能使用GMIME库的接口。 第46行,main开始 该程序要求带一个参数,作为要分析的邮件原始文件名。 48行,g_mime_init(0) 必须在所有GMIME函数调用之前调用。 57行,创建一个基于文件的流对象,流对象见上述。 62行,创建一个CRLF过滤器,过滤器介绍见前述。一般而言,MTA之间的通信每行都是以/n结尾的,但因为我们要处理以CRLF结尾的邮件体,所以必须附加一个CRLF过滤器来处理/r/n. 65行,根据初始文件流和过滤器创建一个具备过滤功能的流对象。 74行,创建一个MIME解析器,分析器可对一封邮件进行解析,生成消息对象。在消息对象对邮件消息进行结构化的存储。通过消息对象可以遍历邮件各部分内容。 83行,根据输入流对象对MIME解析器进行初始化。 84行,利用MIME解析器生成消息对象。 97-99行,获取消息对象中的“发信人”、“收信人”和“主题”。 101行,从消息对象中获取邮件体。 28行, 对一个混合型邮件体,获取其混合对象链表。利用该链表对象可遍历混合体中的各部分。 33-37行,遍历组成混合体的各部分邮件体对象。 |