Author: jaz
Date: Thu May 7 21:29:06 2009 New Revision: 772780 URL: http://svn.apache.org/viewvc?rev=772780&view=rev Log: implemented service to process bounced emails and update the communication event status Added: ofbiz/trunk/applications/party/servicedef/mcas.xml Modified: ofbiz/trunk/applications/party/ofbiz-component.xml ofbiz/trunk/applications/party/servicedef/services.xml ofbiz/trunk/applications/party/src/org/ofbiz/party/communication/CommunicationEventServices.java Modified: ofbiz/trunk/applications/party/ofbiz-component.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/ofbiz-component.xml?rev=772780&r1=772779&r2=772780&view=diff ============================================================================== --- ofbiz/trunk/applications/party/ofbiz-component.xml (original) +++ ofbiz/trunk/applications/party/ofbiz-component.xml Thu May 7 21:29:06 2009 @@ -34,7 +34,8 @@ <service-resource type="model" loader="main" location="servicedef/services.xml"/> <service-resource type="model" loader="main" location="servicedef/services_view.xml"/> <service-resource type="eca" loader="main" location="servicedef/secas.xml"/> - + <service-resource type="mca" loader="main" location="servicedef/mcas.xml"/> + <test-suite loader="main" location="testdef/PartyTests.xml"/> <webapp name="party" Added: ofbiz/trunk/applications/party/servicedef/mcas.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/servicedef/mcas.xml?rev=772780&view=auto ============================================================================== --- ofbiz/trunk/applications/party/servicedef/mcas.xml (added) +++ ofbiz/trunk/applications/party/servicedef/mcas.xml Thu May 7 21:29:06 2009 @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> + +<service-mca xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/service-mca.xsd"> + + <mca mail-rule-name="processBouncedMessage"> + <action service="processBouncedMessage" mode="sync"/> + </mca> + +</service-mca> Modified: ofbiz/trunk/applications/party/servicedef/services.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/servicedef/services.xml?rev=772780&r1=772779&r2=772780&view=diff ============================================================================== --- ofbiz/trunk/applications/party/servicedef/services.xml (original) +++ ofbiz/trunk/applications/party/servicedef/services.xml Thu May 7 21:29:06 2009 @@ -93,7 +93,10 @@ <service name="updatePerson" engine="java" default-entity-name="Person" location="org.ofbiz.party.party.PartyServices" invoke="updatePerson" auth="true"> <description>Update a Person</description> - <permission-service service-name="partyGroupPermissionCheck" main-action="UPDATE"/> + <required-permissions join-type="AND"> + <check-permission permission="update:party:${partyId}"/> + </required-permissions> + <!-- <permission-service service-name="partyGroupPermissionCheck" main-action="UPDATE"/> --> <auto-attributes mode="IN" include="pk" optional="true"><!-- if no partyId specified will use userLogin.partyId --></auto-attributes> <auto-attributes mode="IN" include="nonpk" optional="true"/> <attribute name="preferredCurrencyUomId" type="String" mode="IN" optional="true"/> @@ -1167,4 +1170,10 @@ <attribute name="contactMechId" type="String" mode="IN" optional="true"/> <attribute name="contactMechId" type="String" mode="OUT" optional="false"/> </service> + + <!-- bounced message processing --> + <service name="processBouncedMessage" engine="java" + location="org.ofbiz.party.communication.CommunicationEventServices" invoke="processBouncedMessage"> + <implements service="mailProcessInterface"/> + </service> </services> Modified: ofbiz/trunk/applications/party/src/org/ofbiz/party/communication/CommunicationEventServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/src/org/ofbiz/party/communication/CommunicationEventServices.java?rev=772780&r1=772779&r2=772780&view=diff ============================================================================== --- ofbiz/trunk/applications/party/src/org/ofbiz/party/communication/CommunicationEventServices.java (original) +++ ofbiz/trunk/applications/party/src/org/ofbiz/party/communication/CommunicationEventServices.java Thu May 7 21:29:06 2009 @@ -31,8 +31,12 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.mail.Address; +import javax.mail.BodyPart; +import javax.mail.Header; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Part; @@ -946,4 +950,115 @@ } return attachmentCount; } + + /* + * Service to process incoming email and look for a bounce message. If the email is indeed a bounce message + * the CommunicationEvent will be updated with the proper COM_BOUNCED status. + */ + public static Map<String,Object> processBouncedMessage(DispatchContext dctx, Map<String, ? extends Object> context) { + Debug.logInfo("Running process bounced message check...", module); + MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper"); + MimeMessage message = wrapper.getMessage(); + + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericDelegator delegator = dctx.getDelegator(); + + try { + Object content = message.getContent(); + if (content instanceof Multipart) { + Multipart mp = (Multipart) content; + int parts = mp.getCount(); + + if (parts >= 3) { // it must have all three parts in order to process correctly + + // get the second part (delivery report) + BodyPart part2 = mp.getBodyPart(1); // index 1 should be the second part + String contentType = part2.getContentType(); + if (contentType != null && "message/delivery-status".equalsIgnoreCase(contentType)) { + Debug.logInfo("Delivery status report part found; processing...", module); + + // message is only available as an input stream; read the stream + InputStream insPart2 = (InputStream) part2.getInputStream(); + int part2Size = part2.getSize(); + byte[] part2Bytes = new byte[part2Size]; + insPart2.read(part2Bytes, 0, part2Size); + String part2Text = new String(part2Bytes); + + // find the "Action" element and obtain its value (looking for "failed") + Pattern p2 = Pattern.compile("^Action: (.*)$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); + Matcher m2 = p2.matcher(part2Text); + String action = null; + if (m2.find()) { + action = m2.group(1); + } + + if (action != null && "failed".equalsIgnoreCase(action)) { + // message bounced -- get the original message + BodyPart part3 = mp.getBodyPart(2); // index 2 should be the third part + + // read part 3 message + InputStream insPart3 = (InputStream) part3.getInputStream(); + int part3Size = part3.getSize(); + byte[] part3Bytes = new byte[part3Size]; + insPart3.read(part3Bytes, 0, part3Size); + String part3Text = new String(part3Bytes); + + // find the "Message-Id" element and obtain its value (looking for "failed") + Pattern p3 = Pattern.compile("^Message-Id: (.*)$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); + Matcher m3 = p3.matcher(part3Text); + String messageId = null; + if (m3.find()) { + messageId = m3.group(1); + } + + // find the matching communication event + if (messageId != null) { + List<GenericValue> values; + try { + values = delegator.findByAnd("CommunicationEvent", UtilMisc.toMap("messageId", messageId)); + } catch (GenericEntityException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } + if (values != null && values.size() > 0) { + // there should be only one; unique key + GenericValue value = values.get(0); + + // update the communication event status + Map<String,Object> updateCtx = FastMap.newInstance(); + updateCtx.put("communicationEventId", value.getString("communicationEventId")); + updateCtx.put("statusId", "COM_BOUNCED"); + updateCtx.put("userLogin", context.get("userLogin")); + Map<String,Object> result; + try { + result = dispatcher.runSync("updateCommunicationEvent", updateCtx); + } catch (GenericServiceException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } + if (ServiceUtil.isError(result)) { + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } else { + if (Debug.infoOn()) { + Debug.logInfo("Unable to find communication event with the matching messageId : " + messageId, module); + } + } + } else { + Debug.logWarning("No message ID attached to part", module); + } + } + } + } + } + } catch (MessagingException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } catch (IOException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } + + return ServiceUtil.returnSuccess(); + } } |
Free forum by Nabble | Edit this page |