Select Page

Let’s say you work as a Jira administrator for a company called Acme, which gets acquired by another company, Scavengers Inc. A decision is made that all e-mail addresses used by Acme’s employees will be migrated to a new domain:

* -> *

Both Acme and Scavengers have their own Jira instances, and they will be merged at some point, but not yet. Also, Scavenger’s Jira is connected to Active Directory, which serves as a user directory. Acme’s Jira users are managed within Jira itself. This Jira will be connected to Scavenger’s Active Directory at a later date.

In your Jira (Acme), you have 1200 users with their e-mail addresses in the domain and 60 external contractors, each of them possibly having an e-mail address in a different domain.

Simply put, you need to find a way to edit your user’s e-mail addresses automatically, e.g. should become, but addresses such as must remain unchanged. ​

Ok, how do we do this?


Here’s where ScriptRunner’s Console comes into play. That’s where you can manually run any script of your choice, both just reading data, and editing it. A huge help for any Jira administrator.
Here’s what the console looks like and how to find it:

Once you’re there you will need to create a script that will:

  1. Find the users whose domain is equal to
  2. Replace their domain with
  3. Update the user information in Jira’s database

Sounds easy, right? Here’s how to write the above in Groovy:

import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Level
import org.apache.log4j.Logger
import com.atlassian.jira.user.util.UserManager
import com.atlassian.jira.bc.user.ApplicationUserBuilderImpl


// let's define what domain we want to and what it should be afterwards
final SOURCE_DOMAIN = ''
final TARGET_DOMAIN = ''

// here's the definition of our search params, the domain name is not here yet
def userSearchService = ComponentAccessor.getUserSearchService()
def userSearchParams = new UserSearchParams.Builder()

// here is the actual search for the users who meet our search criteria
// including the domain in their e-mail
def userList = userSearchService.findUsers('', SOURCE_DOMAIN, userSearchParams)

// let's print who we have found and what their e-mails will be after the change
log.debug 'userList size: ' + userList.size() +
    	', emails found: ' + userList.collect { it.getEmailAddress() } +
        ', emails will be: ' + userList.collect {
            it.getEmailAddress().replace(SOURCE_DOMAIN, TARGET_DOMAIN) }

// now all what's left to do is to update the existing users with
// their new emails with the target domain instead of the source domain
def userManager = ComponentAccessor.getUserManager()
userList.each { 
        new ApplicationUserBuilderImpl(it)
                it.getEmailAddress().replace(SOURCE_DOMAIN, TARGET_DOMAIN)).build())

The implementation is straightforward. You can notice it uses closures for iteration instead of loops, which is a nice feature of Groovy that allows you to not only make the code a bit more modern, but it also has other benefits.

Now when you click the Run button under the console, the script will be executed and here’s what you’ll see in the Logs tab below the console:

2020-07-05 11:23:00,090 DEBUG [runner.ScriptBindingsManager]:
userList size: 3,
emails found: [,,],
emails will be: [,,]

This tells us the script has found 3 users that match the domain pattern, and it has changed their domains to, while leaving the non-matching e-mail address intact.
These are just 3 users since that’s what I have set up in my test environment, but I assure you it will work the same for the 1260 users I mentioned in the business requirements. In fact, that’s what scripts do! They scale.


Let’s see what the situation looked like before running the script:

Users from Acme

And after:

Users from Acme changed to Scavengers

Perfect, the matching users were edited, while the non-matching remained untouched. Just imagine how much time it would have taken you to do this manually. And how you can impress your boss with doing this job so much faster. That’s just the beginning.

That’s it for today. I encourage you to give it a try on your local Jira instance set up on your laptop. I described how to set it up here.