Please rate how useful you found this document: 
Average: 3.4 (8 votes)
Contents: [hide]

Overview

Notifications can be used to keep users apprised of new cases in their Inbox and notify them at specified times while running cases. In ProcessMaker, all notifications are sent to users via email, which is why it is important to enter a valid email address for each user and properly configure ProcessMaker to connect to an email server so notifications can be sent out.

There are three types of notifications:

The subject line and body of these email notifications can be customized, and system variables and case variables can be inserted to personalize the email for the recipient using data from the current case.

The content of Task Notifications is in plain text, which is defined in the Task Properties. In contrast, the content of Message Events and Trigger Messages is specified inside a template file, which permits the use of HTML formatting. The template file can be created using ProcessMaker's template editor or it can be uploaded after being created in an external HTML editor such as FrontPage, DreamWeaver or BlueGriffon.

Note: Emails are sent to the configured email server when cron.php is executed, so the ProcessMaker server needs to be configured to execute a cron job in Linux/UNIX or a Scheduled Task in Windows.

Task Notifications

Note: Take into consideration that in cases where the next task of the process routes into a sub-process, the Case Number in the Task Notifications will be the number of the master process.

Task Notifications are useful for keeping users apprised when they have been assigned to work on a task in a case.

To create a message sent to the assigned user, go to the DESIGNER menu and open a process for editing. In the process map, right click on a task that should send out notifications when users are assigned to work on the task when running cases. In the dropdown menu that appears, select the Properties option.

Go to the Notifications tab and mark the After routing notify the next assigned user(s) checkbox. Then define the content of the notification. System variables and case variables can be inserted in the content and in the Subject of the email message.

For a simple message without formatting, choose the Plain Text option. Enter text in the Message box.

For more control over the formatting, select the HTML Template option for the Content Type dropdown box. Then, select the name of the template file to be used for the body of the email message. To create template files, see Templates.

When done defining the task notification, click on Save.

Note: A Task Notification cannot be sent to a Script Task because it doesn't have an assigned user, which is required for a Task Notification to be sent.

Inserting Variables

To insert a variable in the email, click on the [@@] button and select the variable to insert. @@variable will insert the variable enclosed in double quotation marks, whereas @#variable inserts the variable without enclosing quotation marks. Make sure that all variables used in the message have already been created at some earlier point in the process. System variables (such as @@USR_USERNAME and @@APPLICATION) are automatically created and case variables are created in Dynaform fields or defined in Triggers.

When a field in a Dynaform is submitted, ProcessMaker stores both a @@variable and @@variable_label for the field and either variable can be used in the email template. @@variable is the value that is stored internally by ProcessMaker and @@variable_label is the text displayed to the user:

  • For textboxes and textareas, there is no difference between @@variable and @@variable_label.
  • For dropdown boxes and radio buttons, the value of @@variable is the value/key of the selected option and @@variable_label is the displayed text of the selected option. These are defined either in the field's options property or by the first and second fields returned by the sql query.
  • A checkbox (which is not in a grid) has a value of ["1"] if marked or ["0"] if unmarked, so it can't be used directly in a template because it is an array. Instead, use @@variable_label, which is "true" if marked and "false" if unmarked by default; however, these values can be changed by default. If a checkbox is inside a grid, then its @@variable is set to "1" if marked or "0" if unmarked, which are strings that can be used in templates.
  • For datetime fields, @@variable is the datetime in "YYYY-MM-DD HH:MM:SS" format, such as "2016-02-25 16:03:59". In contrast, @@variable_label is the datetime configured by the field's format property. For example, if the format is "MMMM Do, YYYY", then it would be "February 2nd, 2016".
  • For checkgroup fields, @@variable is ["option1", "option2", ...], such as ["accounting","landscaping","cleaning"], which is an array and therefore cannot be inserted into templates. Instead, use @@variable_label, which is a string in the form "["Option 1","Option 2",...]", such as "["Accounting","Landscaping","Cleaning and janitorial"]".
    Note: For prettier formatting, create a string variable and trigger that is executed beforehand that stores the selected options in separate lines in the string variable. The json_decode() function can be used to convert @@variable_label into an array. For example, the following trigger can be used for a checkgroup whose variable is named "selectServices":
    @@selectServicesFormatted = '';
    $aOptions = json_decode(@@selectServices_label);
    foreach ($aOptions as $option) {
        @@selectServicesFormatted .= $option . "<br>\n";
    }
    Then, insert @#selectServicesFormatted in the template.
  • For file fields, @@variable_label has the filename of the selected file in a JSON array, such as "["employeePhoto.jpg"]" or "[]" if no file was selected. In version 3.0.1.8 and later, @@variable is "["file-uid"]", such as "["263247890574cd24044f980079517567"]" or "[]" if there is no selected file.
    Note: If the filename without brackets is necessary, create a string variable and a trigger that is executed beforehand that stores the filename in the string variable. The json_decode() function can be used to convert @@variable_label into an array. For example, the following trigger can be used for a file field whose variable is named "invoiceFile":
    @@invoiceFilename = '';
    $aFilenames = json_decode(@@invoiceFile_label);
    if (count($aFilenames) > 0) {
        @@invoiceFilename = $aFilenames[0];
    }
    Then, insert @#invoiceFilename in the template.
  • For grids, there is no @@variable_label variable. See below.

