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

Issue: SPR-12298
This commit is contained in:
Juergen Hoeller 2014-10-06 15:37:08 +02:00
parent 12a2813e2a
commit b7faef0103
2 changed files with 73 additions and 39 deletions

View File

@ -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");
* you may not use this file except in compliance with the License.
@ -330,7 +330,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
try {
return new MimeMessage(getSession(), contentStream);
}
catch (MessagingException ex) {
catch (Exception 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
*/
protected void doSend(MimeMessage[] mimeMessages, Object[] originalMessages) throws MailException {
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;
}
}
Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();
Transport transport;
try {
transport = getTransport(getSession());
transport.connect(getHost(), getPort(), username, password);
}
catch (AuthenticationFailedException ex) {
throw new MailAuthenticationException(ex);
}
catch (MessagingException ex) {
// Effectively, all messages failed...
for (int i = 0; i < mimeMessages.length; i++) {
Object original = (originalMessages != null ? originalMessages[i] : mimeMessages[i]);
failedMessages.put(original, ex);
}
throw new MailSendException("Mail server connection failed", ex, failedMessages);
}
Transport transport = null;
try {
for (int i = 0; i < mimeMessages.length; i++) {
// 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;
}
try {
transport = connectTransport();
}
catch (AuthenticationFailedException ex) {
throw new MailAuthenticationException(ex);
}
catch (Exception ex) {
// Effectively, all remaining messages failed...
for (int j = i; j < mimeMessages.length; j++) {
Object original = (originalMessages != null ? originalMessages[j] : mimeMessages[j]);
failedMessages.put(original, ex);
}
throw new MailSendException("Mail server connection failed", ex, failedMessages);
}
}
// Send message via current transport...
MimeMessage mimeMessage = mimeMessages[i];
try {
if (mimeMessage.getSentDate() == null) {
@ -427,7 +432,7 @@ public class JavaMailSenderImpl implements JavaMailSender {
}
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}
catch (MessagingException ex) {
catch (Exception ex) {
Object original = (originalMessages != null ? originalMessages[i] : mimeMessage);
failedMessages.put(original, ex);
}
@ -435,9 +440,11 @@ public class JavaMailSenderImpl implements JavaMailSender {
}
finally {
try {
transport.close();
if (transport != null) {
transport.close();
}
}
catch (MessagingException ex) {
catch (Exception ex) {
if (!failedMessages.isEmpty()) {
throw new MailSendException("Failed to close server connection after message failures", ex,
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,
* using the configured protocol.
* <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
* @see javax.mail.Session#getTransport(String)
* @see #getSession()
* @see #getProtocol()
*/
protected Transport getTransport(Session session) throws NoSuchProviderException {

View File

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