程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 用JavaMail發送帶附件的Email

用JavaMail發送帶附件的Email

編輯:關於JAVA

隨著網絡應用的不斷推廣,電子郵件越來越多的被大家使用。雖然我們往往將電子郵件與 Foxmail、Outlook 這樣的電子郵件客戶端聯系起來,但是往往我們也需要自己編程實現發送接收郵件,例如在一個網站注冊用戶後網站發出的回執mail,或者在網絡購物的時候,在完成訂單後的幾分鐘之內發送確認電子郵件。對於這樣的需求,我們不能通過已有的郵件客戶端而需要自己編寫郵件發送或者處理程序。在這裡向大家講解一下如何利用JavaMail來實現郵件的收發。

注意:本文只打算討論JavaMail收發帶附件郵件的一些技巧,所以只是給出部分代碼。

1.發送帶附件的郵件

我們平時發送的郵件主要可以分解成2大部分,一個是發信人,接信人,主題等郵件標頭,另外一部分是郵件內容,它包括了郵件的附件。我們在發送普通郵件的時候content設置的類型是"text/html",帶上附件後,我們需要把content的類型設置成Multipart,這時content包括了附件和"text/html"類型的正文。下面的這個告訴大家如何把附件放置到郵件中。

private Multipart getMultipart() throws MessagingException,UnsupportedEncodingException
{
  MimeMultipart mp = new MimeMultipart();
  try
  {
   //設置content裡的內容
   MimeBodyPart contentMbp = new MimeBodyPart();
   //請指定字符集,否則會是亂碼
   contentMbp.setContent(_mailContent.getContent(), "text/html; charset=GB2312");
   mp.addBodyPart(contentMbp); //添加附件
   for (int i=0;i<_mailAttachment.getAttachPath().size();i++)
   {
    MimeBodyPart mbp = new MimeBodyPart();
    FileDataSource fds = new FileDataSource((String) _mailAttachment.getAttachPath().get(i));
    mbp.setDataHandler(new DataHandler(fds));
    mbp.setFileName(MimeUtility.encodeWord(fds.getName(), "GB2312",null));
    mp.addBodyPart(mbp);
   }
  }
  catch(MessagingException ie)
  {
   System.out.println("Set Content Message error..."+ie.getMessage());
   throw ie;
  }
  catch(UnsupportedEncodingException ie)
  {
   System.out.println("Encode the fileName error..."+ie.getMessage());
   throw ie;
  }
  return mp;
}

放置附件的注意事項如下:

在發mail時需要注意字符集的問題。不但content裡要設置,而且文件名也需要設置。如果我們去掉mbp.setFileName(MimeUtility.encodeWord(fds.getName(),"GB2312",null));這句話,那麼你選中的附件還是會帶到郵件裡,但是在附件裡看不到。我們可以通過查看郵件大小知道。我們利用這個特點來實現發送content中寫的是html語言,而且包含圖片信息的郵件。

2.發送content中包含html頁面的郵件

大家都知道html語言可以帶上圖片鏈接(<img src=”c:/test.jpg”></img>),那麼我們在發送郵件的時候就需要對這些鏈接的圖片做特殊處理。否則在對方接收到郵件的時候會看不到圖片。我們特殊處理的方法就是把它們當成附件發送,但不顯示在附件裡。要做到這些就首先需要對輸入的content進行解析,找到所帶圖片的路徑。然後把content中<img src=”c:/test.jpg”></img>這段代碼變成<img src=” cid:IMG”></img>。我們在發送附件的時候用mbp1.setHeader("Content-ID","IMG") 來把圖片和附件對應上。如何具體解析content的操作我就不贅述了,我現在給出如何把修改好的content發送出去的例子。

//對於發送html類型的content,裡邊包括圖片。

for(int i=0;i<_mailContent.getImgHash().size();i++)
{
  MimeBodyPart mbp1 = new MimeBodyPart();
  //得到圖片的數據
  FileDataSource fds = new FileDataSource( (String)_mailContent.getImgHash().get("IMG"+i));
  //設置到MimeBodyPart中
  mbp1.setDataHandler(new DataHandler(fds));
  //設置圖片附件和html的對應關系
  mbp1.setHeader("Content-ID","IMG"+i);
  mp.addBodyPart(mbp1);
}

