2010-11-11 5 views
4

En utilisant Spring 3.0, j'ai écrit une interface pour cacher à l'application quel moteur de template j'utilisais pour envoyer du courrier. L'interface estJavaMailSenderImpl de Spring lève une exception mais envoie toujours l'email

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; 
} 

Ensuite, la mise en œuvre de vitesse est

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; 
    } 
} 

Être un bon programmeur, je l'ai écrit des scénarios de test pour différents scénarios pour assurer que tout fonctionne correctement. Un de mes affaires est lorsqu'une pièce jointe est spécifiée mais le fichier lui-même n'existe pas, en particulier

@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); 
} 

maintenant, les résultats des tests à l'exception attendue jetés

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 

Cependant, un message électronique encore est envoyé au destinataire répertorié à partir de l'expéditeur répertorié. Toutes les autres choses (sujet, corps, etc.) sont vides. Comment arrêter l'envoi de l'e-mail lorsqu'une exception est générée lors de la création de l'e-mail?

Répondre

2

Intéressant. Il semble que l'implémentation JavaMail interne de Sun tolère les exceptions levées par les gestionnaires de pièces jointes, et se poursuit malgré tout.

La solution la plus simple à laquelle je puisse penser est de faire un peu de validation initiale de vos ressources de pièces jointes, par ex.

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

Cela avec impatience vérifier que le Resource est disponible. Vous pouvez également utiliser Resource.exists() pour ce genre de chose si vous choisissez.

+0

Cela a du sens. J'ai changé les boucles dans le préparateur pour avoir une conditionnelle - if (! Entry.getValue(). Exists()) throw new MailException ("pièce jointe [" + entrée.getKey() + "] n'existe pas") ; - avant d'ajouter le fichier et cela fonctionne. Merci pour la suggestion! – LostHisMind

Questions connexes