Post Function - email latest attachment

timh77 March 31, 2021

I am looking to have a post-function that emails out the most recently attached PDF to the issue being transitioned.  I have looked at the "Send custom email" post-function, but I can't think of how to send ONLY the most recent attachment that is a PDF.

I don't want to send all of the PDF attachments, only the latest one attached to the issue. 

I am working with the assumptions that the attachments won't be added on this transition and that more than one of the specified type will be on the issue.

Does anyone have any insights into a custom attachment callback for this?

2 answers

1 accepted

1 vote
Answer accepted
Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 2, 2021

Hi @timh77 ,

You will need to use ScriptRunner's Send a custom email option in the Post-Function for your requirement.

And in the Send a custom email configuration, you will need to include some conditions in the Custom attachment callback field to customise your attachment requirement.

You can follow the steps below:-

In this example, the post function is added for the In Progress transition.

1) First, go to the Post Functions and add select the Add post function option as shown in the image below:-

mail_config1.png

2) Second, select the Send a custom email [ScriptRunner] option as shown in the image below:-

mail_config2.png

3) Once you are on the Send a custom email configuration page, configure the fields you need to, and mainly, for the Include Attachments section, select the Custom option.

Next, for the Custom attachment callback section, you can try out this working sample code:-

import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.mail.MailAttachment

{
MailAttachment a ->

def issue = a.issue

def allAttachments = issue.attachments

def latest = allAttachments.findAll {

it.filename.endsWith(".pdf")

}.sort { it.created }.last()

return latest.id == a.id
}

Please note, this sample code is not 100% exact to your environment. Hence you will need to make the required modifications.

What the code does, is that it reads through all the attachments in the issue and includes only the PDF files.

Once the PDF files are included in the list, the files are sorted according to the date of creation.

Finally, it selects only the latest PDF file in the list and adds it to the mail as an attachment.

 

Below is a print screen of the Send a custom email configuration:-

mail_config3.png

Lastly, save the post-function and publish the changes and try to transition your issue.


I hope this helps to solve your question. :)

 

Thank you and Kind Regards,

Ram

timh77 April 2, 2021

That answers the question exactly as needed. The only other thing that I am having an issue with is defining the "Condition and Configuration".  I have the below setup but keep getting this error:

groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.getCustomFieldObjectByName() is applicable for argument types: (String) values: [Client(s)]
at Script14.run(Script14.groovy:7)

Here is the current config section:

import com.atlassian.gzipfilter.org.apache.commons.lang.StringUtils
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
 
// define custom fields to use
def customFieldManager = ComponentAccessor.getComponent(CustomFieldManager)
def clientsCf = getCustomFieldObjectByName('Client(s)') <-- Select list
def invoiceDateCf = getCustomFieldObjectByName('Invoice Date') <-- Date picker
def salesLeadCf = getCustomFieldObjectByName('Sales Lead') <-- User picker

// add value of custom fields to config map
config.clients = issue.getCustomFieldValue(clientsCf)
config.invoicedate = issue.getCustomFieldValue(invoiceDateCf)
config.salesLead = issue.getCustomFieldValue(salesLeadCf)

return true

 Any suggestions?

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 4, 2021

Hi @timh77 

Great to hear that the solution worked for you. :)

After reviewing your Current Config Section code, it doesn't appear to be correct.

Firstly, you need to be aware that there are few Bound variables for the Current Config Section field. You do not need to initialise these variables.  For example, the customFieldManager is a bound variable. 

To find out the bound variables, you can click on the question mark symbol at the bottom right of the Condition and Configuration field as shown in the image below:-

custom_config_1.png

 

When you click on the question mark, a dialog box will appear showing all the bound variables as shown in the image below:-

custom_config_2.png

 

If you notice the image above, the customFieldManager is available amongst the list of Bound variables.

The second thing to take note of is that in your code, you do not appear to have any object reference to invoke the getCustomFieldObjectByName i.e.

def clientsCf = getCustomFieldObjectByName('Client(s)')
def invoiceDateCf = getCustomFieldObjectByName('Invoice Date')
def salesLeadCf = getCustomFieldObjectByName('Sales Lead')

This will not work. Instead, it would be best if you tried something like this:-

def clientsCf = customFieldManager.getCustomFieldObjectsByName('Client(s)')[0]
def invoiceDateCf = customFieldManager.getCustomFieldObjectsByName('Invoice Date')[0]
def salesLeadCf = customFieldManager.getCustomFieldObjectsByName('Sales Lead')[0]

 

