JavaMailSenderImpl на Spring хвърля изключение, но все още изпраща имейла

Използвайки Spring 3.0, написах интерфейс, за да скрия от приложението коя машина за шаблони използвах за изпращане на поща. Интерфейсът е

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

Въпреки това, имейл съобщение все още се изпраща до посочения получател от посочения подател. Всички други неща (тема, тяло и т.н.) са празни. Как да спра изпращането на имейла, когато се генерира изключение по време на изграждането на имейла.


person LostHisMind    schedule 11.11.2010    source източник


Отговори (1)


интересно Изглежда, че вътрешната реализация на JavaMail на Sun толерира изключения, хвърляни от манипулаторите на прикачени файлове, и продължава независимо от това.

Най-лесното решение, за което се сещам, е да направите малко предварителна проверка на вашите ресурси за прикачен файл, напр.

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() за този вид неща, ако решите.

person skaffman    schedule 12.11.2010
comment
Това има смисъл. Промених циклите в подготвителя, за да има условен -- if (!entry.getValue().exists()) throw new MailException(attachment[ + entry.getKey() + ] не съществува); -- преди да добавите файла и той работи. Благодаря за предложението! - person LostHisMind; 12.11.2010