How to bulk update user email addresses in Jira Cloud

mohithb
Contributor
January 25, 2020

We have verified domain in our org. I know we can update email address of an user in the managed accounts page. Is there a way to bulk update? 

8 answers

2 accepted

2 votes
Answer accepted
Veera
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 25, 2020

@mohithb 

You will be able to do using REST APIs.

The Organizations API is available to list all the managed accounts in your Organization. You can use this to enumerate the unique Atlassian account ID for each users.

The User management API is available to edit individual users. Use Update a user profile end point to update the email address.

mohithb
Contributor
January 25, 2020

Thanks for the quick response @Veera 

Like Veera likes this
Veera
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 25, 2020

You are very welcome @mohithb

Like mohithb likes this
Maarten_Burssens
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
April 1, 2020

.

Maarten Burssens
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
April 1, 2020

hi Veera, this is an action that needs to be done by many organisations that start to manage their domain accounts on Atlassian. Is there an available code snippet/template so that we do not have to script this from scratch? The only difference between organisations are the API tokens..

thanks 

Maarten

Like Sanka Insomphou likes this
ferhat.surucu April 15, 2022

attached here

1 vote
Answer accepted
ferhat.surucu April 14, 2022

Atlassian Cloud - Bulk User Update

Summary

As of today, we know and are aware that atlassian cloud user access design is limited to conditions . In order to have MFA / SSO, atlassian requires you to verify the domain extension of each user.
(https://jira.atlassian.com/browse/ACCESS-102)

 

Note this will change soon and we may not need below steps;

Use at your own caution, test like 2-3 users before do bulk changes, play safe;


Bulk Update Condition

In order to bulk change atlassian accounts from x domain to y domain, you have to verify x and y domain in the same atlassian instance, before thinking of SSO or MFA enforcements

This change would be effective across all atlassian instances. Means atlassian cloud accounts are similar to having email accounts.

 

Note : Updating an Atlassian account's email will not change any other user data, like product-level information (ticket, history, etc).


Self Update Method

There is also a different approach, users can update their own but this requires different conditions. Both x and y domains have to be unverified. How to get here.

 

Batch Script to do changes in bulk is below;


> Please make sure you have Admin API key ready for this (instructions here)
> Make sure your system is allowed to run this script and show the path of your csv
> A CSV file ("file") which you will supply as input to the above script.

Tips for the Script :
It should contain an Atlassian account ID, old email (current email address), and target email.
You could obtain the Atlassian account ID and old email from a managed accounts export.
See the below csv example for formatting. Note that you will need a trailing comma on each line as well.

account_id,old_email,email,
1234,old_email1@domain.com,new_email1@domain.com,
4532,old_email2@domain.com,new_email2@domain.com,
2000,old_email3@domain.com,new_email3@domain.com,

 

Script is below ;

........................................................................................................................

#!/bin/bash
file=email_change.csv
APIkey=

header=true
while read line || [ -n "$line" ]
do
if [ "$header" = 'true' ];
then
header=false
continue
fi

account_id=`echo $line | cut -d ',' -f1`
old_email=`echo $line | cut -d ',' -f2`
email=`echo $line | cut -d ',' -f3`

echo "$account_id"':' ' old_email:'"$old_email" ' -> new_email:'"$email"

email="${email%%[[:cntrl:]]}"

curl --request PUT \
--url "https://api.atlassian.com/users/${account_id}/manage/email" \
--header "Authorization: Bearer ${APIkey}" \
--header 'Content-Type: application/json' \
--data '{
"email": "'"$email"'"
}'

done <$file

............................................................................................................................

 

If any issues with script, atlassian support should be able to give a hand.

Moses Thomas
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 27, 2023

@ferhat.surucu 

The script makes sense and it works correctly!  but you may want to add the following cos not every user know bash scripting and how to run it

