|
Author: lektran
Date: Tue Jan 5 20:48:15 2010 New Revision: 896213 URL: http://svn.apache.org/viewvc?rev=896213&view=rev Log: Emails will now be sent to any valid recipients even if the SMTP server rejected any invalid ones. This can be turned off if desired in general.properties and also on a per service call basis. A failure notification will be sent to the email's "from" address, listing the failed recipients and the reason for each failure. The notification can be turned off by setting the sendFailureNotification parameter to false in the s These changes fix a problem where emails are not sent to valid recipients and users receive no feedback when emails fail to be sent, generally because of the smtp server rejecting one or more recipients. OFBIZ-3379, thanks to Pranay Pandey for the report and testing, also thanks to Tim Ruppert and Ruth Hoffman for their input into the issue. Modified: ofbiz/trunk/framework/common/servicedef/services_email.xml ofbiz/trunk/framework/common/src/org/ofbiz/common/email/EmailServices.java Modified: ofbiz/trunk/framework/common/servicedef/services_email.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/servicedef/services_email.xml?rev=896213&r1=896212&r2=896213&view=diff ============================================================================== --- ofbiz/trunk/framework/common/servicedef/services_email.xml (original) +++ ofbiz/trunk/framework/common/servicedef/services_email.xml Tue Jan 5 20:48:15 2010 @@ -35,6 +35,8 @@ <attribute name="authPass" type="String" mode="IN" optional="true"/> <attribute name="sendVia" type="String" mode="IN" optional="true"/> <attribute name="sendType" type="String" mode="IN" optional="true"/> + <attribute name="sendFailureNotification" mode="IN" type="Boolean" optional="true"/> + <attribute name="sendPartial" mode="IN" type="Boolean" optional="true"/> <attribute name="subject" type="String" mode="INOUT" optional="true" allow-html="safe"/> <attribute name="contentType" type="String" mode="INOUT" optional="true"/> <attribute name="partyId" type="String" mode="INOUT" optional="true"/> Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/email/EmailServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/email/EmailServices.java?rev=896213&r1=896212&r2=896213&view=diff ============================================================================== --- ofbiz/trunk/framework/common/src/org/ofbiz/common/email/EmailServices.java (original) +++ ofbiz/trunk/framework/common/src/org/ofbiz/common/email/EmailServices.java Tue Jan 5 20:48:15 2010 @@ -39,10 +39,10 @@ import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.Message; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.MessagingException; import javax.mail.SendFailedException; +import javax.mail.Session; +import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; @@ -51,6 +51,8 @@ import javax.xml.transform.stream.StreamSource; import javolution.util.FastList; +import javolution.util.FastMap; + import org.apache.fop.apps.FOPException; import org.apache.fop.apps.Fop; import org.apache.fop.apps.MimeConstants; @@ -76,6 +78,8 @@ import org.ofbiz.widget.screen.ScreenRenderer; import org.xml.sax.SAXException; +import com.sun.mail.smtp.SMTPAddressFailedException; + /** * Email Services */ @@ -143,6 +147,7 @@ String authPass = (String) context.get("authPass"); String messageId = (String) context.get("messageId"); String contentType = (String) context.get("contentType"); + Boolean sendPartial = (Boolean) context.get("sendPartial"); boolean useSmtpAuth = false; @@ -173,6 +178,9 @@ if (UtilValidate.isEmpty(socketFactoryFallback)) { socketFactoryFallback = UtilProperties.getPropertyValue("general.properties", "mail.smtp.socketFactory.fallback", "false"); } + if (sendPartial == null) { + sendPartial = UtilProperties.propertyValueEqualsIgnoreCase("general.properties", "mail.smtp.sendpartial", "true") ? true : false; + } } else if (sendVia == null) { return ServiceUtil.returnError("Parameter sendVia is required when sendType is not mail.smtp.host"); } @@ -207,8 +215,9 @@ if (useSmtpAuth) { props.put("mail.smtp.auth", "true"); } - boolean sendPartial = UtilProperties.propertyValueEqualsIgnoreCase("general.properties", "mail.smtp.sendpartial", "true"); - props.put("mail.smtp.sendpartial", sendPartial ? "true" : "false"); + if (sendPartial != null) { + props.put("mail.smtp.sendpartial", sendPartial ? "true" : "false"); + } session = Session.getInstance(props); boolean debug = UtilProperties.propertyValueEqualsIgnoreCase("general.properties", "mail.debug.on", "Y"); @@ -248,6 +257,8 @@ ByteArrayDataSource bads = new ByteArrayDataSource((byte[]) bodyPartContent, (String) bodyPart.get("type")); Debug.logInfo("part of type: " + bodyPart.get("type") + " and size: " + ((byte[]) bodyPartContent).length , module); mbp.setDataHandler(new DataHandler(bads)); + } else if (bodyPartContent instanceof DataHandler) { + mbp.setDataHandler((DataHandler) bodyPartContent); } else { mbp.setDataHandler(new DataHandler(bodyPartContent, (String) bodyPart.get("type"))); } @@ -291,8 +302,9 @@ return results; } + Transport trans = null; try { - Transport trans = session.getTransport("smtp"); + trans = session.getTransport("smtp"); if (!useSmtpAuth) { trans.connect(); } else { @@ -306,8 +318,28 @@ // message code prefix may be used by calling services to determine the cause of the failure String errMsg = "[ADDRERR] Address error when sending message to [" + sendTo + "] from [" + sendFrom + "] cc [" + sendCc + "] bcc [" + sendBcc + "] subject [" + subject + "]"; Debug.logError(e, errMsg, module); - Debug.logError("Email message that could not be sent to [" + sendTo + "] had context: " + context, module); - return ServiceUtil.returnError(errMsg); + List<SMTPAddressFailedException> failedAddresses = FastList.newInstance(); + Exception nestedException = null; + while ((nestedException = e.getNextException()) != null && nestedException instanceof MessagingException) { + if (nestedException instanceof SMTPAddressFailedException) { + SMTPAddressFailedException safe = (SMTPAddressFailedException) nestedException; + Debug.logError("Failed to send message to [" + safe.getAddress() + "], return code [" + safe.getReturnCode() + "], return message [" + safe.getMessage() + "]", errMsg); + failedAddresses.add(safe); + } + } + Boolean sendFailureNotification = (Boolean) context.get("sendFailureNotification"); + if (sendFailureNotification == null || sendFailureNotification) { + sendFailureNotification(ctx, context, mail, failedAddresses); + results.put("messageWrapper", new MimeMessageWrapper(session, mail)); + try { + results.put("messageId", mail.getMessageID()); + trans.close(); + } catch (MessagingException e1) { + Debug.logError(e1, module); + } + } else { + return ServiceUtil.returnError(errMsg); + } } catch (MessagingException e) { // message code prefix may be used by calling services to determine the cause of the failure String errMsg = "[CON] Connection error when sending message to [" + sendTo + "] from [" + sendFrom + "] cc [" + sendCc + "] bcc [" + sendBcc + "] subject [" + subject + "]"; @@ -551,6 +583,39 @@ return result; } + public static void sendFailureNotification(DispatchContext dctx, Map<String, ? extends Object> context, MimeMessage message, List<SMTPAddressFailedException> failures) { + Map<String, Object> newContext = FastMap.newInstance(); + newContext.put("userLogin", context.get("userLogin")); + newContext.put("sendFailureNotification", false); + newContext.put("sendFrom", context.get("sendFrom")); + newContext.put("sendTo", context.get("sendFrom")); + newContext.put("subject", "Undelivered Mail Returned to Sender"); + StringBuilder sb = new StringBuilder(); + sb.append("Delivery to the following recipient(s) failed:\n\n"); + for (SMTPAddressFailedException failure : failures) { + sb.append(failure.getAddress()); + sb.append(": "); + sb.append(failure.getMessage()); + sb.append("/n/n"); + } + sb.append("----- Original message -----/n/n"); + List<Map<String, Object>> bodyParts = FastList.newInstance(); + bodyParts.add(UtilMisc.<String, Object>toMap("content", sb.toString(), "type", "text/plain")); + Map<String, Object> bodyPart = FastMap.newInstance(); + bodyPart.put("content", sb.toString()); + bodyPart.put("type", "text/plain"); + try { + bodyParts.add(UtilMisc.<String, Object>toMap("content", message.getDataHandler())); + } catch (MessagingException e) { + Debug.logError(e, module); + } + try { + dctx.getDispatcher().runSync("sendMailMultiPart", newContext); + } catch (GenericServiceException e) { + Debug.logError(e, module); + } + } + /** class to create a file in memory required for sending as an attachment */ public static class StringDataSource implements DataSource { private String contentType; |
| Free forum by Nabble | Edit this page |