Note: If a case variable doesn't exist, the message will be sent out with the name of the variable in the text. Case variables will not be created if a Dynaform is not submitted or has a condition that evaluates to false, which causes the Dynaform to be skipped in the case. In order to avoid variable names appearing in messages, fire a trigger after the Dynaform and check whether the variable has been set. If not, set the variable to an empty string, so that any subsequent notifications will insert a blank space in place of the variable name:

if (!isset(@@someVariable)) {  
   @@someVariable = "";
}

Message Events

Messages events can be used to send out messages at specified timings. For more information, see Events.

Trigger Messages

Email notifications can be sent out in triggers using the PMFSendMessage() function. Sending out messages in Triggers provides a great deal of flexibility, since the parameters for the PMFSendMessage() function allow the sender, the list of recipients, the subject line, the template file and even customized insertion variables to be specified. In addition, sending the message can be based upon the conditions of the particular case, a condition can be set for the firing of the trigger or the PMFSendMessage() function can be wrapped inside an if clause in the Trigger code.

In order to configure the notification, the following steps are necessary:

  1. Create the HTML email template.
  2. Create a trigger containing the PMFSendMessage() function.
  3. Assign the trigger to a step in the process.

Create the HTML Email Template

Email template files can be created inside ProcessMaker with the WYSIWYG editor in the Templates option in the Main Toolbox. For greater creativity, create the template file with an external plain text editor or HTML editor and then upload it to ProcessMaker.

Open a process for editing. Click on the "Template" option in the main toolbox.

Then click on either the Create or Upload links to create or upload the template file.

The template file will determine the body of the email message. This text can contain system and case variables and HTML tags. For more information on the format of template files, see Output Documents. For example, the following template is used when a leave request is approved: Dear @#reqUserName,
Your leave request has been approved. Please find details below:
Date From: @#fromReq Date To: @#toReq Days Requested: @#daysReq
Once your leave period has ended, please do not forget to fill out a Leave Report upon returning.
Regards,   @#reqSupervisor

It's HTML code can be edited by clicking on the button in the editor to see the following HTML code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
<p>Dear @#reqUserName, <br>
Your leave request has been approved.  Please find details below: <br>
 <b>Date From:</b>      @#fromReq <br>
 <b>Date To:</b>        @#toReq   <br>
 <b>Days Requested:</b> @#daysReq <br>
<br>
Once your leave period has ended, please do not forget to fill out a Leave Report upon returning. <br><br>
Regards, <br>
 &nbsp; @#reqSupervisor</p>
</body>
</html>

Links to Cases in Templates

The email template can also contain links to access resources inside ProcessMaker. To learn more about web browser redirection inside ProcessMaker, see JavaScript Frames, the G::header() function and the Link field.

An email template can include a link to open a case with a click of the mouse. Links to the current case can be constructed using system variables. For example, to open a link to the current case:

Dear @#reqUserName,

Your leave request has not yet been approved. Please find the details below:
Date From: @#fromReq Date To: @#toReq Days Requested: @#daysReq
We need you to fill in some details. Please click the link below:
http://example.com/sys@#SYS_SYS/@#SYS_LANG/@#SYS_SKIN/cases/open?APP_UID=@#APPLICATION&DEL_INDEX=@#INDEX&action=draft

Regards,   @#reqSupervisor

Its HTML code can be edited by clicking on the button in the editor to see the following HTML code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
<p>Dear @#reqUserName, <br>
Your leave request has been approved.  Please find details below:</p>
<table>
<tr><td><b>Date From:</b>     </td><td>@#fromReq</td></tr>
<tr><td><b>Date To:</b>       </td><td>@#toReq  </td></tr>
<tr><td><b>Days Requested:</b></td><td>@#daysReq</td></tr>
</table>
<p>We need you to fill in some details. Please click the link below:<br>
<a href="http://example.com/sys@#SYS_SYS/@#SYS_LANG/@#SYS_SKIN/cases/open?APP_UID=@#APPLICATION&DEL_INDEX=@#INDEX&action=draft">http://example.com/sys@#SYS_SYS/@#SYS_LANG/@#SYS_SKIN/cases/open?APP_UID=@#APPLICATION&amp;DEL_INDEX=@#INDEX&amp;action=draft</a></p>

