分享

javamail的简单实现--lotusxyhf

 pint 2010-09-08
javamail的简单实现

1。基本的发邮件操作

public static void sendMessage
    (
     Session session,
        String from,
        String[] to,
        String[] cc,
        String[] bcc,
        String subject,
        String content,
        String mimeType
    )
    throws MessagingException
    {
        Message message = new MimeMessage(session);

        // n.b. any default from address is expected to be determined by caller.
        if (! StringUtils.isEmpty(from)) {
   InternetAddress sentFrom = new InternetAddress(from);
   message.setFrom(sentFrom);
   if (mLogger.isDebugEnabled()) mLogger.debug("e-mail from: " + sentFrom);
        }

  if (to!=null)
  {
   InternetAddress[] sendTo = new InternetAddress[to.length];
 
   for (int i = 0; i < to.length; i++)
   {
    sendTo[i] = new InternetAddress(to[i]);
    if (mLogger.isDebugEnabled()) mLogger.debug("sending e-mail to: " + to[i]);
   }
   message.setRecipients(Message.RecipientType.TO, sendTo);
  }

  if (cc != null)
  {
   InternetAddress[] copyTo = new InternetAddress[cc.length];

   for (int i = 0; i < cc.length; i++)
   {
    copyTo[i] = new InternetAddress(cc[i]);
    if (mLogger.isDebugEnabled()) mLogger.debug("copying e-mail to: " + cc[i]);
   }
   message.setRecipients(Message.RecipientType.CC, copyTo);
  }        

  if (bcc != null)
  {
   InternetAddress[] copyTo = new InternetAddress[bcc.length];

   for (int i = 0; i < bcc.length; i++)
   {
    copyTo[i] = new InternetAddress(bcc[i]);
    if (mLogger.isDebugEnabled()) mLogger.debug("blind copying e-mail to: " + bcc[i]);
   }
   message.setRecipients(Message.RecipientType.BCC, copyTo);
  }        
        message.setSubject((subject == null) ? "(no subject)" : subject);
        message.setContent(content, mimeType);

  // First collect all the addresses together.
        Address[] remainingAddresses = message.getAllRecipients();
        int nAddresses = remainingAddresses.length;
        boolean bFailedToSome = false;
       
        SendFailedException sendex = new SendFailedException("Unable to send message to some recipients");
       
  // Try to send while there remain some potentially good addresses
  do
        {
   // Avoid a loop if we are stuck
   nAddresses = remainingAddresses.length;

   try
   {
    // Send to the list of remaining addresses, ignoring the addresses attached to the message
          Transport.send(message,remainingAddresses);
   }
   catch(SendFailedException ex)
   {
    bFailedToSome=true;
    sendex.setNextException(ex);
    
    // Extract the remaining potentially good addresses
    remainingAddresses=ex.getValidUnsentAddresses();
   }
        } while (remainingAddresses!=null && remainingAddresses.length>0 && remainingAddresses.length!=nAddresses);
       
        if (bFailedToSome) throw sendex;
    }

 

2。附件的发送:

发送附件非常像转发消息。您建立各部分以组成完整消息。完成第一部件,即消息正文后,您添加其它部件,其中每个 DataHandler 都代表附件,而不是转发消息情况下的共享处理程序。如果从文件中读附件,附件的数据源是 FileDataSource。而如果从 URL 中读时,附件的数据源是 URLDataSource。一旦存在 DataSource,只要先把它传递给 DataHandler 构造器,最后再用 setDataHandler() 把它附加到 BodyPart。假定您要保留附件的原始文件名,最终要做的是用 BodyPart 的 setFileName() 方法设置与附件相关的文件名。如下所示:

 // Define message
 Message message = new MimeMessage(session);
 message.setFrom(new InternetAddress(from));
 message.addRecipient(Message.RecipientType.TO,
  new InternetAddress(to));
 message.setSubject("Hello JavaMail Attachment");

 // Create the message part
 BodyPart messageBodyPart = new MimeBodyPart();

 // Fill the message
 messageBodyPart.setText("Pardon Ideas");

 Multipart multipart = new MimeMultipart();
 multipart.addBodyPart(messageBodyPart);

 // Part two is attachment
 messageBodyPart = new MimeBodyPart();
 DataSource source = new FileDataSource(filename);
 messageBodyPart.setDataHandler(new DataHandler(source));
 messageBodyPart.setFileName(filename);
 multipart.addBodyPart(messageBodyPart);

 // Put parts in message
 message.setContent(multipart);

 // Send the message
 Transport.send(message);

  就消息引入附件时,若程序是个 servlet (小服务程序),除告知消息发送到何处外,还必需上载附件。可以将 multipart/form-data 表单编码类型(form encoding type)用于每个上载文件的处理。
注意:消息大小由 SMTP 服务器而不是 JavaMail API 来限制。
 
3:附件的获取:
从消息中获取附件比发送它们棘手些,因为 MIME 没有简单的关于附件的概念。当消息包含附件时,消息的内容是个 Multipart 对象。接着,您需要处理每个 Part,获取主要内容和附件。标有从 part.getDisposition() 获得的 Part.ATTACHMENT 配置(disposition)的部件(Part)无疑就是附件。但是,没有配置(以及一个非文本 MIME 类型)和带 Part.INLINE 配置的部件也可能是附件。当配置要么是 Part.ATTACHMENT,要么是 Part.INLINE 时,这个消息部件的内容就能被保存。只要用 getFileName() 和 getInputStream() 就能分别得到原始文件名和输入流。

