Browse Source

JavaMailSenderImpl catches Exception instead of MessagingException and checks for reconnect in case of message batches

Issue: SPR-12298
pull/656/head
Juergen Hoeller 11 years ago
parent
commit
b7faef0103
  1. 77
      spring-context-support/src/main/java/org/springframework/mail/javamail/JavaMailSenderImpl.java
  2. 17
      spring-context-support/src/test/java/org/springframework/mail/javamail/JavaMailSenderTests.java

77
spring-context-support/src/main/java/org/springframework/mail/javamail/JavaMailSenderImpl.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -330,7 +330,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
try { try {
return new MimeMessage(getSession(), contentStream); return new MimeMessage(getSession(), contentStream);
} }
catch (MessagingException ex) { catch (Exception ex) {
throw new MailParseException("Could not parse raw MIME content", ex); throw new MailParseException("Could not parse raw MIME content", ex);
} }
} }
@ -385,35 +385,40 @@ public class JavaMailSenderImpl implements JavaMailSender {
* in case of failure when sending a message * in case of failure when sending a message
*/ */
protected void doSend(MimeMessage[] mimeMessages, Object[] originalMessages) throws MailException { protected void doSend(MimeMessage[] mimeMessages, Object[] originalMessages) throws MailException {
String username = getUsername(); Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();
String password = getPassword(); Transport transport = null;
if ("".equals(username)) { // probably from a placeholder
username = null; try {
if ("".equals(password)) { // in conjunction with "" username, this means no password to use for (int i = 0; i < mimeMessages.length; i++) {
password = null;
// Check transport connection first...
if (transport == null || !transport.isConnected()) {
if (transport != null) {
try {
transport.close();
} }
catch (Exception ex) {
// Ignore - we're reconnecting anyway
}
transport = null;
} }
Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();
Transport transport;
try { try {
transport = getTransport(getSession()); transport = connectTransport();
transport.connect(getHost(), getPort(), username, password);
} }
catch (AuthenticationFailedException ex) { catch (AuthenticationFailedException ex) {
throw new MailAuthenticationException(ex); throw new MailAuthenticationException(ex);
} }
catch (MessagingException ex) { catch (Exception ex) {
// Effectively, all messages failed... // Effectively, all remaining messages failed...
for (int i = 0; i < mimeMessages.length; i++) { for (int j = i; j < mimeMessages.length; j++) {
Object original = (originalMessages != null ? originalMessages[i] : mimeMessages[i]); Object original = (originalMessages != null ? originalMessages[j] : mimeMessages[j]);
failedMessages.put(original, ex); failedMessages.put(original, ex);
} }
throw new MailSendException("Mail server connection failed", ex, failedMessages); throw new MailSendException("Mail server connection failed", ex, failedMessages);
} }
}
try { // Send message via current transport...
for (int i = 0; i < mimeMessages.length; i++) {
MimeMessage mimeMessage = mimeMessages[i]; MimeMessage mimeMessage = mimeMessages[i];
try { try {
if (mimeMessage.getSentDate() == null) { if (mimeMessage.getSentDate() == null) {
@ -427,7 +432,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
} }
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
} }
catch (MessagingException ex) { catch (Exception ex) {
Object original = (originalMessages != null ? originalMessages[i] : mimeMessage); Object original = (originalMessages != null ? originalMessages[i] : mimeMessage);
failedMessages.put(original, ex); failedMessages.put(original, ex);
} }
@ -435,9 +440,11 @@ public class JavaMailSenderImpl implements JavaMailSender {
} }
finally { finally {
try { try {
if (transport != null) {
transport.close(); transport.close();
} }
catch (MessagingException ex) { }
catch (Exception ex) {
if (!failedMessages.isEmpty()) { if (!failedMessages.isEmpty()) {
throw new MailSendException("Failed to close server connection after message failures", ex, throw new MailSendException("Failed to close server connection after message failures", ex,
failedMessages); failedMessages);
@ -453,11 +460,39 @@ public class JavaMailSenderImpl implements JavaMailSender {
} }
} }
/**
* Obtain and connect a Transport from the underlying JavaMail Session,
* passing in the specified host, port, username, and password.
* @return the connected Transport object
* @throws MessagingException if the connect attempt failed
* @since 4.1.2
* @see #getTransport
* @see #getHost()
* @see #getPort()
* @see #getUsername()
* @see #getPassword()
*/
protected Transport connectTransport() throws MessagingException {
String username = getUsername();
String password = getPassword();
if ("".equals(username)) { // probably from a placeholder
username = null;
if ("".equals(password)) { // in conjunction with "" username, this means no password to use
password = null;
}
}
Transport transport = getTransport(getSession());
transport.connect(getHost(), getPort(), username, password);
return transport;
}
/** /**
* Obtain a Transport object from the given JavaMail Session, * Obtain a Transport object from the given JavaMail Session,
* using the configured protocol. * using the configured protocol.
* <p>Can be overridden in subclasses, e.g. to return a mock Transport object. * <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
* @see javax.mail.Session#getTransport(String) * @see javax.mail.Session#getTransport(String)
* @see #getSession()
* @see #getProtocol() * @see #getProtocol()
*/ */
protected Transport getTransport(Session session) throws NoSuchProviderException { protected Transport getTransport(Session session) throws NoSuchProviderException {

17
spring-context-support/src/test/java/org/springframework/mail/javamail/JavaMailSenderTests.java

@ -23,7 +23,6 @@ import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import javax.activation.FileTypeMap; import javax.activation.FileTypeMap;
import javax.mail.Address; import javax.mail.Address;
import javax.mail.Message; import javax.mail.Message;
@ -41,6 +40,7 @@ import junit.framework.TestCase;
import org.springframework.mail.MailParseException; import org.springframework.mail.MailParseException;
import org.springframework.mail.MailSendException; import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.SimpleMailMessage;
import org.springframework.util.ObjectUtils;
/** /**
* @author Juergen Hoeller * @author Juergen Hoeller
@ -106,7 +106,7 @@ public class JavaMailSenderTests extends TestCase {
simpleMessage1.setTo("he@mail.org"); simpleMessage1.setTo("he@mail.org");
SimpleMailMessage simpleMessage2 = new SimpleMailMessage(); SimpleMailMessage simpleMessage2 = new SimpleMailMessage();
simpleMessage2.setTo("she@mail.org"); simpleMessage2.setTo("she@mail.org");
sender.send(new SimpleMailMessage[] {simpleMessage1, simpleMessage2}); sender.send(simpleMessage1, simpleMessage2);
assertEquals("host", sender.transport.getConnectedHost()); assertEquals("host", sender.transport.getConnectedHost());
assertEquals("username", sender.transport.getConnectedUsername()); assertEquals("username", sender.transport.getConnectedUsername());
@ -152,7 +152,7 @@ public class JavaMailSenderTests extends TestCase {
mimeMessage1.setRecipient(Message.RecipientType.TO, new InternetAddress("he@mail.org")); mimeMessage1.setRecipient(Message.RecipientType.TO, new InternetAddress("he@mail.org"));
MimeMessage mimeMessage2 = sender.createMimeMessage(); MimeMessage mimeMessage2 = sender.createMimeMessage();
mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org")); mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org"));
sender.send(new MimeMessage[] {mimeMessage1, mimeMessage2}); sender.send(mimeMessage1, mimeMessage2);
assertEquals("host", sender.transport.getConnectedHost()); assertEquals("host", sender.transport.getConnectedHost());
assertEquals("username", sender.transport.getConnectedUsername()); assertEquals("username", sender.transport.getConnectedUsername());
@ -210,7 +210,7 @@ public class JavaMailSenderTests extends TestCase {
messages.add(mimeMessage); messages.add(mimeMessage);
} }
}; };
sender.send(new MimeMessagePreparator[] {preparator1, preparator2}); sender.send(preparator1, preparator2);
assertEquals("host", sender.transport.getConnectedHost()); assertEquals("host", sender.transport.getConnectedHost());
assertEquals("username", sender.transport.getConnectedUsername()); assertEquals("username", sender.transport.getConnectedUsername());
@ -425,7 +425,7 @@ public class JavaMailSenderTests extends TestCase {
simpleMessage2.setTo("she@mail.org"); simpleMessage2.setTo("she@mail.org");
try { try {
sender.send(new SimpleMailMessage[] {simpleMessage1, simpleMessage2}); sender.send(simpleMessage1, simpleMessage2);
} }
catch (MailSendException ex) { catch (MailSendException ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -456,7 +456,7 @@ public class JavaMailSenderTests extends TestCase {
mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org")); mimeMessage2.setRecipient(Message.RecipientType.TO, new InternetAddress("she@mail.org"));
try { try {
sender.send(new MimeMessage[] {mimeMessage1, mimeMessage2}); sender.send(mimeMessage1, mimeMessage2);
} }
catch (MailSendException ex) { catch (MailSendException ex) {
ex.printStackTrace(); ex.printStackTrace();
@ -537,6 +537,7 @@ public class JavaMailSenderTests extends TestCase {
this.connectedPort = port; this.connectedPort = port;
this.connectedUsername = username; this.connectedUsername = username;
this.connectedPassword = password; this.connectedPassword = password;
setConnected(true);
} }
@Override @Override
@ -552,9 +553,7 @@ public class JavaMailSenderTests extends TestCase {
if ("fail".equals(message.getSubject())) { if ("fail".equals(message.getSubject())) {
throw new MessagingException("failed"); throw new MessagingException("failed");
} }
List<Address> addr1 = Arrays.asList(message.getAllRecipients()); if (!ObjectUtils.nullSafeEquals(addresses, message.getAllRecipients())) {
List<Address> addr2 = Arrays.asList(addresses);
if (!addr1.equals(addr2)) {
throw new MessagingException("addresses not correct"); throw new MessagingException("addresses not correct");
} }
if (message.getSentDate() == null) { if (message.getSentDate() == null) {

Loading…
Cancel
Save