We have a Human Resource Jira project with multiple components, one is "New Hire". There is also a custom user field "User Account", once the hiring process is completed someone adds the new hire user id in that field and adds the start date.
We would like to send a custom email with a PDF file about the onboarding to the new hires once the user account field gets completed. At the same time would like to send another email to the Helpdesk to let them know what day new employees join and what technology need for them.
The logic is if the component value is "New Hire", the issue is unresolved and the "User Account" field is not empty then trigger an email to that user who mentioned in the user account field also send a separate email to the helpdesk and include new employee start date
How can trigger an email with a pdf attachment when the user account field gets updated?
Hi @Shah Baloch
You could try using ScriptRunner's Listener and use the Custom Listener option for your requirement.
Below is a sample code for your reference:-
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.user.ApplicationUser
import groovy.xml.MarkupBuilder
import org.apache.commons.io.FileUtils
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
def issue = event.issue
def customFieldManager = ComponentAccessor.customFieldManager
def attachmentManager = ComponentAccessor.attachmentManager
def userPicker = customFieldManager.getCustomFieldObjectsByName('User Account').first()
def userPickerValue = issue.getCustomFieldValue(userPicker) as ApplicationUser
def attachments = attachmentManager.getAttachments(issue)
final def jiraResourcesPath = '/media/ram/Linux_Disk_Space/atlassian/application-data/jira8/data/attachments'
final def project = issue.projectObject
final def projectKey = project.key
final def issueKey = issue.key
final def recipientEmail = userPickerValue.emailAddress
final def destinationPath = '/tmp'
final def subject = 'This is a test mail'
def emailBody = new StringWriter()
def html = new MarkupBuilder(emailBody)
html.html {
body {
h1 'New Employee'
h2 'Sample Content For Testing Purposes'
}
}
def latestAttachment = attachments.findAll {
it.filename.endsWith('.pdf')
}.sort { it.created }.last()
def fileName = latestAttachment.id
def filePath = "${jiraResourcesPath}/${projectKey}/10000/${issueKey}".toString()
def oldFile = new File("${filePath}/${fileName}")
def dest = new File("${destinationPath}/${userPickerValue.displayName}.pdf")
FileUtils.copyFile(oldFile, dest)
creatMessage(recipientEmail, subject, emailBody.toString(), "${dest.canonicalPath}")
FileUtils.forceDelete(dest)
static creatMessage(String to, String subject, String content, String filename) {
def mailServerManager = ComponentAccessor.mailServerManager
def mailServer = mailServerManager.defaultSMTPMailServer
def multipart = new MimeMultipart()
def body = new MimeBodyPart()
def mailAttachment = new MimeBodyPart()
body.setContent(content, 'text/html; charset=utf-8')
mailAttachment.attachFile(new File(filename))
multipart.addBodyPart(body)
multipart.addBodyPart(mailAttachment)
def email = new Email(to)
email.setSubject(subject)
email.setMultipart(multipart)
email.setMimeType("text/html")
def threadClassLoader = Thread.currentThread().contextClassLoader
Thread.currentThread().contextClassLoader = mailServer.class.classLoader
mailServer.send(email)
Thread.currentThread().contextClassLoader = threadClassLoader
}
Please note the working sample code above is not 100% exact to your environment. Hence, you will need to make the required modifications.
Below is a print screen of the Listener configuration:-
If you observe in the print screen, the set event is the Issue Created event. Hence, when the Issue is created and the pdf attachment is added, it will be added to the email and the pdf file is renamed to the recipient's name.
Below is an example email output for your reference:-
I hope this helps to solve your question. :)
Thank you and Kind Regards,
Ram
Thank you @Ram Kumar Aravindakshan _Adaptavist_ I tried your script, but it didn't send an email to the user mentioned in the "User Account" field. I saw an error in the log. Any idea why I'm getting errors?
2022-01-21 09:58:22,339 ERROR [runner.AbstractScriptListener]: ************************************************************************************* 2022-01-21 09:58:22,347 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null java.util.NoSuchElementException: Cannot access last() element from an empty List at Script267.run(Script267.groovy:37)
and
2022-01-21 12:03:40,200 ERROR [runner.AbstractScriptListener]: ************************************************************************************* 2022-01-21 12:03:40,200 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null java.lang.NullPointerException: Cannot get property 'emailAddress' on null object at Script267.run(Script267.groovy:23)
Thank you
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Shah Baloch
As mentioned in my comment:-
Please note the working sample code above is not 100% exact to your environment. Hence, you will need to make the required modifications.
You will need to modify the names of the fields that you are using according to your environment.
The main parameters that you will need to modify are:-
def userPicker = customFieldManager.getCustomFieldObjectsByName('User Account').first()
...
final def jiraResourcesPath = '/media/ram/Linux_Disk_Space/atlassian/application-data/jira8/data/attachments'
...
final def destinationPath = '/tmp'
...
final def subject = 'This is a test mail'
For the user picker, i.e. userPicker, you will need to update the field's name according to your environment.
For the jiraResourcePath, you will need to modify the path according to your environment.
Also, for the destinationPath, you will need to modify the path where you want to copy the file to.
Could you please share a print screen of your Create screen and include the user picker you are using?
If you have not made any changes to the code, the error appears to be coming from this line.
def latestAttachment = attachments.findAll {
it.filename.endsWith('.pdf')
}.sort { it.created }.last()
Could you please check if you have added the attachment to the ticket when you are creating the ticket?
Thank you and Kind Regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Ram Kumar Aravindakshan _Adaptavist_thank you. I forgot to update "JiraResourcePath". I updated the path and it worked.
Is there a way to keep a generic pdf file in the source location and get attached to the email whenever a user gets added in the "User Account" field? I mean attaching files to every issue will cause space issues in the future, also it issues creator can forget to attach the file.
For example, I copy the NewHire.pdf file to the attachment source location, and once the user field gets updated and the file should get attached with the email that sends to a new hire.
Thank you 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 @Shah Baloch
Can you please confirm that you only want to add the pdf file from a fixed location and not include it in the issue's attachment?
If so, you will need to modify the code to:-
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.user.ApplicationUser
import groovy.xml.MarkupBuilder
import org.apache.commons.io.FileUtils
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
def issue = event.issue
def customFieldManager = ComponentAccessor.customFieldManager
def userPicker = customFieldManager.getCustomFieldObjectsByName('User Account').first()
def userPickerValue = issue.getCustomFieldValue(userPicker) as ApplicationUser
final def recipientEmail = userPickerValue.emailAddress
final def destinationPath = '/tmp' // Folder where template is stored
final def originalFileName = 'output.pdf' // Original pdf file name
final def subject = 'This is a test mail'
def emailBody = new StringWriter()
def html = new MarkupBuilder(emailBody)
html.html {
body {
h1 'New Employee'
h2 'Sample Content For Testing Purposes'
}
}
def oldFile = new File("${destinationPath}/${originalFileName}")
def dest = new File("${destinationPath}/${userPickerValue.displayName}.pdf") //File renamed according to name of user from user picker
FileUtils.copyFile(oldFile, dest)
creatMessage(recipientEmail, subject, emailBody.toString(), "${dest.canonicalPath}")
static creatMessage(String to, String subject, String content, String filename) {
def mailServerManager = ComponentAccessor.mailServerManager
def mailServer = mailServerManager.defaultSMTPMailServer
def multipart = new MimeMultipart()
def body = new MimeBodyPart()
def mailAttachment = new MimeBodyPart()
body.setContent(content, 'text/html; charset=utf-8')
mailAttachment.attachFile(new File(filename))
multipart.addBodyPart(body)
multipart.addBodyPart(mailAttachment)
def email = new Email(to)
email.setSubject(subject)
email.setMultipart(multipart)
email.setMimeType("text/html")
def threadClassLoader = Thread.currentThread().contextClassLoader
Thread.currentThread().contextClassLoader = mailServer.class.classLoader
mailServer.send(email)
Thread.currentThread().contextClassLoader = threadClassLoader
}
dest.delete() // delete modified file
You will need to modify the destination path and the original file name.
final def destinationPath = '/tmp' // Folder where pdf is stored
final def originalFileName = 'output.pdf' // Original pdf file name
Now, once the email is sent out, the original file will still be retained in the folder; only the newly modified file, i.e. which is renamed to the receiver's name, will be deleted.
I hope this helps to solve your question. :)
Thank you and Kind Regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Ram Kumar Aravindakshan _Adaptavist_ It worked I can attach the same file all the time just rename it with the user's name. That's what we were looking for.
There is a couple of things we struggling with. We would like to add the user's name in the email body like "Hi XYZ". Also, we would like to include the hiring date. There is the field "Start date". We would like to add both.
I tried something like this but didn't work.
def startDate = customFieldManager.getCustomFieldObjectByName("Start date")
html.html {
body {
h1 'Hi ${userPickerValue.displayName}'
h2 'Welcome to our company, your start date in company is ${startDate.value} '
}
}
How it didn't work, it is displaying the code, but not the value.
How can I add the name and date in the email?
Thank you 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 @Shah Baloch
When you want to append a variable in a String, in Groovy, you will need to use a double quote, i.e. " " instead of a single quote, i.e. ' '.
So, it should be something like this:-
html.html {
body {
h1 "New Employee ${userPickerValue.displayName}"
h2 "Welcome to our company, your start date in company is ${dateFormat.format(startDateValue)}"
}
}
Also, please note the getCustomFieldObjectByName method you have used to invoke the custom field, i.e.
def startDate = customFieldManager.getCustomFieldObjectByName("Start date")
has been deprecated. You should instead use the getCustomFieldObjectsByName method as shown below:-
def startDate = customFieldManager.getCustomFieldObjectsByName("Start Date").first()
Below is the complete updated working sample code for your reference:-
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import com.atlassian.jira.user.ApplicationUser
import groovy.xml.MarkupBuilder
import org.apache.commons.io.FileUtils
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
import java.text.SimpleDateFormat
def issue = event.issue
def customFieldManager = ComponentAccessor.customFieldManager
def userPicker = customFieldManager.getCustomFieldObjectsByName('User Account').first()
def userPickerValue = issue.getCustomFieldValue(userPicker) as ApplicationUser
def startDate = customFieldManager.getCustomFieldObjectsByName("Start Date").first()
def startDateValue = issue.getCustomFieldValue(startDate) as Date
def dateFormat = new SimpleDateFormat('yyyy-MM-dd')
final def recipientEmail = userPickerValue.emailAddress
final def destinationPath = '/tmp' // Folder where template is stored
final def originalFileName = 'output.pdf' // Original Template
final def subject = 'This is a test mail'
def emailBody = new StringWriter()
def html = new MarkupBuilder(emailBody)
html.html {
body {
h1 "New Employee ${userPickerValue.displayName}"
h2 "Welcome to our company, your start date in company is ${dateFormat.format(startDateValue)}"
}
}
def oldFile = new File("${destinationPath}/${originalFileName}")
def dest = new File("${destinationPath}/${userPickerValue.displayName}.pdf") //File renamed according to name of user from user picker
FileUtils.copyFile(oldFile, dest)
creatMessage(recipientEmail, subject, emailBody.toString(), "${dest.canonicalPath}")
static creatMessage(String to, String subject, String content, String filename) {
def mailServerManager = ComponentAccessor.mailServerManager
def mailServer = mailServerManager.defaultSMTPMailServer
def multipart = new MimeMultipart()
def body = new MimeBodyPart()
def mailAttachment = new MimeBodyPart()
body.setContent(content, 'text/html; charset=utf-8')
mailAttachment.attachFile(new File(filename))
multipart.addBodyPart(body)
multipart.addBodyPart(mailAttachment)
def email = new Email(to)
email.setSubject(subject)
email.setMultipart(multipart)
email.setMimeType("text/html")
def threadClassLoader = Thread.currentThread().contextClassLoader
Thread.currentThread().contextClassLoader = mailServer.class.classLoader
mailServer.send(email)
Thread.currentThread().contextClassLoader = threadClassLoader
}
dest.delete() // delete modified file
Please note the working sample code above is not 100% exact to your environment. Hence, you will need to make the required modifications.
I hope this helps to answer your question. :)
Please don't forget to accept the answer as well.
Thank you and Kind regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Ram Kumar Aravindakshan _Adaptavist_ I just found out that the email should go to the user's personal email, not to work, because once they get hire they don't have access to the work email. Is there a way we can send the email to an external user? For example, instead of the "User Account" field, if we use a custom "Email Address" field where a value will be something like "test@gamil.com". I mean any email entered in the "Email Address" field the email should go to that email address. Is it possible to send an email to a user who doesn't have an account in Jira yet?
Also is there a way to change the email body's text into regular text? Currently, the text is bold? I changed h1, h2 to h5 but still, it is making text bold.
I appreciate 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 @Shah Baloch
Sorry for the late reply; I was pretty busy.
I need to confirm with you, now that you want to use a custom email field, is there any need for the user picker field? Will you require it to invoke other user details?
Thank you and Kind Regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Ram Kumar Aravindakshan _Adaptavist_ I was asking if there is a way to use a custom email field instead of a user picker field. The user picker field just picks up a user who has an account with us in Jira, but we are looking to send an email to an external user who doesn't have an account with us. For example, before someone officially joins our company they won't have access to any of the company accounts. We would like to send a pdf attachment to their personal email address, like ram@gamil.com. If that's something is possible.
Thank you 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 @Shah Baloch
Thank you for the clarification.
So in your case, since the User Picker is not applicable, it can be removed from the code.
However, if you intend the PDF file to be named according to the Recipient's name, you will need to use a text field or something.
Also, if you intend to change the text type for the email, you can change it from Heading, i.e. h1, to Paragraph, i.e. p. For more information on the parameters that can be used, please visit this link.
Below is an updated sample code for your reference:-
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.mail.Email
import groovy.xml.MarkupBuilder
import org.apache.commons.io.FileUtils
import javax.mail.internet.MimeBodyPart
import javax.mail.internet.MimeMultipart
import java.text.SimpleDateFormat
def issue = event.issue
def customFieldManager = ComponentAccessor.customFieldManager
def startDate = customFieldManager.getCustomFieldObjectsByName("Start Date").first()
def startDateValue = issue.getCustomFieldValue(startDate) as Date
def dateFormat = new SimpleDateFormat('yyyy-MM-dd')
def newUserName = customFieldManager.getCustomFieldObjectsByName('New User Name').first()
def userUserNameValue = issue.getCustomFieldValue(newUserName) as String
def userEmail = customFieldManager.getCustomFieldObjectsByName('Sample Email').first()
final def recipientEmail = userEmail.getValue(issue).toString()
final def destinationPath = '/tmp' // Folder where template is stored
final def originalFileName = 'output.pdf' // Original Template
final def subject = 'This is a test mail'
def emailBody = new StringWriter()
def html = new MarkupBuilder(emailBody)
html.html {
body {
p "New Employee ${userUserNameValue}"
p "Welcome to our company, your start date in company is ${dateFormat.format(startDateValue)}"
}
}
def oldFile = new File("${destinationPath}/${originalFileName}")
def dest = new File("${destinationPath}/${userUserNameValue}.pdf") //File renamed according to name of user from user picker
FileUtils.copyFile(oldFile, dest)
creatMessage(recipientEmail, subject, emailBody.toString(), "${dest.canonicalPath}")
static creatMessage(String to, String subject, String content, String filename) {
def mailServerManager = ComponentAccessor.mailServerManager
def mailServer = mailServerManager.defaultSMTPMailServer
def multipart = new MimeMultipart()
def body = new MimeBodyPart()
def mailAttachment = new MimeBodyPart()
body.setContent(content, 'text/html; charset=utf-8')
mailAttachment.attachFile(new File(filename))
multipart.addBodyPart(body)
multipart.addBodyPart(mailAttachment)
def email = new Email(to)
email.setSubject(subject)
email.setMultipart(multipart)
email.setMimeType('text/html')
def threadClassLoader = Thread.currentThread().contextClassLoader
Thread.currentThread().contextClassLoader = mailServer.class.classLoader
mailServer.send(email)
Thread.currentThread().contextClassLoader = threadClassLoader
}
dest.delete() // delete modified file
Below is a print screen of the Create Screen.
I hope this helps to answer your question. :)
Thank you and Kind Regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Ram Kumar Aravindakshan _Adaptavist_, hi @Shah Baloch
I'v read this post with much interest, as this covers exactly my actual task.
But - may I ask you for an advice, as I run into errors all the time using the script as suggested finally in this post?
In our onboarding-Workflow, we'd like to send an static PDF with VPN-rules to the respective issue's reporter once the issue reaches a certain status.
But I fail selecting the correct sendto-address using the userpicker function in the code snippet if I select "reporter" as the respective user:
def userPicker = customFieldManager.getCustomFieldObjectsByName('Reporter').first()
def userPickerValue = issue.getCustomFieldValue(userPicker) as ApplicationUser
This leads to this error:
Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null java.util.NoSuchElementException: Cannot access first() element from an empty List at Script28.run(Script28.groovy:14)
So I changed the script to the last version suggested in these post and use a customfield containing the reporter's email-Adress (UPN) but get the next error:
def userEmail = customFieldManager.getCustomFieldObjectsByName('UPN').first()
Error:
ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null java.util.NoSuchElementException: Cannot access first() element from an empty List at Script61.run(Script61.groovy:13)
I'm a bit lost here...
Thanks and best regards,
Erik
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Ram Kumar Aravindakshan _Adaptavist_ ,
my apologies - like Murphy's law: once I sent my request to you, I found the error and was able to run the script as I hoped for.
Nonetheless - thanks for your previous discussion which helped me "on my way".
Best regards,
Erik
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.