Hi,
I am trying to modify my existing Mail Handler script to find the custom field value in Email Body and then update in Jira. Example format is here
Customer Name: Omprakash Thamsetty ( This field is text field )
Severity: 1 Critical ( This field is single selection field)
Description: TEST: Sending this email to create jira ticket via email reader
So how I can read Customer Name, Severity and description information from Body using script and then create the jira ticket with that info?
As of now we are using issueObject.setDescription(body) to set description but now I need to have some email template body as above and then add the values to custom field. How can I achieve this using Mail Handler?
Thanks,
Om
Not really dealing with mail handlers, but assuming we're looking at something similar to this: https://scriptrunner.adaptavist.com/latest/jira/mail-handler.html#_change_issue_status
So I played around the proof of concept a little bit and got to this kind of an idea - and just to point out, I did not deal with the actual handler or anything, just the console.
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.IssueTypeManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.context.IssueContext
import com.atlassian.jira.issue.context.IssueContextImpl
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.customfields.option.Options
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.fields.config.FieldConfig
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.project.Project
import com.atlassian.jira.project.ProjectManager
import com.atlassian.jira.user.ApplicationUser
final String body = """This is a test body
Severity: 1 Critical
Description: sample description
"""
String severityMatcher = "Severity: .*"
String severityMatch = body.find(severityMatcher)
String severityValue = null
if (severityMatch) {
severityValue = severityMatch.substring(severityMatch.indexOf(' '))
}
if (severityValue != null) {
//this is just an example of proof of concept, not really a fully fledged working script
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
CustomField severityField = customFieldManager.getCustomFieldObjectsByName("Severity")?.first() //careful about this if you have more than 1 field with that name
if (severityField != null) {
ProjectManager projectManager = ComponentAccessor.getProjectManager()
IssueTypeManager issueTypeManager = ComponentAccessor.getComponent(IssueTypeManager)
Project project = projectManager.getProjectByCurrentKey("ABC")
IssueType issueType = issueTypeManager.getIssueType("Task")
if (project != null && issueType != null) {
IssueContext issueContext = new IssueContextImpl(project, issueType)
FieldConfig fieldConfig = severityField.getRelevantConfig(issueContext)
OptionsManager optionsManager = ComponentAccessor.getOptionsManager()
Options options = optionsManager.getOptions(fieldConfig)
Option criticalOption = options.findByName(severityValue)
if (criticalOption != null) {
//Now we have the custom field and custom field value, so we can create the issue with it
ApplicationUser mailhandleruser = ComponentAccessor.getUserManager().getUserByName("mailhandler_actor")
IssueService issueService = ComponentAccessor.getIssueService()
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.with {
it.setSummary("abc")
it.setDescription("def")
it.addCustomFieldValue(severityField.getId(), criticalOption.getOptionId().toString())
}
IssueService.CreateValidationResult createValidationResult = issueService.validateCreate(mailhandleruser, issueInputParameters)
if (createValidationResult.isValid())
issueService.create(mailhandleruser, createValidationResult)
}
}
}
}
The question is, you say you want to create a new issue - what is your current approach to it? I think there might be 2 ways to do so. Typically IssueInputParameters is what I use: https://library.adaptavist.com/entity/update-the-value-of-custom-fields-through-the-script-console
So then depending on your approach it should be possible to set the value (given that everything else works). Note that I did not fully test above snippet, it's just what I would start with. You may want to incorporate part of it into your own script.
Another part to improve is the severity matcher. This here looks anywhere in the body. I tried to limit it to '^$' as in start and end of line, but the groovy didn't want to work with it (tried also Pattern and Matcher java classes, no budge). It's definitely possible but just couldn't fix it quickly enough. Then of course you might want to play around the regex, what if there isn't space, is your format always the same, etc., but just a general idea for now.
Just to re-iterate, I don't really do mail handlers, just a quick look around and thinking process what I'd do. Could still be that there is a better approach to all of this.
This script helps me to start working on the severity field. I am asking the sender to have the severity in one line with the format that I mentioned so If that format is not mentioned then I may go ahead and set the default value.. If the format is correct then I will set the severity with the value of the email body.
But this script helps and think about how we can read the mail body and get the field values from it.
Thank you so much for the help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Radek Dostál I tried to put constant value instead of reading from email body. I did the coding little different. It is working but I see the error in incoming mail reader console.
Here is my script and error message.
def project = projectManager.getProjectObjByKey("DFRHD")
IssueType issueType = issueTypeManager.getIssueType("Helpdesk")
def issueServiceobj = ComponentAccessor.getIssueService()
def issueInputParametersobj = issueServiceobj.newIssueInputParameters()
def subject = message.getSubject() as String
def body = MailUtils.getBody(message)
def fromAddr = MailUtils.getSenders(message)
def cfvalue = fromAddr as String
def EmailID = cfvalue?.replaceAll(/^\[([\s\S]*)]$/,'$1')
//Set up for project/users/inbox
UserManager userManager = ComponentAccessor.getUserManager()
//Change lines for the correct email inbox to test
ApplicationUser user = userManager.getUserByName("dfrmoserhelpdesk")
//If the subject line has an issue id, see if it exists
def issueMatcher = /DFRHD-[0-9]*/
def issueResult = subject =~ /$issueMatcher/
def issue = ServiceUtils.findIssueObjectInString(subject)
if (issue) {
return
}
def issueObject = issueFactory.getIssue()
def ContactEmailField = customFieldManager.getCustomFieldObjectsByName("Customer Email").first()
issueObject.setProjectObject(project)
issueObject.setSummary(subject)
issueObject.setDescription(body)
//issueObject.setPriority("Normal")
issueObject.setPriorityId(ComponentAccessor.getConstantsManager().getPriorities().find{it.getName().equals("4 Low")}.getId())
issueObject.setIssueTypeId(project.issueTypes.find { it.name == "Helpdesk" }.id)
issueObject.setReporter(user)
def projectComponentManager = ComponentAccessor.getProjectComponentManager()
def componentA = projectComponentManager.findByComponentNameCaseInSensitive('1st Level Support')
issueObject.setComponent(componentA)
issueObject.setCustomFieldValue(ContactEmailField, EmailID)
issue = messageHandlerContext.createIssue(user, issueObject)
def attachments = MailUtils.getAttachments(message)
attachments.each { MailUtils.Attachment attachment ->
def destination = new File(jiraHome.home, FileService.MAIL_DIR).getCanonicalFile()
def file = FileUtils.getFile(destination, attachment.filename) as File
FileUtils.writeByteArrayToFile(file, attachment.contents)
messageHandlerContext.createAttachment(file, attachment.filename, attachment.contentType, user, issue)
}
def cfConfig = sevFld.getRelevantConfig(issue)
def value = ComponentAccessor.optionsManager.getOptions(cfConfig)?.find {
it.toString() == '4-Low'
}
issue.setCustomFieldValue(sevFld, value)
def reqsrcfld = customFieldManager.getCustomFieldObjectsByName("Request Source Type").first()
def cfreqsrcConfig = reqsrcfld.getRelevantConfig(issue)
def reqsrcvalue = ComponentAccessor.optionsManager.getOptions(cfreqsrcConfig)?.find {
it.toString() == 'Email'
}
issue.setCustomFieldValue(reqsrcfld, reqsrcvalue)
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)
}
Error Message
any help much appreciated.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
On first look based on static type checking, you are trying to set a value on an "Issue" object. You can only do so on a "MutableIssue" object.
Issue is sort of.. say, read-only reference of an issue.
MutableIssue is an editable reference. When the MutableIssue has got all the changes and whatnot, then you can "publish" them via issueManager.updateIssue(...).
The easiest way out of this is to obtain a MutableIssue reference via issueManager.getIssueObject(issue.getId()) or via a cast, e.g. MutableIssue mutableIssue = (MutableIssue) issue; cast should work too I think.
So essentially
def issueObject = issueFactory.getIssue()
is giving you MutableIssue, you are modifying that, no problems, later on you are creating it with
issue = messageHandlerContext.createIssue(user, issueObject)
and this returns an Issue object, not a MutableIssue
So if you want to modify it then you need to get the MutableIssue reference first
mutableIssue = (MutableIssue) issue
and that's where you can set custom field values, and then do an update via issueManager.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Radek Dostál Yes, You are correct. I did issue to mutable issue then the error message gone and script works fine. Thank you so much for your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Radek Dostál I am sorry for asking another question on this thread. But it is related to mail handler only.
I am getting the full name from directory but I need in format of LastName, FirstName but it is giving me Firstname Lastname. Example: Output Omprakash Thamsetty but I need Thamsetty, Omprakash. How can I get this? Do you have any idea?
def custNameField = customFieldManager.getCustomFieldObjectsByName("Customer Name").first()
def dirUsers = userSearchService.findUsersByEmail(EmailID)
if (dirUsers) { //If one exists
def cwdDirUserVal = dirUsers.first().displayName // grab the first one if there are more than one
log.info "fullname" + cwdDirUserVal
//Set Contact Name field here
issueObject.setCustomFieldValue(custNameField, cwdDirUserVal)
} else {
//Do nothing
log.debug "The Director Full Name was not found! ${EmailID}"
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Jira only has "displayName", so there is no first/middle/last to use. If you need to use a different format then you would need to reformat the displayName string you get out of the user.
Something like this "might" work but that largely depends on the names, I'm not sure how many different name formats there are in the world but I've come across some really funky ones in my days. This is though getting more java/groovy topic-ey:
class Scratch {
public static void main(String[] args) {
String displayName = "Jon Doe";
String displayName2 = "Joanna A Doelina";
System.out.println(Scratch.reformatDisplayName(displayName));
System.out.println(Scratch.reformatDisplayName(displayName2));
}
public static String reformatDisplayName(String displayName) {
String[] displayNameSplit = displayName.split(" ");
int length = displayNameSplit.length;
switch (length) {
case 1:
return displayNameSplit[0]; //Just one name in here
case 2:
return displayNameSplit[1] + ", " + displayNameSplit[0]; //Lastname, Firstname
case 3:
return displayNameSplit[2] + " " + displayNameSplit[1] + ", " + displayNameSplit[0]; //Lastname Middlename, Firstname
case 4:
return "please change your name sir/ma'am";
default:
return "if we really get this far, refer to case 4";
}
}
}
//system.out
Doe, Jon
Doelina A, Joanna
Alternatively a more reliable way would be to use whatever directory has the correct name details, such as your AD which is more likely to hold first/last names. Jira doesn't split it in any case so it's never going to be a IOO% accurate way to do it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Can you help me on how to update multi select field based from the email body using scriptrunner email handler?
Vetrical field is multi select field
Email body
inal String body = """This is a test body
Vertical: [ "option1","option2"]
Description: sample description
"""
Appreciate your help on this
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.