<p>Regards, <br>
 &nbsp; @#reqSupervisor</p>
</body>
</html>

Remember that the person receiving the email needs to either be assigned to work on the current task in the case or have process permissions to open the case. If opening a case as a Process Supervisor, a different URL can be used:
http://example.com/sys@#SYS_SYS/@#SYS_LANG/@#SYS_SKIN/cases/open?APP_UID=@#APPLICATION&DEL_INDEX=@#INDEX&to_revise=true&action=to_revise

If the case is completed, paused or canceled, or the user doesn't have rights to open the case, then the summary for the case will be displayed. The summary can also be displayed by setting action=sent; it is not necessary to include the delegation index number in the URL:
http://example.com/sys@#SYS_SYS/@#SYS_LANG/@#SYS_SKIN/cases/open?APP_UID=@#APPLICATION&action=sent

If the user doesn't currently have an active login session in ProcessMaker, the web browser will first redirect to the login page and then redirect to the specified case after logging in. If the case is opened in a task that has already been completed, then the web browser will redirect to the list of cases in the Inbox.

Redirecting to the ../cases/main Page

Unfortunately, the page "cases/open?..." is designed to open a case inside an <iframe> below the main menu bar, so redirecting the web browser to this address will open a window that doesn't have the main menu bar and the Home sidebar. To be able to get back to the principal page after completing the task, it is recommended to add the following trigger to the process to redirect the web browser back to the "../cases/main" page:

echo "<script>top.location.href = '../cases/main';</script>";

Set the above trigger to execute after routing in the task specified by the "cases/open?..." page. When the user completes working on the task and clicks on the continue button at the end of the task, the web browser will automatically be redirected to the "../cases/main" page, which displays the top-level menu, the Home sidebar and the list of cases in the Inbox.

If the user needs to immediately return to the "../cases/main" page, a button can be added to a Dynaform that redirects to that page when clicked.

For example, if a button is added with the ID "goToInbox", then the following JavaScript code can be added to the Dynaform to save the contents of the Dynaform and redirect the web browser:

$("#goToInbox").click( function() {
   $("form").saveForm();
   top.location.href = "../cases/main";
});

Grids in Templates

The email template can also contain grid data. For example, the grid can be placed inside an HTML table:

Dear @#reqUserName, Your leave request has been approved. Please find details below:
Date FromDate ToNumber DaysComment
@#detDateFrom@#detDateTo@#detNoDays@#detComment
Once your leave period has ended, please do not forget to fill out a Leave Report upon returning.
Regards,   @#reqSupervisor

Its HTML code would be:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
</head>
<body>
Dear @#reqUserName, <br>
Your leave request has been approved.  Please find details below: <br>
<table>
<tr><th>Date From</th><th>Date To</th><th>Number Days</th><th>Comment</th></tr>
<!-- @>reqLeaveGrid -->
<tr><td>@#detDateFrom</td><td>@#detDateTo</td><td>@#detNoDays</td><td>@#detComment</td></tr>
<!-- @<reqLeaveGrid -->
</table>
<p>Once your leave period has ended, please do not forget to fill out a Leave Report upon returning. <br><br>
Regards, <br>
 &nbsp;  @#reqSupervisor</p>
</body>
</html>

For each row in the grid between @>reqLeaveGrid and @<reqLeaveGrid, the grid fields @#detDateFrom, @#detDateTo, @#detNoDays, and @#detComment will be repeated on a new line. For more information on inserting grids in templates, see Grids in Output Documents.

Moreover, it is possible to introduce images inside the template by editing the HTML code. For example:

<img src="http://example.com/companyLogo.jpg">

Images inserted in email templates should be hosted in a server with public access, otherwise they might not be viewable by the person receiving the email. For example, the corporate logo placed in the location INSTALL-DIRECTORY/workflow/public_html/companyLogo.jpg on the ProcessMaker server is publicly accessible at the address: http://example.com/companyLogo.jpg

Sending Emails with PMFSendMessage()

The PMFSendMessage()function is used to send out customized email notifications based on a template file. To use this function, create a Trigger and add this function to the code for that trigger. For more information and code examples, see the documentation for the PMFSendMessage() function. Also see the code examples below.

To see which users are assigned to cases, tasks, groups, departments, roles, etc., it is often necessary to look up information in the database using the executeQuery() function. Then, the email address of those users can be found with the userInfo() function. Emails can be sent to multiple recipients with the PMFSendMessage() function by separating the email addresses with commas (,) in the $to, $cc or $bcc parameters.

