use of org.apache.ofbiz.service.mail.MimeMessageWrapper in project ofbiz-framework by apache.
the class CommonServices method mcaTest.
public static Map<String, Object> mcaTest(DispatchContext dctx, Map<String, ?> context) {
MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper");
MimeMessage message = wrapper.getMessage();
try {
if (message.getAllRecipients() != null) {
Debug.logInfo("To: " + UtilMisc.toListArray(message.getAllRecipients()), module);
}
if (message.getFrom() != null) {
Debug.logInfo("From: " + UtilMisc.toListArray(message.getFrom()), module);
}
Debug.logInfo("Subject: " + message.getSubject(), module);
if (message.getSentDate() != null) {
Debug.logInfo("Sent: " + message.getSentDate().toString(), module);
}
if (message.getReceivedDate() != null) {
Debug.logInfo("Received: " + message.getReceivedDate().toString(), module);
}
} catch (Exception e) {
Debug.logError(e, module);
}
return ServiceUtil.returnSuccess();
}
use of org.apache.ofbiz.service.mail.MimeMessageWrapper in project ofbiz-framework by apache.
the class CommunicationEventServices method storeIncomingEmail.
/**
* This service is the main one for processing incoming emails.
*
* Its only argument is a wrapper for the JavaMail MimeMessage object.
* From this object, all the fields, headers and content of the message can be accessed.
*
* The first thing this service does is try to discover the partyId of the message sender
* by doing a reverse find on the email address. It uses the findPartyFromEmailAddress service to do this.
*
* It then creates a CommunicationEvent entity by calling the createCommunicationEvent service using the appropriate fields from the email and the
* discovered partyId, if it exists, as the partyIdFrom. Note that it sets the communicationEventTypeId
* field to AUTO_EMAIL_COMM. This is useful for tracking email generated communications.
*
* The service tries to find appropriate content for inclusion in the CommunicationEvent.content field.
* If the contentType of the content starts with "text", the getContent() call returns a string and it is used.
* If the contentType starts with "multipart", then the "parts" of the content are iterated thru and the first
* one of mime type, "text/..." is used.
*
* If the contentType has a value of "multipart" then the parts of the content (except the one used in the main
* CommunicationEvent.content field) are cycled thru and attached to the CommunicationEvent entity using the
* createCommContentDataResource service. This happens in the EmailWorker.addAttachmentsToCommEvent method.
*
* However multiparts can contain multiparts. A recursive function has been added.
*
* -Al Byers - Hans Bakker
* @param dctx the dispatch context
* @param context the context
* @return returns the result of the service execution
*/
public static Map<String, Object> storeIncomingEmail(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper");
Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
String partyIdTo = null;
String partyIdFrom = null;
String communicationEventId = null;
String contactMechIdFrom = null;
String contactMechIdTo = null;
Map<String, Object> result = null;
try {
Address[] addressesFrom = wrapper.getFrom();
Address[] addressesTo = wrapper.getTo();
Address[] addressesCC = wrapper.getCc();
Address[] addressesBCC = wrapper.getBcc();
String messageId = wrapper.getMessageId().replaceAll("[<>]", "");
String aboutThisEmail = "message [" + messageId + "] from [" + ((addressesFrom == null || addressesFrom[0] == null) ? "not found" : addressesFrom[0].toString()) + "] to [" + ((addressesTo == null || addressesTo[0] == null) ? "not found" : addressesTo[0].toString()) + "]";
if (Debug.verboseOn()) {
Debug.logVerbose("Processing Incoming Email " + aboutThisEmail, module);
}
// ignore the message when the spam status = yes
String spamHeaderName = EntityUtilProperties.getPropertyValue("general", "mail.spam.name", "N", delegator);
String configHeaderValue = EntityUtilProperties.getPropertyValue("general", "mail.spam.value", delegator);
// only execute when config file has been set && header variable found
if (!"N".equals(spamHeaderName) && wrapper.getHeader(spamHeaderName) != null && wrapper.getHeader(spamHeaderName).length > 0) {
String msgHeaderValue = wrapper.getHeader(spamHeaderName)[0];
if (msgHeaderValue != null && msgHeaderValue.startsWith(configHeaderValue)) {
Debug.logInfo("Incoming Email message ignored, was detected by external spam checker", module);
return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "PartyCommEventMessageIgnoredDetectedByExternalSpamChecker", locale));
}
}
// if no 'from' addresses specified ignore the message
if (addressesFrom == null) {
Debug.logInfo("Incoming Email message ignored, had not 'from' email address", module);
return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "PartyCommEventMessageIgnoredNoFromAddressSpecified", locale));
}
// make sure this isn't a duplicate
List<GenericValue> commEvents;
try {
commEvents = EntityQuery.use(delegator).from("CommunicationEvent").where("messageId", messageId).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
if (!commEvents.isEmpty()) {
Debug.logInfo("Ignoring Duplicate Email: " + aboutThisEmail, module);
return ServiceUtil.returnSuccess(UtilProperties.getMessage(resource, "PartyCommEventMessageIgnoredDuplicateMessageId", locale));
}
// get the related partId's
List<Map<String, Object>> toParties = buildListOfPartyInfoFromEmailAddresses(addressesTo, userLogin, dispatcher);
List<Map<String, Object>> ccParties = buildListOfPartyInfoFromEmailAddresses(addressesCC, userLogin, dispatcher);
List<Map<String, Object>> bccParties = buildListOfPartyInfoFromEmailAddresses(addressesBCC, userLogin, dispatcher);
// Get the first address from the list - this is the partyIdTo field of the CommunicationEvent
if (!toParties.isEmpty()) {
Map<String, Object> firstAddressTo = toParties.get(0);
partyIdTo = (String) firstAddressTo.get("partyId");
contactMechIdTo = (String) firstAddressTo.get("contactMechId");
}
String deliveredTo = wrapper.getFirstHeader("Delivered-To");
if (deliveredTo != null) {
// check if started with the domain name if yes remove including the dash.
String dn = deliveredTo.substring(deliveredTo.indexOf('@') + 1, deliveredTo.length());
if (deliveredTo.startsWith(dn)) {
deliveredTo = deliveredTo.substring(dn.length() + 1, deliveredTo.length());
}
}
// if partyIdTo not found try to find the "to" address using the delivered-to header
if ((partyIdTo == null) && (deliveredTo != null)) {
result = dispatcher.runSync("findPartyFromEmailAddress", UtilMisc.<String, Object>toMap("address", deliveredTo, "userLogin", userLogin));
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
}
partyIdTo = (String) result.get("partyId");
contactMechIdTo = (String) result.get("contactMechId");
}
if (userLogin.get("partyId") == null && partyIdTo != null) {
int ch = 0;
for (ch = partyIdTo.length(); ch > 0 && Character.isDigit(partyIdTo.charAt(ch - 1)); ch--) {
}
// allow services to be called to have prefix
userLogin.put("partyId", partyIdTo.substring(0, ch));
}
// get the 'from' partyId
result = getParyInfoFromEmailAddress(addressesFrom, userLogin, dispatcher);
partyIdFrom = (String) result.get("partyId");
contactMechIdFrom = (String) result.get("contactMechId");
Map<String, Object> commEventMap = new HashMap<>();
commEventMap.put("communicationEventTypeId", "AUTO_EMAIL_COMM");
commEventMap.put("contactMechTypeId", "EMAIL_ADDRESS");
commEventMap.put("messageId", messageId);
String subject = wrapper.getSubject();
commEventMap.put("subject", subject);
// Set sent and received dates
commEventMap.put("entryDate", nowTimestamp);
commEventMap.put("datetimeStarted", UtilDateTime.toTimestamp(wrapper.getSentDate()));
commEventMap.put("datetimeEnded", UtilDateTime.toTimestamp(wrapper.getReceivedDate()));
// default role types (_NA_)
commEventMap.put("roleTypeIdFrom", "_NA_");
commEventMap.put("roleTypeIdTo", "_NA_");
// get the content(type) part
String messageBodyContentType = wrapper.getMessageBodyContentType();
if (messageBodyContentType.indexOf(';') > -1) {
messageBodyContentType = messageBodyContentType.substring(0, messageBodyContentType.indexOf(';'));
}
// select the plain text bodypart
String messageBody = null;
if (wrapper.getMainPartCount() > 1) {
for (int ind = 0; ind < wrapper.getMainPartCount(); ind++) {
BodyPart p = wrapper.getPart(ind + "");
if (p.getContentType().toLowerCase(Locale.getDefault()).indexOf("text/plain") > -1) {
messageBody = (String) p.getContent();
break;
}
}
}
if (messageBody == null) {
messageBody = wrapper.getMessageBody();
}
commEventMap.put("content", messageBody);
commEventMap.put("contentMimeTypeId", messageBodyContentType.toLowerCase(Locale.getDefault()));
// check for for a reply to communication event (using in-reply-to the parent messageID)
String[] inReplyTo = wrapper.getHeader("In-Reply-To");
if (inReplyTo != null && inReplyTo[0] != null) {
GenericValue parentCommEvent = null;
try {
parentCommEvent = EntityQuery.use(delegator).from("CommunicationEvent").where("messageId", inReplyTo[0].replaceAll("[<>]", "")).queryFirst();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (parentCommEvent != null) {
String parentCommEventId = parentCommEvent.getString("communicationEventId");
String orgCommEventId = parentCommEvent.getString("origCommEventId");
if (orgCommEventId == null) {
orgCommEventId = parentCommEventId;
}
commEventMap.put("parentCommEventId", parentCommEventId);
commEventMap.put("origCommEventId", orgCommEventId);
}
}
// populate the address (to/from/cc/bcc) data
populateAddressesFromMessage(wrapper, commEventMap);
// store from/to parties, but when not found make a note of the email to/from address in the workEffort Note Section.
String commNote = "";
if (partyIdFrom != null) {
commEventMap.put("partyIdFrom", partyIdFrom);
commEventMap.put("contactMechIdFrom", contactMechIdFrom);
} else {
commNote += "Sent from: " + ((InternetAddress) addressesFrom[0]).getAddress() + "; ";
commNote += "Sent Name from: " + ((InternetAddress) addressesFrom[0]).getPersonal() + "; ";
}
if (partyIdTo != null) {
commEventMap.put("partyIdTo", partyIdTo);
commEventMap.put("contactMechIdTo", contactMechIdTo);
} else {
commNote += "Sent to: " + ((InternetAddress) addressesTo[0]).getAddress() + "; ";
if (deliveredTo != null) {
commNote += "Delivered-To: " + deliveredTo + "; ";
}
}
commNote += "Sent to: " + ((InternetAddress) addressesTo[0]).getAddress() + "; ";
commNote += "Delivered-To: " + deliveredTo + "; ";
if (partyIdTo != null && partyIdFrom != null) {
commEventMap.put("statusId", "COM_ENTERED");
} else {
commEventMap.put("statusId", "COM_UNKNOWN_PARTY");
}
if (commNote.length() > 255) {
commNote = commNote.substring(0, 255);
}
if (!("".equals(commNote))) {
commEventMap.put("note", commNote);
}
commEventMap.put("userLogin", userLogin);
// Populate the CommunicationEvent.headerString field with the email headers
StringBuilder headerString = new StringBuilder();
Enumeration<?> headerLines = wrapper.getMessage().getAllHeaderLines();
while (headerLines.hasMoreElements()) {
headerString.append(System.getProperty("line.separator"));
headerString.append(headerLines.nextElement());
}
String header = headerString.toString();
commEventMap.put("headerString", header.replaceAll("[<>]", ""));
result = dispatcher.runSync("createCommunicationEvent", commEventMap);
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
}
communicationEventId = (String) result.get("communicationEventId");
Debug.logInfo("Persisting New Email: " + aboutThisEmail + " into CommunicationEventId: " + communicationEventId, module);
// handle the attachments
createAttachmentContent(dispatcher, delegator, wrapper, communicationEventId, userLogin);
// For all addresses create a CommunicationEventRoles
createCommEventRoles(userLogin, delegator, dispatcher, communicationEventId, toParties, "ADDRESSEE");
createCommEventRoles(userLogin, delegator, dispatcher, communicationEventId, ccParties, "CC");
createCommEventRoles(userLogin, delegator, dispatcher, communicationEventId, bccParties, "BCC");
// get the related work effort info
List<Map<String, Object>> toWorkEffortInfos = buildListOfWorkEffortInfoFromEmailAddresses(addressesTo, userLogin, dispatcher);
List<Map<String, Object>> ccWorkEffortInfos = buildListOfWorkEffortInfoFromEmailAddresses(addressesCC, userLogin, dispatcher);
List<Map<String, Object>> bccWorkEffortInfos = buildListOfWorkEffortInfoFromEmailAddresses(addressesBCC, userLogin, dispatcher);
// For all WorkEffort addresses create a CommunicationEventWorkEffs
createCommunicationEventWorkEffs(userLogin, dispatcher, toWorkEffortInfos, communicationEventId);
createCommunicationEventWorkEffs(userLogin, dispatcher, ccWorkEffortInfos, communicationEventId);
createCommunicationEventWorkEffs(userLogin, dispatcher, bccWorkEffortInfos, communicationEventId);
Map<String, Object> results = ServiceUtil.returnSuccess();
results.put("communicationEventId", communicationEventId);
results.put("statusId", commEventMap.get("statusId"));
return results;
} catch (MessagingException | GenericServiceException | GenericEntityException | IOException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
}
use of org.apache.ofbiz.service.mail.MimeMessageWrapper in project ofbiz-framework by apache.
the class CommunicationEventServices method processBouncedMessage.
/*
* 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");
LocalDispatcher dispatcher = dctx.getDispatcher();
Delegator delegator = dctx.getDelegator();
int parts = wrapper.getMainPartCount();
if (parts >= 3) {
// it must have all three parts in order to process correctly
// get the second part (delivery report)
// index 1 should be the second part
String contentType = wrapper.getPartContentType("1");
if (contentType != null && "message/delivery-status".equalsIgnoreCase(contentType)) {
Debug.logInfo("Delivery status report part found; processing...", module);
// get the content of the part
String part2Text = wrapper.getPartRawText("1");
if (part2Text == null) {
part2Text = "";
}
if (Debug.verboseOn()) {
Debug.logVerbose("Part 2 Text :\n\n" + part2Text, module);
}
// 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
// index 2 should be the third part
String part3Text = wrapper.getPartRawText("2");
if (part3Text == null) {
part3Text = "";
}
if (Debug.verboseOn()) {
Debug.logVerbose("Part 3 Text :\n\n" + part3Text, module);
}
// 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()) {
Debug.logInfo("Found message-id : " + m3.group(), module);
messageId = m3.group(1);
}
// find the matching communication event
if (messageId != null) {
List<GenericValue> values;
try {
values = EntityQuery.use(delegator).from("CommunicationEvent").where("messageId", messageId).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
if (UtilValidate.isNotEmpty(values)) {
// there should be only one; unique key
GenericValue value = values.get(0);
// update the communication event status
Map<String, Object> updateCtx = new HashMap<>();
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);
if (ServiceUtil.isError(result)) {
String errorMessage = ServiceUtil.getErrorMessage(result);
Debug.logError(errorMessage, module);
}
} 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 CommunicationEvent with the matching messageId : " + messageId, module);
}
// no communication events found for that message ID; possible this is a NEWSLETTER
try {
values = EntityQuery.use(delegator).from("ContactListCommStatus").where("messageId", messageId).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError(e.getMessage());
}
if (UtilValidate.isNotEmpty(values)) {
// there should be only one; unique key
GenericValue value = values.get(0);
Map<String, Object> updateCtx = new HashMap<>();
updateCtx.put("communicationEventId", value.getString("communicationEventId"));
updateCtx.put("contactListId", value.getString("contactListId"));
updateCtx.put("contactMechId", value.getString("contactMechId"));
updateCtx.put("partyId", value.getString("partyId"));
updateCtx.put("statusId", "COM_BOUNCED");
updateCtx.put("userLogin", context.get("userLogin"));
Map<String, Object> result;
try {
result = dispatcher.runSync("updateContactListCommStatus", 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 ContactListCommStatus with the matching messageId : " + messageId, module);
}
}
}
} else {
Debug.logWarning("No message ID attached to part", module);
}
}
}
}
return ServiceUtil.returnSuccess();
}
use of org.apache.ofbiz.service.mail.MimeMessageWrapper in project ofbiz-framework by apache.
the class CommunicationEventServices method logIncomingMessage.
public static Map<String, Object> logIncomingMessage(DispatchContext dctx, Map<String, ? extends Object> context) {
MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper");
Debug.logInfo("Message recevied : " + wrapper.getSubject(), module);
Debug.logInfo("-- Content Type : " + wrapper.getContentType(), module);
Debug.logInfo("-- Number of parts : " + wrapper.getMainPartCount(), module);
Debug.logInfo("-- Number of attachments : " + wrapper.getAttachmentIndexes().size(), module);
Debug.logInfo("-- Message ID : " + wrapper.getMessageId(), module);
Debug.logInfo("### MESSAGE ###\n\n" + wrapper.getMessageBody(), module);
List<String> attachmentIndexes = wrapper.getAttachmentIndexes();
if (attachmentIndexes.size() > 0) {
Debug.logInfo("### ATTACHMENTS ###", module);
for (String idx : attachmentIndexes) {
Debug.logInfo("### -- Filename : " + wrapper.getPartFilename(idx), module);
Debug.logInfo("### -- Content Type : " + wrapper.getPartContentType(idx), module);
}
}
return ServiceUtil.returnSuccess();
}
use of org.apache.ofbiz.service.mail.MimeMessageWrapper in project ofbiz-framework by apache.
the class CommunicationEventServices method updateCommEventAfterEmail.
/*
* Update the communication event with information from the email;
* runs as a post-commit ECA on sendMail and sendMultiPartMail services
* - service should run as the 'system' user
*/
public static Map<String, Object> updateCommEventAfterEmail(DispatchContext dctx, Map<String, ? extends Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
String communicationEventId = (String) context.get("communicationEventId");
MimeMessageWrapper wrapper = (MimeMessageWrapper) context.get("messageWrapper");
Map<String, Object> commEventMap = new HashMap<>();
commEventMap.put("communicationEventId", communicationEventId);
commEventMap.put("subject", wrapper.getSubject());
commEventMap.put("statusId", "COM_COMPLETE");
commEventMap.put("datetimeEnded", UtilDateTime.nowTimestamp());
commEventMap.put("entryDate", wrapper.getSentDate());
commEventMap.put("messageId", wrapper.getMessageId());
commEventMap.put("userLogin", userLogin);
commEventMap.put("content", wrapper.getMessageBody());
// populate the address (to/from/cc/bcc) data
populateAddressesFromMessage(wrapper, commEventMap);
// save the communication event
try {
Map<String, Object> result = dispatcher.runSync("updateCommunicationEvent", commEventMap);
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result));
}
} catch (GenericServiceException e) {
return ServiceUtil.returnError(e.getMessage());
}
// attachments
try {
createAttachmentContent(dispatcher, dctx.getDelegator(), wrapper, communicationEventId, userLogin);
} catch (GenericServiceException | GenericEntityException e) {
return ServiceUtil.returnError(e.getMessage());
}
return ServiceUtil.returnSuccess();
}
Aggregations