Runing your script

  • Generate your API key details can be found in script Generate API
  • On your unix-like machine, go to the path where you have the script by typing cd /home/atlassian for instance
  • Give your script executable permission by typing chmod +x scriptname.sh
  • while you are still in the path where the script is the type ./scriptname.sh to finally run the script

Kind regards,

Moses

Like # people like this
ferhat.surucu February 27, 2023

Thanks alot @Moses Thomas , very good point.

 

How was your experience bulk renaming users ?

How many users you had to updated ? Was there any data loss after rename ?

just wanted to understand overall experience

 

Thanks alot again :)

Moses Thomas
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 27, 2023

@ferhat.surucu  I have renamed about 5 users for testing purpose  and all is perfect! , there is no data loss of course after testing because in the script we are just renaming the login but user id  remains the same.

 

Thank you for the post too!. No need to do it in groovy or using script runner.

 

Kind regards,

Moses

Like ferhat.surucu likes this
ferhat.surucu February 27, 2023

awesome, thanks alot

we are foreseeing renaming of > 1000 users :) lol

wonder what would be api limit

Like Moses Thomas likes this
Moses Thomas
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 27, 2023

@ferhat.surucu  There is no limit, if you look at the script you are updating a single account in the iteration(one after the other) doesn't matter how many users you have in the CSV.

 

Kind regards,

Moses

Like ferhat.surucu likes this
0 votes
ferhat surucu
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
August 25, 2024

New Approach after AI in our life;

 

- Draft & Plan what you need to do in Atlassian,

- Check Atlassian API documentation if Possible,

- Ask AI to generate you script you like (python simplest)

- Smart Enough > Test it before apply widely

 

Sample,

 

- Want to update usernames in bulk 

- Available in Atlassian API

- Hey ChatGPT; Can you please generate me python script by referring Atlassian API which will update usernames in bulk via csv that I will provide 

 

0 votes
Kader Price August 25, 2024

Hello @Moses Thomas , @Brian Yurick , @SunilKumar.Shangishetty , @ferhat.surucu , @Ferhat Surucu J2 , @Maarten_Burssens 

i need to change the domain in jira cloud for multiple users 

i have see differentes scripts but who is the right script ?

Thanks in advance

0 votes
Ravi Kumar Boddu December 15, 2023

@Brian Yurick - Can you please share the detailed steps how your are running the python script? 

0 votes
Ferhat Surucu J2
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
May 2, 2023

If stuck with 50 api limit crap, try belows

 

Bulk update emails

 

import csv

import requests

 

access_token = "your_api_key"

 

update_email_url = "https://api.atlassian.com/users/{account_id}/manage/email"

 

# Read in CSV file with list of account IDs and new email addresses

with open("emails_change.csv") as f:

reader = csv.DictReader(f)

account_data = [(row["\ufeffaccount_id"], row["old_email"], row["new_email"]) for row in reader]

 

# Loop through list of accounts and update email addresses

for i in range(0, len(account_data), 50):

chunk = account_data[i:i+50]

for account_id, old_email, new_email in chunk:

url = update_email_url.format(account_id=account_id)

headers = {

"Authorization": f"Bearer {access_token}",

"Content-Type": "application/json",

}

payload = {

"email": new_email

}

response = requests.put(url, headers=headers, json=payload)

if response.status_code == 204:

print(f"Updated email for account {account_id} from {old_email} to {new_email}")

else:

print(f"Failed to update email for account {account_id}: {response.text}")

 

if i + 50 < len(account_data):

response = input("Do you want to continue? Press 'y' to continue or any other key to stop.")

if response.lower() != "y":

break

 

It should do 50 row at a time and prompt if want to continue

 

Bulk Deactivate is below

 

import pandas as pd

import requests

import json

import csv

 

url = "https://api.atlassian.com/users/{account_id}/manage/lifecycle/disable"

 

headers = {

"Content-Type": "application/json",

"Authorization": "Bearer YourAPI Key"

}

 

# Read the CSV file using pandas

df = pd.read_csv("bulksuspend.csv")

 