Assigning the Trigger to Step(s)

Once you have uploaded your template email file and defined a trigger to send the email, it is possible to assign the related trigger to steps in different instances:

  • before/after a step (Dynaform, Input Document or Output Document) is displayed
  • before the case is assigned a user for the next task in the case
  • before/after a case is routed (derivated) to the next task in the case

In each case, it is also possible to define conditions that dictate whether a trigger should be executed or not. If the condition evaluates to false, the trigger will not be fired. If it evaluates to true, the trigger will be fired.

For example, the following condition defines that the trigger will be executed only if the @@repFinalDec case variable is 0. In other words, the notification will be sent only when this condition is true.

Trigger Message Examples

Emailing the Current Assigned User for a Case

A message can be sent to the user currently assigned to work on the case by using the @@USER_LOGGED system variable to get that user's unique ID. Then, pass that unique ID to the userInfo() function to look up his/her email address. For example:

$aUser = userInfo(@@USER_LOGGED);
$to = $aUser['mail'];
PMFSendMessage(@@APPLICATION, 'boss@example.com', $to, '', '', 'Some Message Title', 'someTemplate.html');

Emailing the Supervisor of a Case's Assigned User

To send a message to the supervisor of the user currently assigned to a case, first use the InternalClasses::loadCase() to look up who is currently assigned to work on the case and then use the Users::Load() method to get that user's supervisor. Finally, use userInfo() to get the supervisor's email.

For example, to email the supervisor of the user assigned to the current case when the case is overdue:

G::LoadClass("users");
$c = new Cases();
$aCase = $c->loadCase(@@APPLICATION, @%INDEX);
$u = new Users();
$aUser = $u->Load($aCase['CURRENT_USER_UID']);
if (!empty($aUser['USR_REPORTS_TO'])) {
    $aSupervisor = userInfo($aUser['USR_REPORTS_TO']);
    PMFSendMessage(@@APPLICATION, 'admin@example.com', $aSupervisor['mail'], $aUser['USR_EMAIL'],
        '', 'Case is Overdue', 'overdueTemplate.html');
}
else {
    @@ERROR = "There is no supervisor for user {$aCase['CURRENT_USER']}.";
   $g = new G();
   $g->SendMessageText(@@ERROR, "ERROR");
}

Emailing the Previous User in a Case

To send a message to a user who worked on a previous task in a case, create a trigger that saves the user's unique ID to a case variable, and set it to fire in the previous task.

For example, in a process to approve purchase requests, an email message needs to be sent to the purchase requester, informing them whether the purchase was approved or disapproved. In the first task when the requester fills out the purchase request form, fire the following trigger:

@@requesterId = @@USER_LOGGED;

In the subsequent task, when the manager decides to approve or disapprove the purchase request, fire the following trigger to send an email to the requester:

