Send email using ScriptRunner when sensitive files are involved in a pull request

We would like send an email using ScriptRunner when certain sensitive files are included in a pull request. This request is similar to the questions raised and answered in my earlier question here: How can we adapt this solution as an event handler for a PullRequestOpenedEvent that sends an email to certain users which would include a list of files changed?  When I use pathsMatch, I see the same issue as was raised in previous question. 

1 answer

1 accepted

2 votes
Accepted answer

The example in the other answer you have linked to can easily be adapted to work for an event handler, so a lot of this will be familiar. To make this easier you can use the built-in send mail event handler which will send the email if you listen for the PullRequestOpenedEvent.

You can find the event handler under Admin -> ScriptRunner -> Script Event Handlers -> Send mail.

The documentation for this can be found here. Your condition should be the following code which will stream the changes in the pull request and return true if sensitive files are detected.

import com.atlassian.bitbucket.content.AbstractChangeCallback
import com.atlassian.bitbucket.content.Change
import com.atlassian.bitbucket.event.pull.PullRequestOpenedEvent
import com.atlassian.bitbucket.pull.PullRequestChangesRequest
import com.atlassian.bitbucket.pull.PullRequestService
import com.atlassian.sal.api.component.ComponentLocator

import javax.annotation.Nonnull

def event =  event as PullRequestOpenedEvent
def pullRequestService = ComponentLocator.getComponent(PullRequestService)
// get pull request from event
def pullRequest = event.pullRequest

def senstiveFilePatterns = ["", "basic_branching/file.txt"]

def fileChangeFinder = new FileChangeFinder(senstiveFilePatterns)
pullRequestService.streamChanges(new PullRequestChangesRequest.Builder(pullRequest).build(), fileChangeFinder)

// return true if sensitive files detected
return fileChangeFinder.fileFound

class FileChangeFinder extends AbstractChangeCallback {

    private boolean fileFound = false
    private List<String> files

    FileChangeFinder(List<String> files) {
        this.files = files

    boolean onChange(@Nonnull Change change) throws IOException {

        if (change.path.toString() in files) {
            fileFound = true

        return true


Additionally if you want to check the files in all commits on the pull request (not just the diff changes) you can instead use as your condition: 


The first one will ignore deleted files too, more about that here.

Hope this helps. Let me know if you have trouble getting it to work.

Hi Adam,

Thank you for the information.  I am seeing this in my logs when it runs:

2016-09-27 17:38:03,007 ERROR [AtlassianEvent::thread-1] user @17HNHIKx1058x1738562x1 w7lfwf <IP ADDRESS> "POST /projects/SANDBOX/repos/pr-build-test/pull-requests HTTP/1.1" c.o.s.bitbucket.InnerListener Event handler failed: event: com.atlassian.bitbucket.event.pull.PullRequestOpenedEvent file: null

groovy.lang.MissingPropertyException: No such property: pullRequest for class: groovy.lang.Binding

 at$_doScript_closure3.doCall(StashSendCustomEmail.groovy:173) ~[na:na]

 at ~[na:na]

 at com.onresolve.scriptrunner.canned.CannedScript$doScript$ Source) ~[na:na]

 at com.onresolve.scriptrunner.canned.CannedScript$doScript$ Source) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.validateAndRunCannedInternal(ScriptRunnerImpl.groovy:402) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunnerImpl.runCanned(ScriptRunnerImpl.groovy:361) ~[na:na]

 at com.onresolve.scriptrunner.runner.ScriptRunner$runCanned$ Source) ~[na:na]

 at com.onresolve.scriptrunner.bitbucket.InnerListener.receiveEvent(BitbucketEventListener.groovy:202) ~[na:na]

 at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke( ~[atlassian-event-3.0.0.jar:na]

 at com.atlassian.stash.internal.event.AsyncBatchingInvokersTransformer$AsyncInvokerBatch.invoke( ~[bitbucket-platform-4.9.0.jar:na]

 at com.atlassian.event.internal.AsynchronousAbleEventDispatcher$1$ ~[atlassian-event-3.0.0.jar:na]

 at ~[sal-core-3.0.6.jar:na]

Any ideas?


I do not get the same error as you.

Did you modify the script I added in any way? It seems to be trying to get the pullRequest from the binding. Are you using:

def event =  event as PullRequestOpenedEvent
def pullRequest = event.pullRequest

to get the pull request from the event in your condition? Event is in the binding but pull request is not.

Failing that what version of ScriptRunner and Bitbucket are you using?

Hi Adam,

No, I did not modify the script.  I created a new Script Event Handler, gave it a name, a repository, and under events I added PullRequestOpenedEvent (the form did not let me leave this field blank).  I added the script under Condition, added a Subject template and Email template, chose HTML as Email format and added my email address.

Yes, those 2 lines are in the condition.

I am running Bitbucket version 4.9.0 and ScriptRunner version 4.3.4

Hi Michael,

I could not reproduce the same error as you even with those versions. Could you try upgrading your version of ScriptRunner and seeing if that resolves the issue?

I've attached my screenshots of the send mail event handler below for you to check you have a similar configuration.

For the condition I just copied and pasted the code I provided in my answer here.

Screen Shot 2016-09-29 at 13.40.22.png


Screen Shot 2016-09-29 at 13.40.40.png

Hi Adam,

Thanks, I upgraded the plugin and I removed some variables from the Subject template and Email template fields and now it works. I guess I need some help with what is possible in the templates.  Is there some documentation on that? Specifically, I would like to add the user who created the pull request, the file(s) changed and a link to the pull request.

I appreciate all the help!


Suggest an answer

Log in or Sign up to answer
Community showcase
Published Nov 29, 2018 in Marketplace Apps

How to set up an incident workflow from the VP of Engineering at Sentry

Hey Atlassian community, I help lead engineering at Sentry, an open-source error-tracking and monitoring tool that integrates with Jira. We started using Jira Software Cloud internally last year, a...

1,750 views 3 11
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you