Some Options for Sending Emails in PeopleTools

By Chris Malek | Sat, Sep 1, 2012

There are many scenarios where you would want to send emails out of PeopleTools.

  • A new business transaction is pending a user.
  • An error occurred in a business transaction and you need to alert an administrator.
  • A deadline is approaching for a business transaction and you need the user to login.

There are many technical options in PeopleTools to send these emails.

  • PeopleTools Workflow Objects
    • I never use workflow objects. They are archaic and inflexible. Don’t use them in production code (stay tuned for a post about this).
  • SendMail PeopleCode Function
  • PT_MCF_MAIL:MCFOutboundEmail application class

SendMail PeopleCode Function

The SendMail PeopleCode function allows you to send emails easily. However, there are some limitations including:

  • You cannot do HTML emails “correctly” because you cannot send multi-part messages.
  • Non-Production emails will trigger to real email addresses.
    • This is a huge issue for testing and production support.
  • At one point, the documentation said that this was a deprecated function. However, the latest documentation no longer states that.
  • Every piece of code has to do an email lookup causing redundancy
  • You can’t set headers

PT_MCF_MAIL:MCFOutboundEmail Application Class

The PT_MCF_MAIL:MCFOutBoundEmail Application class allows you more control than SendMail. If you take a look at the code examples in PeopleBooks, you see that you have really fine grained control over things like headers and even the email server. The PT_MCF_MAIL:MCFOutBoundEmail class is a dramatic improvement over SendMail.

  • The classes in the PT_MC_MAIL application package give you lower level control over the different email options
  • You can set headers, priorities, and other email options
  • You can make one connection to the email server and send multiple emails
  • You can send multi-part messages

These are great improvements. However, from the average application developer’s perspective who is writing code in PeopleSoft, there are still some issues that need to be addressed.

  • Non-Production emails will trigger to real email addresses.
    • This is a huge issue for testing and production support.
  • Testing emails are hard unless your testers change every email address in the system. If this is done then you are not really testing because it hard to know who would have actually got the email if the code were running in production.
  • Each piece of application code sending emails has to look up the email addresses
    • This causes code redundancy and violates DRY principles
    • Your company may have rules about what addresses should be used for emails from PeopleSoft. You may not want PeopleSoft emails to go to yahoo or gmail addresses. You want these rules in a central piece of code and not repeated throughout your code base.
  • Each piece of application code sending emails requires a relatively “large amount” of code to send an email.
  • If your email server happens to be down during the attempted connection is not delivered and the end use may even see an error.
  • There is no logging of emails that are sent.
  • There is no way to turn off emails without a code change

A Proposed Enhancement

One of the largest issues I see with sending emails is testing and non-production data refreshes. When a database gets refreshed, you will have functional users go in and do testing. You do no want users getting emails from a non-production database. For example, I once worked at a client where terminations in HR would be automatically emailed to an expansive distribution list to revoke access to various systems and buildings. A user was testing some new functionality and needed a terminated employee. She just happened to terminate a Vice President in the testing database. However, the email went to the real email distribution list and it caused days of wasted time and at least 100 wasted man hours discussing the root cause. Imagine if these emails were going to students or end users and they were not caught. There is a very simple solution to prevent this from ever happening.

You should have a custom email Application Class which will provide the missing functionality. This would be a common piece of code that all emails are routed through.

The goal of this common piece of code are:

  • One common piece of code that sends all emails
  • Ensure that non-productions emails will never ever go to the real people
  • Make testing for new development easier, since emails will be redirected to whatever address you need.
  • Allow for future changes like appending footers to all emails
  • Allow for logging of all emails
  • Allow for de-activating certain emails in production without a code change.

Here is the functionality overview

  • You pass in either OPRID, ROLE, or EMPLID which is easily available in PeopleCode.
    • All email address lookup code will happen internally
  • You pass in a subject
  • You pass in a text body
  • You pass in an optional HTML body
  • You pass in a “message id” (explained later)
  • You call the “send” method and check the return.

Here is some sample code that exhibits the interface. This is an actual API that I built for a client that sends thousands of emails a day.

import CHG_UTILITIES:email; 

&msgid = "your_message_id"; 

Local CHG_UTILITIES:email &em = create CHG_UTILITIES:email(&msgid); 

If &em.AddRecipient("TO", "EMPLID", "0001222122") Then 
    /* returned true "" email address was added */ 
ELSE 
    /* returned false  could not find email address for emplid */ 
    /* Take some action */ 

END-IF; 

Local boolean &b; 
/* example of added more recipients */ 
/* Call AddRecipient as many times as needed */
&b = &em.AddRecipient("CC", "ROLE", "SOME_PEOPLESOFT_ROLE"); 
&b = &em.AddRecipient("CC", "EMAILID", "john@somewhere.com"); 

&em.textBody = "My text body"; 

&em.htmlBody = "some html body"; 

&em.Subject = "my subject"; 

&b = &em.send(); 

If &b = true then 
    &deliveredToAddresses = &em.eMail.ValidSentAddresses; 
Else 

    /* 
     something bad happened you can check different things from the eMail Object
    &em.eMail.ResultOfSend 
    &em.eMail.ValidSentAddresses 
    &em.eMail.InvalidAddresses 
    &em.eMail.ErrorDescription 
    &em.eMail.ErrorDetails 
    &em.eMail.SMTPServer */ 

End-if; 

The code uses the PT_MC_MAIL application package code to actually send the emails but wraps it in some custom code. The “Message ID” is a simple table that holds a unique string created by the developer that is referenced in code when calling the common email class. It serves a few purposes.

  1. If the code is not running in production, it delivers the email to the address listed in the table

    • Additionally, it appends some text to the bottom of the email to indicate who the email would have gone to in a production environment.
  2. You can turn off emails in production by just flipping the status to in-active.

  3. It controls the logging level.

Message ID Non-Production Email Active Description Log Level
HR_TERM_EVENT john@somedomain.com Y No Logging
FIN_STUDENT_RECEIPT sally@somedomain.com Y Full Logging

I have had this code running at a client for years and it has been invaluable for testing. Each user can setup their own email address in the message id table and have just their emails delivered to them. They also have full view of who the email would have gone to because the function appends that information to the bottom of the email if running in a test database. After database refreshes no special procedure needs to happen to ensure that emails from testing database get pushed to non-project members.

If you are interested in the actual implementation details please contact me and I will see if I can get you the code.

Article Categories