//check if the case variable has been set and is not empty
if (isset(@@requesterId) and !empty(@@requesterId)) {
   $aUserTo = userInfo(@@requesterId);
   $aUserFrom = userInfo(@@USER_LOGGED);
   PMFSendMessage(@@APPLICATION, $aUserFrom['mail'], $aUserTo['mail], '', '', 'Purchase Request Decision',
      '
purchaseDecision.html');
}

Emailing the Previous User with a Database Query

Another way to find the user who worked on a previous task in a case is to look up the record for that task in the wf_<WORKSPACE>.APP_DELEGATION table. There is a record for each task in a case with the last user to work on that task. First, look up the unique ID for the task with the taskList() web service at ADMIN > Settings > Web Services Test (or look it up in the wf_<WORKSPACE>.TASK.TAS_UID field in the database). Then, use executeQuery() in a trigger to look up the user who worked on a particular task for the case in the wf_<WORKSPACE>.APP_DELEGATION.USR_UID field.

For example, to send a message to a user who worked on a task with the ID "7710617204e67abaabfb1c9082177702" in the current case:

$taskId = "7710617204e67abaabfb1c9082177702";
$caseId = @@APPLICATION;
$query = "SELECT USR_UID FROM APP_DELEGATION WHERE APP_UID='$caseId' AND TAS_UID='$taskId'";
$tasks = executeQuery($query);
if (is_array($tasks) and count($tasks) > 0) {
   //get the last record, in case the task was repeated in the case
   $userId = $tasks[count($tasks)]['USR_UID'];
   $aUser = userInfo($userId);
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $aUser['mail'], '', '', 'Some Message Title', 'someTemplate.html');
}

Emailing the Next Assigned User

An email can be sent out to the user assigned to work on the next task in two ways:

  1. Using the PMFGetNextAssignedUser() function for tasks with Cyclical Assignment.
  2. Looking up the next user in the APP_DELEGATION table after routing of the previous task.

The second way is more reliable and works with any type of assignment rule.

For Next Tasks with Cyclical Assignment

If the next task uses cyclical assignment, the next assigned user in a case can be looked up using the PMFGetNextAssignedUser() function. The parameters of this function require the unique IDs for the case and the task, which can be looked up with taskList() at ADMIN > Settings > Web Services Test or by querying the wf_<WORKFLOW>.TASK.TAS_UID field in the database.

For example, the following trigger sends an email message to the next user who will be assigned to work on the current case.

$taskId = 'XXXXXXXXXXXXXXXXXXXXXXXX'; //set to the unique ID for next task
$aUser = PMFGetNextAssignedUser(@@APPLICATION, $taskId);
if (is_array($aUser) and count($aUser) > 0) {
 PMFSendMessage(@@APPLICATION, "Mr. Boss <boss@example.com>", $aUser['USR_EMAIL'], '', '',
   'You are assigned to next task', 'template.html');
}
else {
   $g = new G();
   $g->SendMessageText("Unable to lookup next assigned user!", "ERROR");
}

Remember that the PMFGetNextAssignedUser() function only works if the next task uses cyclical assignment. If the next task uses any other type of assignment rule, it is necessary to use the following method.

For Next Tasks with Any Type of Assignment Rule

The assigned user for the next task can be looked up in the wf_<WORKSPACE>.APP_DELEGATION.USR_UID field in the database with a trigger that fires after routing from the previous task. At that point, the next task has already been created in the database, although still in the previous task of the case. This method works for tasks with any type of assignment rule.

For example, the following trigger sends an email message to the next user who will be assigned to work on the current case.

//ID of next task which can be found in the @@TASK variable in the next task in the debugger:
$nextTaskId = '67156450657e5b7bc47c393009386672';
$caseId = @@APPLICATION;
//lookup the user assigned to the next task in the case
$query = "SELECT USR_UID FROM APP_DELEGATION WHERE APP_UID='$caseId' AND
    DEL_INDEX=( SELECT MAX(DEL_INDEX) FROM APP_DELEGATION WHERE APP_UID='$caseId'
    AND TASK_UID='$nextTaskId' )"
;
$result = executeQuery($query) or
   die("Error in query: $query");
$aUser = userInfo($result[1]['USR_UID']);
$to = $aUser['firstname'] .' '. $aUser['lastname'] .' <'. $aUser['mail'] .'>';
PMFSendMessage(@@APPLICATION, "Mr. Boss <boss@example.com>", $to, '', '',
   'You are assigned to next task', 'template.html');

Emailing the Next Assigned Users of Parallel Tasks

The previous code example will have problems if the next tasks are parallel tasks, because their index numbers might not be the maximum index number. In that case, search for particular task IDs in the wf_<WORKSPACE>.APP_DELEGATION.TAS_UID field in the database. Task IDs can be found with taskList() at ADMIN > Settings > Web Services Test or by querying the wf_<WORKFLOW>.TASK.TAS_UID field in the database.

For example, the following trigger code set to fire after routing from the previous task will look up the next tasks in the process, which are three parallel tasks with the unique IDs "8494848774f28459638eb76005941643", "3466222164f2951faaf2915011308833" and "2935650394f297698b78467062625755":

$caseId = @@APPLICATION; //lookup the user assigned to the next task in the case
$query = "SELECT USR_UID FROM APP_DELEGATION WHERE APP_UID='$caseId' AND DEL_THREAD_STATUS='OPEN' AND
   (TAS_UID='8494848774f28459638eb76005941643' OR '3466222164f2951faaf2915011308833'
   OR '2935650394f297698b78467062625755')"
;
$aUsers = executeQuery($query) or die("Error executing query: \n$query");
if (is_array($aUsers) and count($aUsers) > 0) {
   $to = '';
   foreach ($aUsers as $aUser) {
      $aInfo = userInfo($aUser['USR_UID']);
      $to .= ($to == '' ? '' : ', ') . $aInfo['mail'];
   }
   PMFSendMessage(@@APPLICATION, "Mr. Boss <boss@example.com>", $to, '', '',
      'You are assigned to the next tasks', 'template.html');
}

Emailing all Users Assigned to a Task

Sending out an email to all users in the assignment pool for a specified task can be useful, especially for self-service tasks where a user is not automatically assigned to a task, so all the available users in the assignment pool are informed that a new case is available.

To send an email to all assigned users for a specified task, first look up the unique ID for the task either by using the taskList() web service test or by querying the database:

 SELECT CON_ID FROM CONTENT WHERE CON_CATEGORY='TAS_TITLE'

With the unique ID for the task, look up all the users assigned to that task in the wf_<WORKSPACE>.TASK_USER table. If a group is assigned to the task, then also look up all the members of that group in the wf_<WORKSPACE>.GROUP_USER table.

In this example, an email is sent to all users assigned to the "Review Proposal" task, which has a unique ID of "2180652364e08ac6275dbb7037406882":

$taskId = "2180652364e08ac6275dbb7037406882"; //change to unique ID for the task
$assignedUsers = array(); //empty array to hold the UIDs of the assigned users to the task
$userQuery = "SELECT USR_UID FROM TASK_USER WHERE TAS_UID = '$taskId' AND TU_RELATION = 1";
$groupQuery = "SELECT GU.USR_UID FROM GROUP_USER GU, TASK_USER TU WHERE
   TU.TAS_UID = '$taskId' AND TU.TU_RELATION = 2 AND TU.USR_UID = GU.GRP_UID"
;
$users = executeQuery($userQuery);
if (is_array($users) and count($users) > 0) {
   foreach ($users as $user)
      $assignedUsers[] = $user['USR_UID'];
}
$users = executeQuery($groupQuery);
if (is_array($users) and count($users) > 0) {
   foreach ($users as $user)
      $assignedUsers[] = $user['USR_UID'];
}
 
$assignedUsers = array_unique($assignedUsers); //eliminate any duplicates in array
$emailTo = "";  
foreach ($assignedUsers as $assignedUser) {
   $aUser = userInfo($assignedUser);
   $emailTo .= (empty($emailTo) ? "" : "," ) . $aUser['mail'];
}
if (!empty($emailTo)) {
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $emailTo, '', '',
      "New self-service case to be claimed", 'unassignedCase.html');
}