# Create a loop that iterates over the rows of the DataFrame with a step size of 50

for i in range(0, len(df), 50):

batch_df = df.iloc[i:i+50]

 

# Extract the required information from each row

for index, row in batch_df.iterrows():

org_id = row['org_id']

account_id = row['account_id']

email = row['email']

 

# Use the extracted information to form the request URL and headers

request_url = url.format(account_id=account_id)

payload = json.dumps({

"message": "On 6-month suspension"

})

 

# Send a DELETE request to the endpoint with the necessary headers and URL parameters

response = requests.request(

"POST",

request_url,

data=payload,

headers=headers

)

 

# Prompt the user if they want to proceed with the next batch of deactivation

if index % 50 == 0 and index != 0:

user_input = input("Do you want to proceed with the next batch of deactivation? (Y/N)").lower()

if user_input == 'n':

break

 

# If the user has not yet confirmed to continue with the next batch, prompt again

if 'user_input' in locals() and user_input == 'n':

break

 

Export all managed users from org below

 

import requests

import json

import csv

import logging

 

url = "https://api.atlassian.com/admin/v1/orgs/your-org-id/users?limit=50"

 

headers = {

"Accept": "application/json",

"Authorization": "Bearer YourAPIKEY"

}

 

users = []

 

while True:

response = requests.get(url, headers=headers)

if response.status_code != 200:

logging.error("Failed to get users from API: status code %d", response.status_code)

break

data = json.loads(response.text)

if "data" not in data or not data["data"]:

logging.error("API response does not contain user data")

break

users += data["data"]

if "links" not in data or "next" not in data["links"]:

break

url = data["links"]["next"] + "&limit=50"

 

# Open a CSV file for writing

with open("allmanagedusers.csv", "w", newline="", encoding="utf-8") as f:

writer = csv.writer(f)

 

# Write the header row

writer.writerow(["account_id", "email", "account_status", "access_billable"])

 

# Write the user data rows

for user in users:

writer.writerow([user["account_id"], user["email"], user["account_status"], user["access_billable"]])

0 votes
ferhat.surucu April 25, 2023

for the ones who like to use python since available almost everywhere in general, 

 

Bulk Change/Update Emails

Preparation

Make sure you have admin account in Atlassian & once logged in create api key for the org,

https://admin.atlassian.com/o/xyz ---> settings ---> api keys, save it handy & secure place,

Make sure old_email & email domains are verified under same org, otherwise wont work.

Prepare your csv file & also analyze your directory. Because if email already exist, but suspended or not in use that you may want to rename to somethingelse before run it.

 Save the csv & python script at same location/path

required -> account_id, old_email(current), email(new)

Screenshot 2023-04-25 at 5.12.10 PM.png

 

Code is Below 

 

#!/usr/bin/env python3

 

import requests

import csv

 

FILE = "email_change.csv"

API_KEY = "xyzabc"

 

with open(FILE, newline='') as f:

reader = csv.reader(f)

header = True

for row in reader:

if header:

header = False

continue

account_id = row[0]

old_email = row[1]

email = row[2]

 

print(account_id, " old_email: ", old_email, " -> new_email: ", email)

 

email = email.strip()

print(email)

 

url = f"https://api.atlassian.com/users/{account_id}/manage/email"

 

headers = {

"Authorization": f"Bearer {API_KEY}",

"Content-Type": "application/json"

}

data = {

"email": email

}

response = requests.put(url, headers=headers, json=data)

response.raise_for_status()

print(response.text)

 


Also adding extra stuff below  that you may need in terms of bulk operations or find it handy

Bulk Suspend Accounts

 Preparation

Make sure you have admin account in Atlassian & once logged in create api key for the org,

https://admin.atlassian.com/o/xyz&nbsp; ---> settings ---> api keys, save it handy & secure place,

Prepare your csv file & make sure double check account_ids, do not disable wrong accounts :)

 Save csv & python script at same location/path

 *Suspended accounts do not cost license, they can be recovered anytime

