最近在研究javamail自认为解决不少感觉挺有点难度的问题,呵,但有一个看起来很简单的问题,
我却一直没有弄出来,言归正传.我们知道,当一封邮件含混合内容时,常在邮件头里设置一行说明,如:
This is a multi-part message in MIME format.
前后各空一行,就是这行,我此不知道怎么加入,其它的字段如: subject等等,都可以
使用:mimeMessage.setSubject(subject)
或mimeMessage.setHeader("subject", subject);来设置,可这行怎么写入呢?

解决方案 »

  1.   

    当收到邮件后进行解析,我们可以看到如下的邮件代码(注意为了便于阅读,已经将分隔符替换为比较容易阅读的格式):Received: from 127.0.0.1 by FMS4711; Fri, 25 Jul 2008 13:02:36 +0800
    Date: Fri, 25 Jul 2008 13:02:36 +0800
    From: "beansoft" <[email protected]>
    To: "hp" <[email protected]>
    Subject: =?gb2312?B?wb249ri9vP4=?=
    Message-ID: <[email protected]>
    X-mailer: Foxmail 6, 13, 102, 15 [cn]
    Mime-Version: 1.0 Content-Type: multipart/mixed;
        boundary="===========分割一============" This is a multi-part message in MIME format. --===========分割一============
      Content-Type: multipart/alternative;
        boundary="===========分割2================="   --===========分割2=================
      Content-Type: text/plain;
        charset="gb2312"
      Content-Transfer-Encoding: 7bit   Body   --===========分割2=================
      Content-Type: text/html;
        charset="gb2312"
      Content-Transfer-Encoding: 7bit   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
      <HTML><HEAD>
      <META http-equiv=Content-Type content="text/html; charset=GB2312">
      <META content="MSHTML 6.00.5730.13" name=GENERATOR><LINK 
      href="BLOCKQUOTE{margin-Top: 0px; margin-Bottom: 0px; margin-Left: 2em}" 
      rel=stylesheet></HEAD>
      <BODY style="FONT-SIZE: 10pt; MARGIN: 10px; FONT-FAMILY: verdana">
      <DIV><FONT face=Verdana size=2><STRONG>Body</STRONG></FONT></DIV><FONT 
      face=Verdana size=2>
      <DIV>&nbsp;</DIV></FONT></BODY></HTML> --===========分割2=================-- --===========分割一============
    Content-Type: application/octet-stream;
        name="String2Java.jpg"
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment;
        filename="String2Java.jpg" /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a
    oAKKKKACiiigAooooA//2Q== --===========分割一============
    Content-Type: application/octet-stream;
        name="FoxmailUpdate.log"
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment;
        filename="FoxmailUpdate.log" OAAAAPgb7GHGsCG8a8W48hC9ihdb8CcIlHlKXcYwNP+8dPRB30zrsI2K4TPJP0gYLB3Cua0JRtBL
    g/z8XA5PJneuwd9Uiu0nEH4Iobo+12oK9hsKK7xFXYhw++a50FHQuCDXX5kpF2d6 --===========分割一============--
      
      

  2.   

    它对应JavaMail的Message对象,一个Message对象又会有多个子对象如MultiPart对象,更特殊的是整个邮件内容为一个大的MultiPart,然而邮件的正文则在嵌套的一个子MultiPart中,如果不了解这种组织结构,就可能无法正确获得邮件的正文。此结构如下图,图楼主可以参考http://www.blogjava.net/beansoft/archive/2008/08/02/219599.html
    有了这些资料,我们就可以来解析邮件了,代码如下:
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.Properties; import javax.mail.Address;
    import javax.mail.BodyPart;
    import javax.mail.FetchProfile;
    import javax.mail.Flags;
    import javax.mail.Folder;
    import javax.mail.Message;
    import javax.mail.MessagingException;
    import javax.mail.Multipart;
    import javax.mail.NoSuchProviderException;
    import javax.mail.Part;
    import javax.mail.Session;
    import javax.mail.Store;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMultipart; /**
    * 邮件接受测试

    */
    public class POP3MailReceiverTest {     public POP3MailReceiverTest() {
            try {
                // 1. 设置连接信息, 生成一个 Session
                Properties props = new Properties();
                props.put("mail.transport.protocol", "pop3");// POP3 收信协议
                props.put("mail.pop.port", "110");
                // props.put("mail.debug", "true");// 调试             Session session = Session.getInstance(props);             // 2. 获取 Store 并连接到服务器
                Store store = session.getStore("pop3");
                store.connect("localhost", "[email protected]", "1234");
                // 3. 通过 Store 打开默认目录 Folder
                Folder folder = store.getDefaultFolder();// 默认父目录
                if (folder == null) {                 System.out.println("服务器不可用");
                    return;
                    // System.exit(1);
                } //            System.out.println("默认信箱名:" + folder.getName());
    //
    //            Folder[] folders = folder.list();// 默认目录列表
    //
    //            System.out.println("默认目录下的子目录数: " + folders.length);             Folder popFolder = folder.getFolder("INBOX");// 获取收件箱
                popFolder.open(Folder.READ_WRITE);// 可读邮件,可以删邮件的模式打开目录
                // 4. 列出来收件箱 下所有邮件
                Message[] messages = popFolder.getMessages();
                // 取出来邮件数
                int msgCount = popFolder.getMessageCount();
                System.out.println("共有邮件: " + msgCount + "封");             // FetchProfile fProfile = new FetchProfile();// 选择邮件的下载模式,
                // 根据网速选择不同的模式
                // fProfile.add(FetchProfile.Item.ENVELOPE);
                // folder.fetch(messages, fProfile);// 选择性的下载邮件             // 5. 循环处理每个邮件并实现邮件转为新闻的功能
                for (int i = 0; i < msgCount; i++) {
                    Message msg = messages[i];// 单个邮件
                    // 发件人信息
                    Address[] froms = msg.getFrom();
                    if(froms != null) {
                        System.out.println("发件人信息:" + froms[0]);
                        InternetAddress addr = (InternetAddress)froms[0];
                        System.out.println("发件人地址:" + addr.getAddress());
                        System.out.println("发件人显示名:" + addr.getPersonal());
                    }
                    News news = new News();// 生成新闻对象
                    System.out.println("邮件主题:" + msg.getSubject());
                    news.setTitle(msg.getSubject());                 // getContent() 是获取包裹内容, Part 相当于外包装
                    Multipart multipart = (Multipart) msg.getContent();// 获取邮件的内容, 就一个大包裹,
                                                                    // MultiPart
                                                                        // 包含所有邮件内容(正文+附件)
                    System.out.println("邮件共有" + multipart.getCount() + "部分组成");                 // 依次处理各个部分
                    for (int j = 0, n = multipart.getCount(); j < n; j++) {
                        System.out.println("处理第" + j + "部分");
                        Part part = multipart.getBodyPart(j);//解包, 取出 MultiPart的各个部分, 每部分可能是邮件内容,
                        // 也可能是另一个小包裹(MultipPart)                     // 判断此包裹内容是不是一个小包裹, 一般这一部分是 正文 Content-Type: multipart/alternative
                        if (part.getContent() instanceof Multipart) {
                            Multipart p = (Multipart) part.getContent();// 转成小包裹
                            System.out.println("小包裹中有" + p.getCount() + "部分");
                            // 列出小包裹中所有内容
                            for (int k = 0; k < p.getCount(); k++) {
                                System.out.println("小包裹内容:" + p.getBodyPart(k).getContent());
                                System.out.println("内容类型:"
                                        + p.getBodyPart(k).getContentType());
                                if(p.getBodyPart(k).getContentType().startsWith("text/plain")) {
                                    // 处理文本正文
                                    news.setBody(p.getBodyPart(k).getContent() + "");
                                } else {
                                    // 处理 HTML 正文
                                    news.setBody(p.getBodyPart(k).getContent() + "");
                                }
                            }
                        }                     // Content-Disposition: attachment;    filename="String2Java.jpg"
                        String disposition = part.getDisposition();// 处理是否为附件信息
                        if (disposition != null) {                         System.out.println("发现附件: " + part.getFileName());
                            System.out.println("内容类型: " + part.getContentType());
                            System.out.println("附件内容:" + part.getContent());
                            java.io.InputStream in = part.getInputStream();// 打开附件的输入流
                            // 读取附件字节并存储到文件中
                            java.io.FileOutputStream out = new FileOutputStream(part.getFileName());
                            int data;
                            while((data = in.read()) != -1) {
                                out.write(data);
                            }
                            in.close();
                            out.close();
                        }
                    }
                    // }
                    // TODO newsDAO.save(news); // 将邮件所携带的信息作为新闻存储起来                 // 6. 删除单个邮件, 标记一下邮件需要删除, 不会真正执行删除操作
                    // msg.setFlag(Flags.Flag.DELETED, true);
                }             // 7. 关闭 Folder 会真正删除邮件, false 不删除
                popFolder.close(true);
                // 8. 关闭 store, 断开网络连接
                store.close();
            } catch (NoSuchProviderException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }     /**
         * @param args
         */
        public static void main(String[] args) {
            new POP3MailReceiverTest();     } }
      

  3.   

    貌似跟 http 协议 有些像 内容中已空行表示结束某种输入以前也写过邮件收发 
    记得没有必要care 这个问题的具体 记不清了
    貌似 java mail 会根据你 你设置的MIME  类型 自动添加的 
      

  4.   


    感觉这个说明是在邮件头与邮件体之间,分析邮件内容可以知道(看一楼的就行),它是在整体分割线的上方,感觉并不属于邮件体,如何直接加入呢?
    我把整个邮件体看作是一个MimeMultipart对象,邮件体各个部分的MimeBodyPart对象再往MimeMultipart对象中增加,
    如:allMultipart.addBodyPart(bodyPart1);那这行说明是在MimeMultipart对象对象中设置还是MimeBodyPart对象中设置呢?
    感觉应该是前者,可没设置成功....注:这行说明有点怪,它的前后都空了一行的,应该也不属于邮件头,可能是属于邮件体,但这样总觉得别扭.
      

  5.   

    为了让方便大家更好的参与,我把可执行代码贴出来,大家有空也试试吧,可以在此基础上添加修改即可,我实在不知道怎么弄了,虽然不加这也可用,但没解决总觉得不爽,呵,不知道这是不是程序员的通病.import java.io.FileOutputStream;
    import java.util.Properties;import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import javax.mail.Message;
    import javax.mail.Session;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeBodyPart;
    import javax.mail.internet.MimeMessage;
    import javax.mail.internet.MimeMultipart;/**
     * 
     * 注:本代码可以直接运动并在c盘根目录生成abc.eml邮件,使用时要导入mail.jar包,不然无法使用.
     * 生成的abc.eml文件用记事本打开,就可知道结果
     *
     */
    public class BirthMail
    {
    public static void main(String[] args) throws Exception
    {

            MimeMessage mimeMessage = BirthMail.createMessage();
            
            mimeMessage.saveChanges();//存储邮件内容
            mimeMessage.writeTo(new FileOutputStream( "c:\\abc.eml"));//保存邮件到磁盘 }

    public static MimeMessage createMessage() throws Exception
    {
    Session session = Session.getDefaultInstance(new Properties());
            
            MimeMessage mimeMessage = new MimeMessage(session); 
            mimeMessage.setSubject("mail subject");//邮件主题设置     
            
            mimeMessage.setFrom(new InternetAddress("[email protected]"));
            mimeMessage.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]"));//设置收件人        
            
            MimeMultipart allMultipart = new MimeMultipart("mixed"); MimeBodyPart attachmentPart = new MimeBodyPart();
            FileDataSource fileDataSource = new FileDataSource("d:\\a.bmp");//随便指定一个附件路径即可
            attachmentPart.setDataHandler(new DataHandler(fileDataSource));     allMultipart.addBodyPart(attachmentPart);//添加附件
          
         /*
          * This is a multi-part message in MIME format.这句说明怎么添加进去呢?其前后要空一行
          */
        
            mimeMessage.setContent(allMultipart);//设置整个邮件内容                return mimeMessage;
    }
    }
    注:如果会的话,那是一下子就做出来了,感觉是不难的,呵.
      

  6.   

    看来这里研究javamail的朋友不是很多吧,期待这方面的高人出现...
      

  7.   

    自己顶下吧,手头方便的希望可以帮忙试下,谢了!这对以后有机会开发javamail之类的,也会有一定的帮助的.
      

  8.   

    若直接在attachmentPart 中添加,如:加入这行:
    attachmentPart.addHeaderLine("This is a multi-part message in MIME format.");
    则这行说明会出现在Content-Transfer-Encoding: base64之后,还是没达到目的.感觉就那个几个方法,该试的也都试了,很怪,那到底能不能加入呢?
    自己还真的怀疑了,到底javamail能不能实现呢?不然,这么大的论坛也没人懂,就放着吧,但愿到时别无满意结贴吧.
      

  9.   

    你思路不对,不能在MimeBodyPart中加的,要在mimeMessage中加的,我给你试了下,加入下面两行就行了
    mimeMessage.addHeaderLine("\n");//这行是为留空行而加的
    mimeMessage.addHeaderLine("This is a multi-part message in MIME format.");