Hi there “Process Automation” fans,
Welcome to a new installment of “Process Automation” tips.
Last week we put the service call receiveEmail
to the test. For this week we’ll implement the undocumented best-practices of OpenText as they see “receiveEmail” as a middleware call which you don’t put at your front-desk (which is for me for unclear!?). Ok, we just swallow this idea with a recommended implementation…Watch and learn how we create a best-practice on top of a best-practice!
Let’s get right into it…
We split this post into three sections:
- Sending out a mail from an entity (the easy part)
- Reply to the same mail and saving it within the entity instance (where we expose
<{ItemId}@opentext.com>
in a reference header!) - Creating an entity instance from the mail AND saving the mail with the instance
But first…We require a mail server to communicate with AND we require an entity with mail-enriched building blocks.
Sending out mail from an entity
That’s as easy as following the first section “Send out an E-mail” of my own post “Master the game; Using Gmail as the ultimate email service container for our beloved platform”. Once in place, you can send a mail via SendMail
(after doing the SetProfile
call!).
You see me sending a mail to
antal@bos-ictservices.nl
with a from-addressOPA@gmail.com
. For now, that’s fine, but later, you want to reply to the from-address! So, eventually this must be a valid mail-address to send a mail to! It should even be a from-address that we can read out with a mail configuration in the ‘Email’ service container (not for now!).
Next, we create a new ‘Case’ entity and add the ‘Email’ building block with new configuration:
Notes:
- Save the
mc_case
config into aconfigs
folder of your project (just a good habit!)- You need to add the ‘Content’ BB to save mails (as configured in the ‘Email’ BB)
- In the
lyt_default
, add the ‘Emails’ panel to view it all in runtime!- Don’t forget to also add the ‘Web service’ BB with the CRUD operation (for now)
- With this ‘Web service’ BB, you also require a service container of the ‘Application server’ in the ‘System Resource Manager’ artifact!
Publish it all into runtime, create a new ‘Case’ instance, and create/send a new mail:
It will use the
SetProfile
details to (again) send a second mail (first one was from last week!).
Now for the great <{ItemId}@opentext.com>
trick!?…Save the mail (so, you get a .eml
file) from you client. I use Gmail itself (for the demo) where you can download the file here:
Open it with Notepad++ and watch this:
AHA-Moment…AND BUSTED!! 🤓
Time for our next section where exactly this reply reference is important!
Reply to mail and save with entity
So, now the other way around! I have my mail in the inbox of antal@bos-ictservices.nl
with a reference in the header to my entity ID! How and where do I reply to? Well, you need to reply (in our demo) to OPA@gmail.com
, and our mail configuration (of the mail service container) needs a “poller” to read the inbox of OPA@gmail.com
with a trigger on what to do when it finds a new mail!
For this case we can perfectly (for now!) use the documentation example as emailbox
configuration. In this example, you find (again!) the receiveEmail
service call which simply maps the email data to the correspondent service call entries (‘from’, ‘subject’, and ‘body’ as Base64 String…incl. possible mail-attachments as multipart request!)
Now, double-check two things:
- Did you create a label/folder
OPA_REPLY
in the (for meOPA@gmail.com
) mailbox? - Did you create a rule to apply this label when
@opentext.com
is in the header? Probably not, as I see that’s a limitation in Gmail! #WTF…So, we need to improvise with a different “reply” reference which is the subject hasRe:
!
After this change (including reading the comments in the XML part!) in the ‘Email’ service container, do a restart, check you logging Application_Server.xml
and 🤞 it gets green again (or solve the problem from your logging feedback)!
I have white smoke, so time for a reply-mail test (from antal@bos-ictservices.nl
to OPA@gmail.com
)…This is the result:
Nicely saved in the inbox of the referenced entity instance! 😎
Do you wonder what happens when we just send a new mail (without @opentext.com
in the references!) that has a subject part of Re:
? Yes, please…And guess what…In the email subject 'Re: test...', item ID is missing between [# and ]
! AHA-moment…That’s a familiar one from last week!
Be careful on this last assessment as it looks to me like the mail container gets into some endless looping!? Even a restart does not work as there is already a table entry in the database which starts the looping again…What table? Well, what about the
processing_status='RELEASED'
! Setting the value toCOMPLETED
solved it nicely!
…
I’m also cheating a little here because I don’t have the header-rule in place which will solve it. But still, you must avoid endless looping at all cause!
…
This last comment section does ring a completely different bell! Now I understand why OpenText’s advice (because of middleware!?) is against using receiveEmail
directly in the mail configuration of the relevant service container. Probably, because of this loose cannonball behavior on wrong receiving mail (I agree…the chance isn’t high, but it’s there)! Moving this logic to a BPM makes this (in my opinion #BUG!) controllable with an aborted BPM as a result…Please tell me I’m incorrect here, but I’m pretty certain that’s the exact reason (which they don’t communicate obviously)! 🤠
…
Time to move on…Time to remove the middleware call from the mail configuration and moving it to a solid (monkey-proof?) BPM implementation!
Create entity from mail and save the mail with the instance
Ok…When we remove the middleware call from the mailbox configuration, we need to replace it with something else? Yes, that (my friends) will be a BPM call AND executing a BPM in this (webservice only!) perspective can happen in two ways:
- Calling
ExecuteProcess
with the proper input; Read about it here, but you can also search to find more examples on the topic! - Extracting a service out of a BPM and calling that service with the proper input; Read about it here
We go for the ExecuteProcess
approach as you don’t need a dedicated BPM service container AND we don’t need a dedicated service call to expose to others that require it.
So, we need a simple BPM (bpm_manage_mail
) first (just an easy one-activity BPM…we do the implementation later):
Now we update our mail config by replacing receiveEmail
with ExecuteProcess
…And some other magic things:
1 | <message> |
Preview the end-result (with details from below) here
Make sure to restart the service container after this change, and do a first test sending out a mail from the entity, and reply to it like in the previous section (re:
in the subject). In the PIM, you should see an instance of our BPM:
Continue if you have a green light…
…
Now we need a BPM implementation, AND our BPM must be so smart that when we get a reply to a mail, we need to find the entity and the mail needs to save with the entity (via our well-known receiveEmail
service call)! When we don’t find an entity instance (we assume it’s a new instance) it needs to create a new entity instance, AND in the new entity we also need to save the mail!
Make sure to understand the scope as there is one glitch in this story…That’s when users start to manipulate the subject on a reply mail! For us no big deal, as manipulation will route to a new case; That’s a choice the end-user makes not following procedures!
This the pseudocode for our BPM implementation (which always brings new insights with a ChatGPT collaboration…try it!):
1 | public void processEmail(String subject, String to, String from, String attachment) { |
Now for the implementation part…Open the one-activity BPM from the beginning of this section, and start with an input message containing a set of elements in the BPM messagemap:
AND set this input message in the green ‘Start’ construct of the BPM:
Next step is to map our input data from the mail configuration into our BPM (check the <message>
and mappings
parts):
1 | <message> |
See the end-result here including the “secret” comments!
Restart the service again, and evaluate your mail reply action…Now watch the PIM, and check the input message for the instance:
OHHHH YEAH 😎…It’s a party! 🥳
…
With this in place, we continue the craftsmanship of our BPM from our pseudocode…Start with this:
From the messagemap, you can add the ‘local’ variable/element
caseNr
! (like you did the input message; now it’s not a message, but just an element on itself!)
NOW JUST WAIT A MINUTE…(I’m processing here!…)
Why on earth do we want to check the case number from a reply mail if the ‘Base64Attachment’ string in our mail has the ‘Reference’ <{ItemId}@opentext.com>
…remember? Why don’t we decode the String in the XPath call com.eibus.util.Base64.decode("{your_Base64String}")
(see here), and grab the entity ‘ItemId’ from it? That’s a far better/solid solution with a fail-save!
Just a moment of “AHA”! Is this possible from XPath?…Well, watch this:
1 | substring-before( |
Notes:
- The before/after substring will grab a string somewhere between two specific values:
References: <
and@opentext.com>
- The extra
concat()
makes sure thecom.eibus.util.Base64.decode()
accepts the input as a “String” value…don’t shoot the messenger!
What will it do with our pseudocode? It will be more like this:
1 | public void processEmail(String subject, String to, String from, String attachment) { |
Our BPM can now execute like this:
Notes:
- You can add webservices from the context menu of the relevant activities
- The
ReceiveEmail
requires a runtimereference in your project ofMethod Set Entity Email
in categoryOpenText Entity Runtime
! No clue? Read about it here- I convert my ‘local’ variable/element
caseNr
tocaseItemId
.
Have a look at this consolidated view of the messagemap for this BPM (read this always from right/source to left/target!):
Publish your changes, and give it a shot on a reply mail from your entity instance AND a new mail for create a new case. Check both instances on the inbox items for a validation on a correct (and solid!) implementation!
In my VM, it’s white smoke with green checkmarks all over the place (on both test-cases)! 😎
For the new case test, you still need to make sure you match the mail rule which is starting with
Re:
, but you can add an extra rule in your mailbox that will move the mail to the same label/folderOPA_REPLY
which will run the same BPM! Now that I’m ReThinking this over, it would be better to use a label/folder likeOPA_MAIL
!
…
Just an interesting question? Can we also create a new entity instance from a mail send out by another entity applying the subject of our mail-rule? Well, not anymore with our solid “Reference” check! If we had checked the ‘caseNr’ from the subject, the answer is YES when you manipulate the subject on your reply!
Another question? What happens to mail that does not apply our mail rule? Well, what do you think will happen with those mails? Indeed, they will stick in your mailbox not triggering any BPM via the mail service container! 😉
Again, a best-practice (on top of a best-practice!) “DONE” with a solid BPM implementation for correct receiving emails from a server. Why the initial best-practice is undocumented, is unclear for me?? It raises other questions on what other best-practices are available from the OpenText team? Tell us! We can all learn from it which makes the community stronger with solid best-practice implementations at your licensed customers! No more to say; Let’s see…I go for a weekend and see you all next time in another topic about “OpenText Process Automation Tips”.
Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The Process Automation guy”?