Emailing All Assigned Users to the Next Task(s)

Like the previous example, an email can be sent out to all the users in the assignment pool for the next task(s) in the process. Unlike the previous example, the unique ID of the task(s) does not need to be known, since it is automatically looked up in the ROUTE table, based on the current task stored in the @@TASK system variable.

$taskId = @@TASK; //current task
//lookup next task(s), if the current task isn't a final task
$tasks = executeQuery("SELECT ROU_NEXT_TASK FROM ROUTE WHERE TAS_UID='$taskId' AND ROU_NEXT_TASK<>'-1'");
$taskList = ''; //build list of next task(s)
foreach ($tasks as $task) {
   $taskList .= (empty($taskList) ? '' : ', ') . "'" . $task['ROU_NEXT_TASK'] . "'";
}
 
$assignedUsers = array(); //empty array to hold the UIDs of the assigned users to the task
$userQuery = "SELECT USR_UID FROM TASK_USER WHERE TAS_UID IN ($taskList) AND TU_RELATION = 1";
$groupQuery = "SELECT GU.USR_UID FROM GROUP_USER GU, TASK_USER TU WHERE
   TU.TAS_UID IN ($taskList) AND TU.TU_RELATION = 2 AND TU.USR_UID = GU.GRP_UID"
;
 
$users = executeQuery($userQuery);
if (is_array($users) and count($users) > 0) {
   foreach ($users as $user)
      $assignedUsers[] = $user['USR_UID'];
}
 
$users = executeQuery($groupQuery);
if (is_array($users) and count($users) > 0) {
   foreach ($users as $user)
      $assignedUsers[] = $user['USR_UID'];
}
 
$assignedUsers = array_unique($assignedUsers); //eliminate any duplicates in array
$emailTo = "";  
foreach ($assignedUsers as $assignedUser) {
   $aUser = userInfo($assignedUser);
   $emailTo .= (empty($emailTo) ? "" : "," ) . $aUser['mail'];
}
if (!empty($emailTo)) {
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $emailTo, '', '',
      "New self-service case to be claimed", 'unassignedCase.html');
}

Emailing all Participants in a Case

An email can be sent out to all the users who have participated in a specified case to keep them apprised of the progress of that case.

To send an email to all users who have participated in a case, first look up the unique ID for the case in one of the following ways:

  1. Use the @@APPLICATION system variable for the current case.
  2. Look up the case with the caseList() web service.
  3. Look up the case in the wf_<WORKSPACE>.APPLICATION.APP_UID or wf_<WORKSPACE>.APP_DELEGATION.APP_UID field with an SQL query.

With the unique ID for the case, look up all the users who have been assigned to the case in the wf_<WORKSPACE>.APP_DELEGATION.USR_UID field and add them to the list of email recipients.

In this example, an email is sent to all users who have participated in the current case:

