Sending Emails

Introduction to Sending Emails

The capability of receiving and sending emails is a core feature of ConSol CM. Please read the detailed introduction in the ConSol CM Administrator Manual for information.

In this section we will describe how you can write scripts to send emails from the workflow. This is very useful for use cases like the following:

Usually, you do not write the text of the email into the script but you work with email templates. So please read the detailed introduction to the ConSol CM Text Template Manager in the ConSol CM Administrator Manual first.

Important Methods

There are different ways of sending emails from ConSol CM workflows. The following list provides an overview of the classes and methods which can be applied and discusses the advantages and disadvantages of each variant. However, please see for yourself, which variant will cover your specific use case the best way.

Work with the ConSol CM API documentation in order to gain an overview of all methods which are provided by the respective classes!

Variant 1: Use an Object of Class Mail

Here you can define all required parameters for an email (see Example #1 up to Example #3 in the Examples section).

Advantages:

Disadvantages:

Information: 

Variant 2: Work with the workflowApi (Singleton of Class WorkflowContextService)

The object workflowAPI provides the method sendEmail() with several different signatures. All those methods return void.

Figure 151: Methods sendEmail() in workflowApi (WorkflowContextServcice)

Advantages:

Disadvantages:

Information:

We recommend to use the rather new Mail object instead of working with workflowApi for sending emails unless you have a very special reason to use workflowApi.

Variant 3: Use the mailService (Singleton of Class MailService)

You can also work with the mailService to send emails from a workflow (or an Admin Tool script which is called by a workflow script).

The following methods are available, they all return void.

Figure 152: Methods of the class MailService, they all return void

Advantages:

Disadvantages:

Examples

Example #1: Sending an Automatic Acknowledgment of Receipt to the Customer Who Has Opened a Ticket

This script might be placed in one of the first activities of the workflow.

// create new mail object

def mail = new Mail()

 

// fetch main contact of the ticket

def maincontact = ticket.getMainContact()

 

// fetch e-mail address of the main contact. The Data Object Group Field has to be addressed using Data Object Group name:Data Object Group Field name

def toaddress = maincontact.get("MyCustomerDataObjectGroup:email")

 

// put the e-mail TO address into the Mail object

mail.setTo(toaddress)

 

// fetch the REPLY TO address, this is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

 

// put the e-mail REPLY TO address into the Mail object

mail.setReplyTo(replyaddress)

 

// build e-mail text using a template which is stored in the Template Designer

def text = workflowApi.renderTemplate("Acknowledgement_of_receipt")

 

// put the e-mail text into the Mail object

mail.setText(text)

 

// create the subject of the e-mail, the ticket number with the correct Regular Expression has to be set for correct recognition of incoming e-mails for the ticket

def ticketname = ticket.getName()

def subject = "Your case has been registered as Ticket (" + ticketname + ")"

 

// put the subject into the Mail object

mail.setSubject(subject)

 

// send out the e-mail

mail.send()

Code example 57: Sending an automatic acknowledgment of receipt to the customer who has opened a ticket, using a Mail object

Example #2: Sending an Email to the Engineer When a Certain Escalation Level Has Been Reached

This script might be placed in an automatic activity which is connected to a time trigger. The time trigger measures the escalation interval. When the deadline has been reached, the trigger fires and the ticket enters the automatic activity.

// create new mail object

def mail = new Mail()

 

// fetch current engineer of the ticket and set it as e-mail receiver

if (ticket.engineer){

mail.setTargetEngineer(ticket.engineer)

 

// fetch the REPLY TO address, this is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

 

// put the e-mail REPLY TO address into the Mail object

mail.setReplyTo(replyaddress)

 

// build e-mail text using a template which is stored in the Template Designer

def text = workflowApi.renderTemplate("ESCALATION_Mail")

 

// put the e-mail text into the Mail object

mail.setText(text)

 

// create the subject of the e-mail, the ticket number with the correct Regular Expression has to be set for correct recognition of incoming e-mails for the ticket

def ticketname = ticket.getName()

def subject = "ESCALATION Level 3 REACHED! Ticket (" + ticket.getId() + ")"

 

// put the subject into the Mail object

mail.setSubject(subject)

 

// send out the e-mail

mail.send()

}

Code example 58: Sending an email to the engineer when a certain escalation level has been reached, using a Mail object

Example #3: Sending an Email to a Customer Integrating the Queue-Specific Mail Script

This is the same script as shown in the example above, but the queue-specific mail script will be used. For a detailed explanation of this type of script, refer to the ConSol CM Administrator Manual, section Admin Tool Scripts.

As an effect, the outgoing email will pass through the script before it leaves the CM system. Email parameters, like Cc, Bcc, or Reply To can be changed.

// create new mail object

def mail = new Mail()

 

// fetch main contact of the ticket

def maincontact = ticket.getMainContact()

 

// fetch e-mail address of the main contact. The Data Object Group Field has

// to be addressed using Data Object Group name:Data Object Group Field name

def toaddress = maincontact.get("MyCustomerDataObjectGroup:email")

 

// put the e-mail TO address into the Mail object

mail.setTo(toaddress)

 

// fetch the REPLY TO address, this is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

 

// put the e-mail REPLY TO address into the Mail object

mail.setReplyTo(replyaddress)

 

// build e-mail text using a template which is stored in the Template Designer

def text = workflowApi.renderTemplate("Acknowledgement_of_receipt")

 

// put the e-mail text into the Mail object

mail.setText(text)

 

// create the subject of the e-mail, the ticket number with the correct Regular Expression

// has to be set for correct recognition of incoming e-mails for the ticket

def ticketname = ticket.getName()

def subject = "Your case has been registered as Ticket (" + ticketname + ")"

 

// put the subject into the Mail object

mail.setSubject(subject)

 

// Mail should use the e-mail script which is configured for the queue

mail.useDefaultScript()

 

// send out the e-mail

mail.send()

Code example 59: Sending an email to a customer integrating the queue-specific mail script, using a Mail object

Example #4: Sending an Email to All Contacts of the Ticket

This will send one email with all customers (that have an email address) as receiver. Please note that this is a simple example which demonstrates the use of a list. The Reply-To address is not set, so answers to the email would not be appended to the ticket.

def custEmails = workflowApi.getContactList()*.get("email").findAll{it != null}.join(",")

workflowApi.sendEmail(custEmails, "Confirmation", "Good afternoon, we received your request!", null, null)

Code example 60: Sending an email to all contacts of the ticket

Example #5: Sending an Email to Each Contact in a List of All Contacts of the Ticket

This will send one email to every single customer (that has an email address). Please note that this is a simple example which demonstrates the use of a list. The Reply-To address is not set, so answers to the email would not be appended to the ticket.

workflowApi.getContactList().each {

def custEmail = it.get("email")

if (custEmail){

workflowApi.sendEmail(custEmail, "Confirmation",

"Good afternoon, we received your request!", null, null)

}

}

Example #6: Sending an Email and Inserting it into the Ticket History

The following code shows a script which is called to send a receipt notice to the customer when a tickets for this customer was opened. If the main customer of the ticket is a company, no email is sent, because in the example system, companies do not have email addresses. In the next step, the correct customer field which contains the email address has to be found. The field name can vary between customer groups (with the respective customer model), so this has to be considered. When the email has been sent, this is documented as ticket history entry with the correct entry type.

import com.consol.cmas.common.model.mail.Mail

import com.consol.cmas.common.model.content.MailEntryStatus;

import com.consol.cmas.common.model.content.AttachmentEntry;

import com.consol.cmas.common.model.content.ContentFile;

import com.consol.cmas.common.model.content.ContentEntryCategory

import com.consol.cmas.common.model.content.MailEntry;

import com.consol.cmas.common.util.MailHeadersUtil;

import com.consol.cmas.core.server.service.*;

 

// create new mail object

def mail = new Mail()

def ticket = workflowApi.getTicket()

 

// fetch main contatc of the ticket

def maincontact = ticket.getMainContact()

def unit_type = maincontact.definition.type.toString()

 

if(unit_type.equals('COMPANY')) {

println 'No email address for company; no receipt notice sent.'

return

} else if (unit_type.equals('CONTACT')){

 

def toaddress_field

def custgroup = maincontact.customerGroup.name

println 'Customergroup is now ' + custgroup

switch(custgroup) {

case "Reseller": toaddress_field = "email";

break;

case "DirectCustomers": toaddress_field = "dir_cust_email"

break;

case "MyCustomerGroup": toaddress_field = "email"

break;

case "OurPartnerCompanies": toaddress_field = "email"

break;

case "RetailCustomers": toaddress_field = "retail_customer_email"

break;

}

def toaddress = maincontact.get(toaddress_field)

println 'toaddress is now ' + toaddress

if (!toaddress){

println 'No email address found for contact, no receipt notice sent.'

} else {

// put the e-mail TO address into the Mail object

mail.setTo(toaddress)

 

// fetch the REPLY TO address, theis is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

// put the e-mail REPLY TO address into the Mail object

mail.setReplyTo(replyaddress)

 

// build e-mail text using a template which is stored in the Template Designer

def text = workflowApi.renderTemplate("Acknowledgement_of_receipt")

// put the e-mail text into the Mail object

mail.setText(text)

 

// create the subject of the e-mail, the ticket number with the correct Regular Expression

// has to be set for correct recognition of incoming e-mails for the ticket

def ticketname = ticket.getName()

def subject = "Your case has been registered as Ticket (" + ticketname + ")"

// put the subject into the Mail object

mail.setSubject(subject)

// Mail should use the e-mail script which is configured for the queue

mail.useDefaultScript()

// send out the e-mail and register status

def attList = new ArrayList<AttachmentEntry>()

def collection = new HashSet<MailEntry>()

def mailStatus = true;

 

// add attachments to attList .

try {

mail.send();

} catch (Exception e){

mailStatus = false;

}

 

MailEntry mailEntry = new MailEntry(subject,text);

// you can also use an email template -> String text = workflowApi.renderTemplate

mailEntry.setTicket(ticket);

mailEntry.setCategory(ContentEntryCategory.OUTGOING_MAIL);

// or other status -> see com.consol.cmas.common.model.content.ContentEntryCategory in API

mailEntry.setCreationDate(new Date());

mailEntry.setLastModificationDate(new Date());

mailEntry.setMimeType("text/html"); // maybe "text/plain" shows linebreaks if "text/html" doesn't

mailEntry.setEncoding("UTF-8");

mailEntry.setAttribute(MailHeadersUtil.FROM_PROPERTY, replyaddress)

mailEntry.setAttribute(MailHeadersUtil.TO_PROPERTY, toaddress)

mailEntry.setAttribute(MailHeadersUtil.SUBJECT_PROPERTY,subject);

 

if(mailStatus){

mailEntry.setMailEntryStatus(MailEntryStatus.SUCCESS)

} else {

mailEntry.setMailEntryStatus(MailEntryStatus.FAILURE)

}

 

attList?.each { att ->

mailEntry.addAttachment(att)

}

collection.add(mailEntry)

workflowApi.updateTicket(ticket,collection)

} // end if (!toaddress){

} // end of else if (unit_type.equals('COMPANY')){

Code example 61: Admin Tool script for sending a notification of receipt and inserting the email as ticket history entry

Example #7: Working with a Template for the Ticket Name in the Mail Subject

In the previous coding example, the following lines are used: 

def ticketname = ticket.getName()

def subject = "Your case has been registered as Ticket (" + ticketname + ")"

This is because the pattern in the email subject guarantees that an incoming email can be assigned to the correct ticket. This means, if you use the coding style shown in the example above, you have to make sure that the pattern you use matches the pattern which has been configured in the Admin Tool, navigation item Email (compare following figure).

Figure 153: Admin Tool: Pattern and template for the email subject

In order to avoid inconsistencies between workflow code and system configuration (Admin Tool), you can also work with the template name which is implicitly available in CM.

Use the following code in the Admin Tool script: 

import static com.consol.cmas.common.util.TemplateUtil.TICKET_SUBJECT_TEMPLATE_NAME

( ... )

def subject = templateService.merge(TICKET_SUBJECT_TEMPLATE_NAME, [ticketName:ticket.name])

Note that you have to put a parameter called ticketName in the context for the template to work.

Alternative solution: if you modify the template for the outgoing emails to accept either ticketName or the ticket object (you can then work with ticket.name), you can also work with the regular renderTemplate() method as shown below.

The outgoing email subject template is then:

Ticket (<#if ticketName??>${ticketName}<#elseif ticket??>${ticket.name}</#if>)

and the subject is then: 

def subject = workflowApi.renderTemplate(TICKET_SUBJECT_TEMPLATE_NAME)

Example #8: Using the MailService to Send an Email in an Asynchronous Mode

Here, we show an example of sending a single email. However, the code might be used to improve performance if a great number of emails should be sent in a bulk operation. Then you can really benefit from the asynchronous mechanism. The sending of the emails will not block other processes which are triggered in the same script, for example.

import com.consol.cmas.common.model.mail.MailSendHolder

 

def text = workflowApi.renderTemplate("Acknowledgement_of_receipt")

def holder = MailSendHolder.createSelfSendHolder(text, true, null, null)

 

def ticket = workflowApi.ticket

def ticketname = ticket.name

def maincontact = ticket.mainContact

def toaddress_field

def custgroup = maincontact.customerGroup.name

 

 

switch(custgroup) {

case "Reseller":toaddress_group = "ResellerCustomerData";

toaddress_field = "email";

break;

case "DirectCustomers": toaddress_group = "DirCustCustomerData" ;

toaddress_field = "dir_cust_email"

break;

case "MyCustomerGroup": toaddress_group = "customer";

toaddress_field = "email"

break;

case "OurPartnerCompanies": toaddress_group = "PartnersContactData";

toaddress_field = "email"

break;

case "RetailCustomers": toaddress_group = "RetailCustomersContactData";

toaddress_field = "retail_customer_email"

break;

}

 

def toaddressComplete = toaddress_group + ":" + toaddress_field

 

def toaddress = maincontact.get("${toaddressComplete}")

 

if (!toaddress){

log.info 'No email address found for contact, no receipt notice sent.'

} else {

holder.setTo(toaddress)

def subject = "Your case has been registered as Ticket (" + ticketname + ")"

holder.setSubject(subject)

 

// fetch the REPLY TO address, this is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

holder.setFrom(replyaddress)

mailService.sendMailAsynchronous(holder)

log.info 'Acknowledgement of receipt has been sent!'

}

Code example 62: Script for sending an email in an asynchronous mode, please see also alternative code in the following example

log.info 'Customergroup is now ' + custgroup

def sourceGroupMap = [

Reseller: [toaddress_group: "ResellerCustomerData",toaddress_field : "email"],

DirectCustomers: [toaddress_group: "DirCustCustomerData",toaddress_field : "dir_cust_email"],

OurPartnerCompanies: [toaddress_group: "PartnersContactData",toaddress_field : "email"],

RetailCustomers: [toaddress_group: "RetailCustomersContactData",toaddress_field : "retail_customer_email"],

]

def toaddressComplete = sourceGroupMap[custgroup].toaddress_group+":"+sourceGroupMap[custgroup].toaddress_field

def toaddress = maincontact.get("${toaddressComplete}")

Code example 63: Alternative code to switch statement: use a multi-dimensional hashmap for more efficient coding

Writing Emails from Scripts when Engineer Representation Rules Apply

When you write scripts where emails are sent out to engineers and/or customers, you have to take the engineer representation rules into consideration. For detailed explanations of the engineer representation feature, please refer to the ConSol CM Administrator Manual (section Role Administration) and the ConSol CM User Manual (section User Profile).

Important information about representation configurations

Please note that there are two different scenarios for sending emails and that the CM system behavior concerning sending representation mails might differ for the two scenarios!

  1. An engineer writes an email using the Ticket-Email Editor: the representation rule is applied and the representing engineer receives a copy of the email. This means all emails which are sent manually using CM are sent to the original recipient and their current representative. The CM system checks if a representation rule is active for a certain email address! Please keep this in mind when you configure the representation permissions in the Admin Tool and inform your CM users (engineers) about this behavior! It might lead to unwanted effects, especially when persons are registered as engineers and as contacts in the ConSol CM system (e.g. for an internal help desk).
  2. An email is sent automatically from the CM system: it depends on the specific configuration of the CM system which engineers receive a copy of the email, the email is (!) not sent to the representing engineers automatically! It might be implemented that the representing engineer gets a copy, but this is not mandatory. The original email might be sent from a workflow script or from an Admin Tool script (which might also be called from a workflow). It depends on the implementation in this script who receives a copy of the email. Please read the introductory section of Important Methods and the following section for details!

For emails sent out using scripts, the CM system behavior concerning representation rules depends on the method which is used to send the email.

All of the three methods listed here belong to the java Class Mail.

setTo(String pTo)

Mail.setTo(<email of originalReceivingEngineer>)

This method receives a String object as parameter. This is the email address of the recipient. This method will not (!) send a copy of the original email to representing engineers.

setTargetEngineer(Engineer pTargetEngineer)

Mail.setTargetEngineer(<current engineer of the ticket>)

This method receives an Engineer object as parameter and will send the original email to the engineer's email address (if set) and to the representing engineer who is registered as representation for the original email address. Be careful here - please read the info box above!

setTargetEngineers(List<Engineer> pTargetEngineers)

This method receives a list of Engineer objects as parameter and will send the original email to the email address of each engineer in the list (if email address is set) and to the representing engineers for all of the listed engineers' email addresses. Be careful here - please read the info box above!

All three methods are used in the same way, i.e. you have to use only one of them to set the recipient's address in a script which should send an email. Please see the following example which uses the Mail.setTargetEngineer() method.

import com.consol.cmas.common.model.mail.Mail

import com.consol.cmas.core.server.service.*

import static com.consol.cmas.common.util.TemplateUtil.TICKET_SUBJECT_TEMPLATE_NAME

// create new mail object

def mail = new Mail()

def ticket = workflowApi.getTicket()

def eng = ticket.engineer

def toaddress = eng?.email

println 'toaddress is now ' + toaddress

if (!toaddress){

log.info 'No email address found for engineer, no info notice sent.'

} else {

// put the e-mail TO address into the Mail object

// mail.setTo(toaddress)

mail.setTargetEngineer(eng)

// fetch the REPLY TO address, theis is stored in a system property

def replyaddress = configurationService.getValue("cmweb-server-adapter","mail.reply.to")

// put the e-mail REPLY TO address into the Mail object

mail.setReplyTo(replyaddress)

 

// build e-mail text using a template which is stored in the Template Designer

def text = "Hello I am your info ticket"

// put the e-mail text into the Mail object

mail.setText(text)

 

def subject = templateService.merge(TICKET_SUBJECT_TEMPLATE_NAME, [ticketName:ticket.name])

// put the subject into the Mail object

mail.setSubject(subject)

// Mail should use the e-mail script which is configured for the queue

mail.useDefaultScript()

// send out the e-mail and register status

 

try {

mail.send();

} catch (Exception e){

mailStatus = false;

}

}

Code example 64: Workflow or Admin Tool script used to send an email to an engineer, using the representation feature by using the setTargetEngineer() method