IBMDO YOU?Hi, I'm MBO!

Settings

Make the site feel at home on your screen.

Theme

Loading your theme preference.

Keyboard shortcuts

Open search from anywhere, then move through the results without leaving the keyboard.

Open settings
Ctrl,or⌘,
Open search
CtrlKor⌘K
Select a search result
↑↓
Open the selected result
Enter
Close an open dialog
Esc

I Build Maximo

Send email from a Maximo automation script

Use a communication template to email the previous CHANGEBY user's primary address from a Maximo Jython automation script.

I Beat Maximo — confirmed solution

Sometimes an automation script needs to tell someone what has happened to a record. The useful part is deciding who that someone should be.

In this example, the recipient comes from the previous value of CHANGEBY. The script resolves that Maximo user to a person, finds their primary email address and sends a message using a communication template.

The template handles the message content. The script handles the recipient. No SMTP implementation required in the script itself.

The approach

The supplied script follows this chain:

  1. Read the previous in-memory value of CHANGEBY on the current MBO.
  2. Find the corresponding MAXUSER row and its PERSONID.
  3. Retrieve the PERSON record using the current user's security context.
  4. Read the person's PRIMARYEMAIL relationship.
  5. Create a communication on the current record, select a template and set SENDTO.
  6. Attempt to send the message, marking the communication as failed if sending raises an exception.

This is Jython running inside Maximo's automation scripting environment. The psdi imports and implicit mbo variable are provided by Maximo; it is not a standalone Python script you can run from a terminal.

Prepare the template and launch point

Create or identify a communication template appropriate for the object your script runs against. Check its sender, subject, message and any record substitutions, along with its recipient configuration. In the supplied code, the template ID is ASSETSPECREJ; replace that with your own template ID when adapting it.

For this ASSETSPEC implementation, I also had to add a relationship named COMMLOG to the ASSETSPEC object in Database Configuration, pointing to the COMMLOG object. This relationship is needed in this setup for creating communication log records through mbo.createComm(). The relationship in this example uses the following WHERE clause:

OWNERID = :ASSETSPECID
AND OWNERTABLE = 'ASSETSPEC'

This matches communication log records whose OWNERID is the current record's ASSETSPECID and whose OWNERTABLE is ASSETSPEC. Both conditions identify the owning record: the table condition keeps communications for other object types out of the relationship. If adapting the script to another object, use that object's owning table name and identifier.

Maximo's outbound email configuration also needs to work. Before debugging the lookup, verify that an ordinary communication can be sent from the relevant application.

The script expects:

  • A current mbo supporting CHANGEBY and createComm().
  • A MAXUSER record linking the selected user ID to a person.
  • A PRIMARYEMAIL relationship on that person returning an email record.
  • Permission for the executing user to read the necessary records and create the communication.

Choose the launch point for the business event that should send the notification. The code does not include a status-change condition or a launch-point definition, so attaching it to every save would not, by itself, restrict email to a rejection or approval event.

The script

The script below resolves the recipient and sends the template-based communication:

from psdi.mbo import MboConstants, SqlFormat
from psdi.server import MXServer
 
# Find the person linked to the previous CHANGEBY user.
personWhereFormat = SqlFormat(
    "PERSONID IN (SELECT PERSONID FROM MAXUSER WHERE USERID = :1)"
)
personWhereFormat.setObject(
    1,
    "MAXUSER",
    "USERID",
    mbo.getMboValue("CHANGEBY").getPreviousValue().toString()
)
 
personSet = MXServer.getMXServer().getMboSet("PERSON", mbo.getUserInfo())
personSet.setWhere(personWhereFormat.format())
personSet.reset()
 
personRecord = personSet.moveFirst()
 
if personRecord is not None:
    emailSet = personRecord.getMboSet("PRIMARYEMAIL")
    emailRecord = emailSet.moveFirst()
 
    if emailRecord is not None:
        newCommunication = mbo.createComm()
        newCommunication.setValue("TEMPLATEID", "ASSETSPECREJ")
        newCommunication.setValue("SENDTO", emailRecord.getString("EMAILADDRESS"))
 
        try:
            newCommunication.sendMessage()
        except:
            newCommunication.setValue(
                "ISSENDFAIL", True, MboConstants.NOACCESSCHECK
            )