3.郵件的狀態

我們在閱讀完郵件後可以給郵件設置刪除標志,然後在關閉FOLDER的時候用true來清空已經被標志為刪除的郵件。郵件的狀態是在類FLAGS.FLAG中定義的。包括如下幾種:

Flags.Flag.ANSWERED
Flags.Flag.DELETED
Flags.Flag.DRAFT
Flags.Flag.FLAGGED
Flags.Flag.RECENT
Flags.Flag.SEEN
Flags.Flag.USER

我們可以根據不同的需要進行設置,但是需要注意的是,不是所有的服務器都支持這些狀態。我們在做操作之前可以用getPermanentFlags方法來得到Message中的狀態。參考下面代碼

Message m = folder.getMessage(1);
// set the DELETED flag
m.setFlag(Flags.Flag.DELETED, true);
// Check if DELETED flag is set of this message
if (m.isSet(Flags.Flag.DELETED))
  System.out.println("DELETED message");
  // Examine ALL system flags for this message
Flags flags = m.getFlags();
Flags.Flag[] sf = flags.getSystemFlags();
for (int i = 0; i < sf.length; i++)
{
  if (sf[i] == Flags.Flag.DELETED)
   System.out.println("DELETED message");
  else if (sf[i] == Flags.Flag.SEEN)
   System.out.println("SEEN message");
}

4.接收帶附件的郵件

在帶有附件的郵件中,消息的內容是Multipart型,這樣我們就需要解析它來得到content和附件(它是發送帶附件的郵件的逆向過程)。大家在使用outlook、foxmail這些電子郵件客戶端的時候會發現,我們的郵件被從服務器上下載下來並且保存到本地硬盤上了,這種方式方便我們離線浏覽郵件。在下面的范例中我們也把服務器上的郵件保存到本地。如果有興趣大家可以編寫一個客戶端的圖形界面來讀取保存下來的郵件。

在下面的例子裡,我只是向大家介紹如何解析附件。

private void getAttachFile(Part messagePart,BufferedOutputStream writeAttachObj) throws IOException, MessagingException { Object content = messagePart.getContent() ;
try
  {
   //這種情況下的郵件都是用multi模式發送的,
   // 這種模式包括有附件的郵件和用html表示content的郵件
   if (content instanceof Multipart)
   {
    Multipart contentTmp = (Multipart) content ;
    //如果是MULTI模式發送的,BodyPart(0).getContent()肯定就是content
    System.out.println("content==" + contentTmp.getBodyPart(0).getContent()) ;
    //getCount()可以得到content中bodyPart的個數,content就是第一個
     //bodyPart,其它的附件按照順序類推。但是有的時候附件就是另外一個郵件,
    //而這個郵件裡邊可能有其他的附件。下面代碼用循環對嵌套情況進行解析。
   for (int i = 0 ; i < contentTmp.getCount() ; i++)
   {
    if (contentTmp.getBodyPart(i).isMimeType("multipart/*"))
    {
     Multipart multipart = (Multipart) contentTmp.getBodyPart(i).getContent() ;
     //這個地方增加循環是為了解決嵌套附件的情況。
    for (int k = 0 ; k < multipart.getCount() ; k++)
    {
     //content也會存在於INPUTSTREAM中。
     saveAttacheFile(multipart.getBodyPart(k).getContentType(), multipart.getBodyPart(k).getDisposition(), multipart.getBodyPart(k).getFileName(), multipart.getBodyPart(k).getInputStream(), writeAttachObj);
    }
   }
   else
   {
    saveAttacheFile(contentTmp.getBodyPart(i).getContentType(), contentTmp.getBodyPart(i).getDisposition(), contentTmp.getBodyPart(i).getFileName(), contentTmp.getBodyPart(i).getInputStream(), writeAttachObj);
   }
   }
  }
  //這種情況中郵件是純文本形式,並且沒有附件

  else
  {
   writeAttachObj.write(("content = "+content+"\r\n").getBytes()); writeAttachObj.flush();
  }
  }
  catch (Exception ie)
  {
   System.out.println("exception====" + ie.getMessage()) ;
  }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved