/* * Copyright 2002-2007 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.mail; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import org.springframework.util.ObjectUtils; /** * Exception thrown when a mail sending error is encountered. * Can register failed messages with their exceptions. * * @author Dmitriy Kopylenko * @author Juergen Hoeller */ public class MailSendException extends MailException { private transient Map failedMessages; private Exception[] messageExceptions; /** * Constructor for MailSendException. * @param msg the detail message */ public MailSendException(String msg) { super(msg); } /** * Constructor for MailSendException. * @param msg the detail message * @param cause the root cause from the mail API in use */ public MailSendException(String msg, Throwable cause) { super(msg, cause); } /** * Constructor for registration of failed messages, with the * messages that failed as keys, and the thrown exceptions as values. * <p>The messages should be the same that were originally passed * to the invoked send method. * @param failedMessages Map of failed messages as keys and thrown * exceptions as values */ public MailSendException(Map failedMessages) { super(null); this.failedMessages = new LinkedHashMap(failedMessages); this.messageExceptions = (Exception[]) failedMessages.values().toArray(new Exception[failedMessages.size()]); } /** * Return a Map with the failed messages as keys, and the thrown exceptions * as values. * <p>Note that a general mail server connection failure will not result * in failed messages being returned here: A message will only be * contained here if actually sending it was attempted but failed. * <p>The messages will be the same that were originally passed to the * invoked send method, that is, SimpleMailMessages in case of using * the generic MailSender interface. * <p>In case of sending MimeMessage instances via JavaMailSender, * the messages will be of type MimeMessage. * <p><b>NOTE:</b> This Map will not be available after serialization. * Use {@link #getMessageExceptions()} in such a scenario, which will * be available after serialization as well. * @return the Map of failed messages as keys and thrown exceptions as * values, or an empty Map if no failed messages * @see SimpleMailMessage * @see javax.mail.internet.MimeMessage */ public final Map getFailedMessages() { return (this.failedMessages != null ? this.failedMessages : Collections.EMPTY_MAP); } /** * Return an array with thrown message exceptions. * <p>Note that a general mail server connection failure will not result * in failed messages being returned here: A message will only be * contained here if actually sending it was attempted but failed. * @return the array of thrown message exceptions, * or an empty array if no failed messages */ public final Exception[] getMessageExceptions() { return (this.messageExceptions != null ? this.messageExceptions : new Exception[0]); } public String getMessage() { if (ObjectUtils.isEmpty(this.messageExceptions)) { return super.getMessage(); } else { StringBuffer sb = new StringBuffer("Failed messages: "); for (int i = 0; i < this.messageExceptions.length; i++) { Exception subEx = this.messageExceptions[i]; sb.append(subEx.toString()); if (i < this.messageExceptions.length - 1) { sb.append("; "); } } return sb.toString(); } } public String toString() { if (ObjectUtils.isEmpty(this.messageExceptions)) { return super.toString(); } else { StringBuffer sb = new StringBuffer(getClass().getName()); sb.append("; nested exceptions (").append(this.messageExceptions.length).append(") are:"); for (int i = 0; i < this.messageExceptions.length; i++) { Exception subEx = this.messageExceptions[i]; sb.append('\n').append("Failed message ").append(i + 1).append(": "); sb.append(subEx); } return sb.toString(); } } public void printStackTrace(PrintStream ps) { if (ObjectUtils.isEmpty(this.messageExceptions)) { super.printStackTrace(ps); } else { ps.println(getClass().getName() + "; nested exception details (" + this.messageExceptions.length + ") are:"); for (int i = 0; i < this.messageExceptions.length; i++) { Exception subEx = this.messageExceptions[i]; ps.println("Failed message " + (i + 1) + ":"); subEx.printStackTrace(ps); } } } public void printStackTrace(PrintWriter pw) { if (ObjectUtils.isEmpty(this.messageExceptions)) { super.printStackTrace(pw); } else { pw.println(getClass().getName() + "; nested exception details (" + this.messageExceptions.length + ") are:"); for (int i = 0; i < this.messageExceptions.length; i++) { Exception subEx = this.messageExceptions[i]; pw.println("Failed message " + (i + 1) + ":"); subEx.printStackTrace(pw); } } } }