Spring JavaMailSenderImpl throws an exception but sends an email anyway

Using Spring 3.0, I wrote an interface to hide the template engine that I used to send mail from the application. Interface

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

Then the Velocity implementation

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

As a good programmer, I wrote test cases for different scenarios so that everything would work correctly. One of my cases is when the attachment is specified, but the file itself does not exist, in particular

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

Now the test result throws the expected exception

 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 

However, the e-mail message is still sent to the specified recipient from the specified sender. All other things (theme, body, etc.) are empty. How to stop sending email when an exception is thrown while creating an email.

+4
source share
1 answer

Interesting. Sun's JavaMail embedded implementation seems to allow exceptions thrown by the binding handlers, and is executed independently.

The easiest solution I can think of is to check a bit on the correctness of your investment resources, for example

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

This will confidently check for a Resource . You can also use Resource.exists() for this kind of thing, if you choose.

+2
source

All Articles