required - > org_id & account_id optional -> email (just informational)

Screenshot 2023-04-25 at 5.57.24 PM.png

Code is below

 

#!/usr/bin/env python3

 

import requests

import csv

 

FILE = "bulksuspend.csv"

API_KEY = "xyz"

 

with open(FILE, newline='') as f:

reader = csv.reader(f)

header = True

for row in reader:

if header:

header = False

continue

org_id = row[0]

account_id = row[1]

email = row[2]

 

print(org_id, account_id, email)

 

url = f"https://api.atlassian.com/admin/v1/orgs/{org_id}/directory/users/{account_id}/suspend-access"

 

print(url)

 

headers = {

"Authorization": f"Bearer {API_KEY}",

"Content-Type": "application/json"

}

data = {

"org_id": org_id,

"account_id": account_id

}

response = requests.post(url, headers=headers, json=data)

response.raise_for_status()

print(response.text)


 

Export list of users from the Org

 

If you know your Atlassian organization id, you can export list of users from that org

 

Code is below

 

#!/usr/bin/env python3

import requests

import json

import csv

import pandas as pd

 

API_KEY = "xyz"

org_Id = "your org id"

url = f"https://api.atlassian.com/admin/v1/orgs/{org_Id}/users"

headers = {

  "Accept": "application/json",

  "Authorization": f"Bearer {API_KEY}"

}

 

response = requests.request("GET",url,headers=headers)

 

 

myjson = response.json()

myjson_str = json.dumps(myjson)

data = json.loads(myjson_str)

df = pd.json_normalize(data, record_path=['data'])

#below to drop unnecessary columns from the result

df = df.drop(["picture","product_access","links.self"],axis=1)

df.to_csv("orgusers.csv", index=False, encoding="utf-8")

 

Please note above api url will result on 50 records in default, so you need to add optional query parameters which are startAt & maxResults

 You have to call service multiple times to fetch all the data,

 For example, if you have 2560 users,

 startAt=0&maxResults=1000

startAt=1000&maxResults=1000

startAt=2000&maxResults=1000 (This will return only 560 users)

 


 

List Domains that verified under the Organization

 

If you know your Atlassian organization id, you can use rest api or Atlassian UI to list these verified& managed domains if any,

 

Code is below

 

#!/usr/bin/env python3

import requests

import json

import csv

import pandas as pd

 

 

API_KEY = "xyz"

org_Id = "your org id"

 

url = f"https://api.atlassian.com/admin/v1/orgs/{org_Id}/domains"

 

headers = {

  "Accept": "application/json",

  "Authorization": f"Bearer {API_KEY}"

}

 

response = requests.request("GET",url,headers=headers)

 

myjson = response.json()

myjson_str = json.dumps(myjson)

data = json.loads(myjson_str)

df = pd.json_normalize(data, record_path=['data'])

df.to_csv("domains.csv", index=False, encoding="utf-8")

 


 

 

0 votes
SunilKumar.Shangishetty April 20, 2021

Hi Veera,

I'm also looking for the same solution. I'm new to JIRA, can you please help me out with the Code to do a bulk update domain in the user email address.

Thanks in advance.

ferhat.surucu April 15, 2022

attached to here

Like Mark Bailey likes this
Brian Yurick January 10, 2023

Has anyone gotten this script to work? I keep getting errors:

: command not foundne 4:

./bulk-email.sh: line 30: syntax error near unexpected token `done'

./bulk-email.sh: line 30: `done <$file'

Brian Yurick January 11, 2023

OK I figured out the file I made has extra carriage returns. After fixing that I get no more errors when I run the script but it didn't work as the email/user I was testing with didn't update.

Brian Yurick January 11, 2023

I set the output of running the script to a log file and it shows nothing is happening. No errors or anything.

Moses Thomas
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 26, 2023

@Brian Yurick  If you create the right template as explained and  run the script  it works correctly

Suggest an answer

Log in or Sign up to answer