Below is a full sample Condition and Configuration code for your reference:-

def clientsCf = customFieldManager.getCustomFieldObjectsByName('Client(s)')[0]
def invoiceDateCf = customFieldManager.getCustomFieldObjectsByName('Invoice Date')[0]
def salesLeadCf = customFieldManager.getCustomFieldObjectsByName('Sales Lead')[0]

config.clients = issue.getCustomFieldValue(clientsCf)
config.invoicedate = issue.getCustomFieldValue(invoiceDateCf)
config.salesLead = issue.getCustomFieldValue(salesLeadCf)

 

I hope this helps to solve your question :)

 

Thank you and Kind regards,

Ram

timh77 April 10, 2021

That got me what I needed. Thank you very much.

Jyoti Verma
Contributor
February 22, 2022

Thanks a lot Ram Kumar - it helped me a lot today

Hemanth Kumar September 11, 2022

@Ram Kumar Aravindakshan _Adaptavist_ 

I need to find the latest attachment irrespective of file format and include it in my email notification as post function (script runner). Please help on this.

 

I could see one of the method:

import com.atlassian.jira.component.ComponentAccessor
def im = ComponentAccessor.issueManager
def am = ComponentAccessor.attachmentManager
def issue = im.getIssueObject('JSP-4736')
am.getAttachments(issue).sort{it.created}.last()

https://community.atlassian.com/t5/Adaptavist-questions/Get-last-added-attachment-to-issue-with-Scriptrunner/qaq-p/1481739#U2131350

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
September 11, 2022

Hi @Hemanth Kumar

For your requirement, you could try something like this:-

import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.mail.MailAttachment

{

MailAttachment a ->

def issue = a.issue

def allAttachments = issue.attachments

def fileExtensions = ['.pdf', '.jpg', '.jpeg', '.docx', '.png']

def latest = allAttachments.findAll {

fileExtensions.each { String fileType ->

it.filename.endsWith(fileType)

}

}.sort { it.created }.last()

return latest.id == a.id

}
Please note that the sample code provided is not 100% exact to your environment. Hence, you will need to make the required modifications.
I have tested this with the different types of attachments, and it is working as expected.
I hope this helps to answer your question. :)

Thank you and Kind regards,
Ram
Like Hemanth Kumar likes this
Hemanth Kumar September 12, 2022

@Ram Kumar Aravindakshan _Adaptavist_  thanks a lot, it worked.

But when i use this along with my other template and try completing the ticket - its throwing an error. 

Done-Transitions.JPG

i am using Email Issue Post-function  where i have configured subject, HTML Body and under attachment options chosen - Attachments returned by a Groovy script as shown below. Kindly advise where i made a mistake.

attachment groovy.JPG

Ram Kumar Aravindakshan _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
September 12, 2022

Hi @Hemanth Kumar

From the screenshot that you have shared, it doesn't appear to be a ScriptRunner feature. Hence, it is not expected to work.

I hope this helps to solve your question. :)

Thank you and Kind regards,

Ram

Like Hemanth Kumar likes this
Hemanth Kumar September 12, 2022

@Ram Kumar Aravindakshan _Adaptavist_ : i was using email this post function.

Later i switched to script runner for my complete requirements

Fetch Issue details, last comment and latest attachment and send as email closure notification.

your inputs helped me.. thanks a lot

0 votes
Hemanth Kumar September 11, 2022

@Ram Kumar Aravindakshan _Adaptavist_ :

thanks for the approach, it worked for me. I need to figure out a way if we can filter/sort all PDF, Docx and Jpg file ? I need to get latest attachment irrespective of file format. I mean any of these three file format fetch me the latest.

I have tried ".pdf" && ".jpg" && ".docx"  but it didn't work.

I need to sort attachments and fetch the latest one irrespective of file format

 

import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.mail.MailAttachment
{
    MailAttachment a ->

        def issue = a.issue

        def allAttachments = issue.attachments

        def latest = allAttachments.findAll {

            it.filename.endsWith(".docx")
            it.filename.endsWith(".pdf")
            it.filename.endsWith(".jpg")
            it.filename.endsWith(".png")

        }.sort { it.created }.last()

        return latest.id == a.id
}

Suggest an answer

Log in or Sign up to answer