Multipart mp = (Multipart)message.getContent();
for (int i=0, n=multipart.getCount(); i<n; i++) {
 Part part = multipart.getBodyPart(i));
 String disposition = part.getDisposition();
 if ((disposition != null) &&
   ((disposition.equals(Part.ATTACHMENT) ||
     (disposition.equals(Part.INLINE))) {
  saveFile(part.getFileName(), part.getInputStream());
 }
}

  saveFile() 方法仅依据文件名创建了一个 File,它从输入流中将字节读出,然后写入到文件中。万一文件已经存在,就在文件名后添加一个数字作为新文件名,如果这个文件名仍存在,则继续添,直到找不到这样的文件名为止。

// from saveFile()
File file = new File(filename);
for (int i=0; file.exists(); i++) {
file = new File(filename+i);
}

  上面的代码涵盖了最简单的情况 - 消息中各部件恰当的标记了。要涵盖所有情况,还要在配置为空时进行处理,并且获取部件的 MIME 类型来进行相应处理。

if (disposition == null) {
 // Check if plain
 MimeBodyPart mbp = (MimeBodyPart)part;
 if (mbp.isMimeType("text/plain")) {
  // Handle plain
 } else {
  // Special non-attachment cases here of image/gif, text/html, ...
 }
...
}
 
如何一次发送多个邮件?

  取得必要的Transport对象并调用SendMessage()发送每一个邮件。注意在调用之间设置或改变接收者。

    Message message = …;
    Transport t = session.getTransport("smtp");
    t.connect();
message.setRecipient(Message.RecipientType.TO,recipient1);
t.sendMessage(message,recipient);
message.setRecipient(Message.RecipientType.TO,recipient2);
t.sendMessage(message,recipient);
message.setRecipient(Message.RecipientType.TO,recipient3);
t.sendMessage(message,recipient);
t.close();

  如何保存邮件?

  用MimeMessage类的writeTo()方法可以实现。用Message类的对象不能实现。

    FileOutputStream fos = new FileOutputStream("test.mail");
    Mimemessage.writeTo(fos);

  怎样发送带有图像的HTML格式邮件?

  一些图像还是放在服务器上较好,让用户的邮件工具处理。读者可以将图像作为附件或HTML体发送。如果所有附件保存在同一个目录下,那么必须用不同的图像文件名以确保邮件工具不会显示其他图片。另外图像URL要用绝对路径,不能用相对路径。

  如何设置∕获取邮件的优先级?

  设置邮件的优先级,只需在消息头中添加"X-Priority"属性:
  MimeMessage msg;
  Msg.addHeader("X-Priority","1");
  同样道理,要获取邮件的优先级只要获取"X-Priority"属性的值就可以了:
String priority = msg.getHeader("X-Priority");

  附录:Java Mail API的基本概念

  什么是Java Mail API

  JavaMail API 是一个用于阅读、编写和发送电子邮件的可选包(标准扩展)。与 Eudora、pine 及 Microsoft Outlook 相似,这个包用来创建邮件用户代理(Mail User Agent,MUA) 类型程序。API 的主要用途并不在于传输、发送和转发消息;这一功能范围属于某些应用程序,如 sendmail 及其它邮件传输代理(Mail Transfer Agent,MTA)类型程序。MUA 类型的程序能让用户阅读和书写邮件,而它却依赖 MTA 处理实际发送。

  什么是SMTP

  SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议,它定义了发送电子邮件的机制。在 JavaMail API 环境中,基于 JavaMail 的程序将和您的公司或因特网服务供应商的(Internet Service Provider's,ISP's)SMTP 服务器通信。SMTP 服务器可将消息中转至接收方 SMTP 服务器,以便最终让用户经由 POP 或 IMAP 获得。这不是要求 SMTP 服务器成为开放的中继,尽管 SMTP 服务器支持身份验证,不过还是得确保它的配置正确。像配置服务器来中继消息或添加删除邮件账号这类任务的实现,JavaMail API 中并不支持。

  什么是POP

  POP(Post Office Protocol),即邮局协议。目前用的是版本3,所以人们通常将它称为 POP3,RFC 1939 定义了这个协议。POP 和SMTP一样,也是一种机制,Internet上大多数人通过它得到邮件。该协议规定每个用户只能有一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。所以当使用 JavaMail API 时,如果读者想要这类信息,就只能由自己来计算了。

  什么是IMAP

  IMAP(Internet Message Access Protocol),即Internet消息访问协议,是更高级的用于接收消息的协议,在 RFC 2060 中有它的定义。目前使用的IMAP版本为4,人们习惯将它称为 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况--用户在服务器上可以有多个文件夹(folder),并且这些文件夹可以被多个用户共享。
  因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。

  什么是MIME

  MIME(Multipurpose Internet Mail Extensions),即多用途Internet邮件扩展标准。它不是邮件传输协议,而是对传输内容的消息、附件及其它的内容定义了格式。这里有很多不同的RFC(Requirement of Comment)文档:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。作为一个 JavaMail API 的用户,您通常不必对这些格式操心。无论如何,一定存在这些格式而且程序会用到它。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多