$caseId = @@APPLICATION; //UID for current case
$users = executeQuery("SELECT DISTINCT USR_UID FROM APP_DELEGATION WHERE APP_UID = '$caseId'");
if (is_array($users) and count($users) > 0) {
   $emailTo;    //empty string to hold the emails of the participants in case
   foreach ($users as $user) {
      $aUser = userInfo($user['USR_UID']);
      $emailTo .= (empty($emailTo) ? "" : "," ) . $aUser['mail'];
   }
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $emailTo, '', '',
      "Update on Case Progress", 'caseStatus.html');
}

In this example, an email is sent to all users who have participated in the current case and all master process or subprocess cases associated with the current case:

$caseId = @@APPLICATION; //UID for current case
$query = "SELECT DISTINCT USR_UID FROM APP_DELEGATION WHERE APP_UID =
   (SELECT APP_UID FROM SUB_APPLICATION WHERE APP_UID = '$caseId' OR APP_PARENT = '$caseId')"
;
$users = executeQuery($query);
if (is_array($users) and count($users) > 0) {
   $emailTo; //empty string to hold the emails of the participants in case
   foreach ($users as $user) {
      $aUser = userInfo($user['USR_UID']);
      $emailTo .= (empty($emailTo) ? "" : "," ) . $aUser['mail'];
   }
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $emailTo, '', '',
      "Update on Case Progress", 'caseStatus.html');
}

Emailing Members of a Group

In this example, the members of a group are looked up in the ProcessMaker database and an email is sent to each member of a group named "employees".

$groupName = 'employees';  //change to name of group
$query = "SELECT DISTINCT GU.USR_UID FROM CONTENT AS C, GROUP_USER AS GU WHERE " .
   "C.CON_CATEGORY='GRP_TITLE' AND C.CON_VALUE='$groupName' AND C.CON_ID=GU.GRP_UID";
$result = executeQuery($query);
if (!is_array($result) or count($result) < 1) {
   $g = new G();
   $g->SendMessageText("Unable to find any users in group '$groupName'.", "WARNING");
}
else {
   $to = '';
   foreach ($result as $record) {
      $aInfo = userInfo($record['USR_UID']);
      if (empty($to))
         $to = $aInfo['mail'];
      else
         $to .= ', ' . $aInfo['mail'];
   }
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $to, '', '',
      "Work for $dptName", 'positiveExpense.html');
}

Emailing Members of a Department

Sending an email to all members of a department is very similar to sending an email to members of a group, but query the USERS.DEP_UID field.

In this example, the members of department named "Sales" are looked up in the ProcessMaker database and an email is sent to all members:

$dptName = 'Sales';  //change to name of department
$query = "SELECT DISTINCT U.USR_UID FROM USERS AS U, CONTENT AS C WHERE " .
   "C.CON_CATEGORY='DEPO_TITLE' AND C.CON_VALUE='$dptName' AND C.CON_ID=U.DEP_UID";
$result = executeQuery($query);
if (!is_array($result) or count($result) < 1) {
   $g = new G();
   $g->SendMessageText("Unable to find any users in department '$dptName'.", "WARNING");
}
else {
   $to = '';
   foreach ($result as $record) {
      $aInfo = userInfo($record['USR_UID']);
      if (empty($to))
         $to = $aInfo['mail'];
      else
         $to .= ', ' . $aInfo['mail'];
   }
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $to, '', '',
      "Work for $dptName", 'positiveExpense.html');
}

Emailing Users with a Role

Sending an email to all users with a specified role requires first looking up the unique ID for the role in the rb_<WORKSPACE>.ROLES table and then querying the wf_<WORKSPACE>.USERS.USR_ROLE field for that unique ID.

In this example, the users with the "PROCESSMAKER_MANAGER" role are looked up in the ProcessMaker database and an email is sent to all those users:

$roleCode = 'PROCESSMAKER_MANAGER';  //change to code for role
$roleQuery = executeQuery("SELECT ROL_UID FROM ROLES WHERE ROL_CODE='$roleCode'", 'rbac');
$roleUid = $roleQuery[1]['ROL_UID'];
$result = executeQuery("SELECT USR_UID FROM USERS WHERE USR_ROLE='$roleUid'");
if (!is_array($result) or count($result) < 1) {
   $g = new G();
   $g->SendMessageText("Unable to find any users with role '$roleCode'.", "WARNING");
}
else {
   $to = '';
   foreach ($result as $record) {
      $aInfo = userInfo($record['USR_UID']);
      if (empty($to))
         $to = $aInfo['mail'];
      else
         $to .= ', ' . $aInfo['mail'];
   }
   PMFSendMessage(@@APPLICATION, 'boss@example.com', $to, '', '',
      "Meeting for all managers next Friday", 'managersMeeting.html');
}

