2010-11-11 52 views
4

使用Spring 3.0,我编写了一个接口,以从应用程序中隐藏我用于发送邮件的模板引擎。该接口是Spring的JavaMailSenderImpl抛出一个异常,但仍然发送电子邮件

public interface MailSender { 
    public void send(String[] to, String from, String subject, String template, 
     Map<Object, Object> model, boolean isHtml, 
     Map<String, Resource> attachments, 
     Map<String, Resource> inline) throws MailException; 
} 

那么速度实现

public class MailSenderVelocity implements MailSender { 
    private JavaMailSender sender; 
    private VelocityEngine engine; 

    @Override 
    public void send(final String[] to, final String from, 
     final String subject, final String template, 
     final Map<Object, Object> model, final boolean isHtml, 
     final Map<String, Resource> attachments, 
     final Map<String, Resource> inline) 
      throws com.engrid.mail.MailException { 
     try { 
      // prepare the message to send 
      MimeMessagePreparator preparator = new MimeMessagePreparator() { 
       @Override 
       public void prepare(MimeMessage mimeMessage) throws Exception { 
        // determine if the message needs to be multipart or not 
        boolean multipart = (attachments != null && !attachments.isEmpty()) || (inline != null && !inline.isEmpty()); 

        // create the message 
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, multipart); 

        // populate header fields 
        helper.setTo(to); 
        helper.setFrom(from); 
        helper.setSubject(subject); 

        // fetch template and merge model 
        String text = VelocityEngineUtils.mergeTemplateIntoString(engine, template, model); 
        helper.setText(text, isHtml); 

        // add inline attachments 
        if (inline != null) { 
         for (Entry<String, Resource> entry : inline.entrySet()) { 
          helper.addInline(entry.getKey(), entry.getValue()); 
         } 
        } 

        // add other attachments 
        if (attachments != null) { 
         for (Entry<String, Resource> entry : attachments.entrySet()) { 
          helper.addAttachment(entry.getKey(), entry.getValue()); 
         } 
        } 
       } 
      }; 

      // send the email 
      this.sender.send(preparator); 
     } catch(MailException e) { 
      // error preparing or sending the message 
      e.printStackTrace(); 
      throw new com.engrid.mail.MailException(e); 
     } 
    }  

    public void setSender(JavaMailSender sender) { 
     this.sender = sender; 
    } 

    public void setEngine(VelocityEngine engine) { 
     this.engine = engine; 
    } 
} 

作为一个优秀的程序员,我写测试用例不同的方案,以确保一切正常。我的一个案例是,当指定的附件,但文件本身不存在,特别是

@Test(expected=MailException.class) 
public void testSend_MissingAttachment() throws IOException, MailException { 
    // create new object 
    MailSenderVelocity testSender = new MailSenderVelocity(); 
    testSender.setEngine(engine); 
    testSender.setSender(sender); 

    // assign properties 
    String subject = "testSend_MissingAttachment"; 
    String template = "simple.vm"; 
    Map<Object, Object> model = new HashMap<Object, Object>(); 
    model.put("user", "User"); 
    boolean isHtml = true; 
    Map<String, Resource> attachments = new HashMap<String, Resource>(); 
    String file = "notext.txt"; 
    attachments.put(file, templateDirectory.createRelative(file)); 
    Map<String, Resource> inline = null; 

    // send a message -- will fail because it won't find the file to attach 
    testSender.send(this.to, this.from, subject, template, model, isHtml, attachments, inline); 
} 

现在,测试结果在预期的异常被抛出

org.springframework.mail.MailSendException: Failed messages: javax.mail.MessagingException: IOException while sending message; 
nested exception is: 
    java.io.FileNotFoundException: class path resource [com/company/mail/template/notext.txt] cannot be opened because it does not exist; message exception details (1) are: 
Failed message 1: 
javax.mail.MessagingException: IOException while sending message; 
    nested exception is: 
    java.io.FileNotFoundException: class path resource [com/company/mail/template/notext.txt] cannot be opened because it does not exist 
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:625) 
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:416) 
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340) 
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:355) 
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:344) 
    at com.company.mail.MailSenderVelocity.send(MailSenderVelocity.java:103) 
    at com.company.mail.MailSenderVelocity.send(MailSenderVelocity.java:53) 
    at com.company.mail.MailSenderVelocityTest.testSend_MissingAttachment(MailSenderVelocityTest.java:136) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37) 
    at java.lang.reflect.Method.invoke(Method.java:600) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:22) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) 
    at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:220) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) 
Caused by: java.io.FileNotFoundException: class path resource [com/company/mail/template/notext.txt] cannot be opened because it does not exist 
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:158) 
    at org.springframework.mail.javamail.MimeMessageHelper$1.getInputStream(MimeMessageHelper.java:1086) 
    at javax.activation.DataHandler.writeTo(DataHandler.java:302) 
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1350) 
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:845) 
    at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:361) 
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:85) 
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:881) 
    at javax.activation.DataHandler.writeTo(DataHandler.java:314) 
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1350) 
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1683) 
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:585) 
    ... 38 more 
2010-11-11 13:50:30,261 

然而,电子邮件仍从列出的发件人发送到列出的收件人。所有其他东西(主题,正文等)都是空白的。如何在构建电子邮件时生成异常时停止发送电子邮件。

回答

2

有趣。看起来Sun的内部JavaMail实现允许附件处理程序抛出异常,并且无论如何都在继续。

我能想到的最简单的解决方案是对附件资源进行一些预先验证,例如,

for (Entry<String, Resource> entry : inline.entrySet()) { 
    entry.getValue().getInputStream(); // validate the resource - fails if not existing 
    helper.addInline(entry.getKey(), entry.getValue()); 
} 

这将迫切检查Resource是否可用。如果您选择,您也可以使用Resource.exists()来处理这类事情。

+0

这很有道理。我改变了预处理器中的循环来获得一个条件 - if(!entry.getValue()。exists())抛出新的MailException(“attachment [”+ entry.getKey()+“]不存在”) ; - 在添加文件之前,它工作。感谢您的建议! – LostHisMind 2010-11-12 17:03:24

相关问题