IBM's automation scripting guide demonstrates the same createComm(), TEMPLATEID and sendMessage() pattern in an object-structure action. Here, the additional lookup supplies a specific recipient.

Why look through MAXUSER?

CHANGEBY identifies a user. The email address belongs to a person. Those identifiers should not be assumed to be interchangeable.

The query follows the explicit link through MAXUSER.PERSONID:

PERSONID IN (
    SELECT PERSONID FROM MAXUSER WHERE USERID = :1
)

SqlFormat.setObject() supplies the user ID using the metadata for MAXUSER.USERID, rather than building a WHERE clause by concatenating the value into quoted SQL.

The PERSON set is opened with mbo.getUserInfo(). That keeps the lookup in the executing user's context; this code does not deliberately switch to a privileged system user.

After finding the person, the script uses the existing PRIMARYEMAIL relationship. It takes the first related record, so check the relationship definition and primary-address data in your environment rather than treating it as an arbitrary list of addresses.

Previous value is about timing

The most important line is also the easiest one to misread:

mbo.getMboValue("CHANGEBY").getPreviousValue().toString()

This reads the previous value held by the current MBO value. It does not query an audit table or reconstruct the record's entire change history.

Whether that value represents the person you intend to notify depends on when the launch point runs and when CHANGEBY changes. If the intention is to notify the previous editor, verify that behaviour at the actual launch point. A fresh load of a record is not a substitute for capturing the right transition.

Test with two different users and inspect which address is selected. Also test new records, unchanged values and a missing previous user. If you need the original requester, owner or an earlier historical editor, resolve that identity explicitly instead.

What happens when sending fails?

The exception handler sets ISSENDFAIL on the communication using NOACCESSCHECK. That flag bypasses access checking for this particular assignment; it is not a general bypass for the person lookup or the entire script.

The original exception is swallowed. This lets the script continue if that flag assignment succeeds, but it also means a failed send can be easy to miss unless staff monitor failed communications.

Only sendMessage() is inside the try block. Failures while resolving the recipient, creating the communication or assigning the template still propagate.

There is no explicit save() in this script and no retry loop. Check communication persistence in the surrounding transaction and launch point. Setting ISSENDFAIL alone does not establish that the failure record was committed or that a retry will occur.

Checks before reusing it

The snippet shows the core behaviour. When adapting it, address these details in the surrounding implementation:

  • Missing recipients: no matching person or email record causes the script to do nothing. Decide whether that should instead produce a visible message or a diagnostic. A blank EMAILADDRESS is not explicitly checked.
  • Resource ownership: the script opens personSet directly through MXServer. Add appropriate cleanup() and close() handling in a finally block for that independently acquired set. The related email set belongs to the person relationship; do not indiscriminately close MBO sets owned by the current record.
  • Repeated execution: there is no duplicate-send protection. Confirm the launch point cannot send the same notification repeatedly during saves, retries or repeated actions.
  • Transaction timing: an email already sent cannot be recalled because a later database operation rolls back. Choose the sending point with that possibility in mind.
  • Template recipients: review To, CC and BCC behaviour so the resulting communication reaches exactly the intended audience.
  • Failure visibility: use approved logging or communication monitoring without recording full email bodies or personal recipient details unnecessarily.

A short verification checklist

Use a non-production mailbox and test:

  1. A previous user with a valid person and primary email address.
  2. A previous user without a person or primary email record.
  3. A blank or unexpected previous CHANGEBY value at your launch point.
  4. An unavailable mail service and the resulting failed communication.
  5. A repeated action and a transaction that fails after the send attempt.

No Maximo version or launch-point configuration was supplied with this example, so neither is listed as verified here.

The useful pattern is small: resolve the recipient through Maximo's records, create the communication on the business record and let the communication template provide the message. The part worth spending time on is making sure the right person receives it at the right point in the transaction.

Find the fix

Search articles

Esc

Search titles, technical terms or error codes.