Emailing when Cases are Canceled/Paused/Reassigned

ProcessMaker does not provide a way to fire a trigger when these actions occur in a case. The only way to get around this problem is to add code directly to the functions Cases::deleteCase, Cases::cancelCase(), Cases::pauseCase, Cases::unpauseCase() or Cases::reassignCase(), which are defined in the file workflow/engine/classes/class.case.php.

For example, to send an email notification to the next user when a case is reassigned to them, the following code should be added to the end of the Cases::reassignCase() function:

G::LoadClass("pmFunctions");
$aUser = userInfo($newUserUID);
PMFSendMessage($sApplicationUID, "admin@example.com", $aUser['mail'], '', '',
   "Assigned to the case!", "someTemplate.html");

Debugging Email Notifications

Email notifications can fail for a number of reasons. If emails aren't being received, it is recommended to check the following issues in order to figure out what is causing the problem.

First, check the configuration to connect to the email server and make sure that the email server is functioning by pinging it. Also make sure that the ProcessMaker server is configured to periodically execute cron.php, so the emails will get sent.

Check the PMFSendMessage() Return Value

If the email was sent out by PMFSendMessage() in a trigger, then check the return value. If 0, then there is probably a problem in the parameters for the function. Perhaps one of the email addresses is not recognized as an email address. Perhaps the name of the template file was misspelled. Remember that template names are case sensitive.

Assign the return value of the PMFSendMessage() function to a case variable and run a case with the debugger turned on to see the return value.

@@ret = PMFSendMessage(...);

Check the APP_MESSAGE table

Check whether a record has been written to the wf_<WORKSPACE>.APP_MESSAGE table in the database. (To avoid logging in MySQL from the command line, phpMyAdmin can be used to view the database from a web browser.)

Every email message to be sent out will be stored in the wf_<WORKSPACE>.APP_MESSAGE table in the database. When the record is first written to the database, the APP_MSG_SENT field will be set to the current datetime. (Note that the APP_MSG_SENT field doesn't indicate the time when the message was sent to the email server.) When the email message is sent to the email server by the cron.php script, the APP_MSG_STATUS field will change from "pending" to "sent".

Check the Output of cron.php

When the cron.php script is executed, it sends every message in the wf_<WORKSPACE>.APP_MESSAGE table whose status is "pending" to the email server. cron.php keeps a log of its activities. If emails were sent out, a record should be written in the shared/log/cron.log file. If an error occurred while trying to send out emails, a record should be written to the shared/log/cronError.log file.

If the log files don't indicate anything, execute cron.php manually from the command line and check the output.

Log Module to Manage Notifications

The Log module displays information about all mail sent inside a process. This feature is optimized by emulating APP_MESSAGE inside this log, allowing the emails to be searched according to different search parameters added. Basically, the following notifications will be stored inside the email log:

When sending emails using the PMFSendMessage() function, notice that it is possible to add a parameter into this function that will decide wether or not the message will be displayed in the log list.

Only users with PROCESSMAKER_ADMIN and PROCESSMAKER_MANAGER role will have access to the email log.

When emails are sent, their registry is stored at ADMIN > Settings > Logs > Emails

Email Log Options

Once an email has been sent, it will be stored in APP_MESSAGE and displayed in the log list with the following description:

  • #: Displays the number of the case where the email was sent.
  • Case: Displays the name of the case where the email was sent.
  • Process: Name of the process where the email was sent.
  • Task: Name of the task where the email was configured to be sent.
  • Type: Displays the type of notification. There are two types of notification: Trigger if the email was sent using a trigger (the PMFSendMessage() function, for example), and Routing if the email was sent using a Task Notification or a Case Note.
  • Date: Date when the email was sent.
  • Subject: The subject (title) of the email.
  • From: The email address of the person who sent out the email.
  • To: The email address to whom the email was sent.
  • Status: Displays the status of the message; if the email was sent its status will be Sent, otherwise it will be Pending. This status can be changed in case a lot of mail is queued and wasn't sent correctly. If the status is changed, it will be also changed on APP_MESSAGE table.

Below each email description, a preview of the message body is displayed, click on the icon to expand the information and to contract it.

In the above example, the email was sent by adding a case note.

If the template is customized with styles, font size, color, etc. the format will be displayed in the preview. In the example below, an event was executed and its template was created using a particular style:

Searching Emails

One of the advantages of the email log is the ability to search an email depending on a selected criteria. The search criteria is:

  • Process: Search by process name or by all processes created in the current workspace.
  • Status: Search by status: pending, sent or both.
  • Delegate Date From: To: Search by the date on which the email was sent.