Skip to content

Instantly share code, notes, and snippets.

@fkasler
Last active May 8, 2024 06:49
Show Gist options
  • Save fkasler/f993bd6ca3668700f5ebf6cf74baf90b to your computer and use it in GitHub Desktop.
Save fkasler/f993bd6ca3668700f5ebf6cf74baf90b to your computer and use it in GitHub Desktop.
o365 Contact Miner
//paste this in the web console and copy out the results when it's done to a file like "allcontacts.json"
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
var gal = []
var contacts = []
function collectPersonas(){
let persona = gal.pop()
var canary = getCookie('X-OWA-CANARY')
$.ajax({
url: '/owa/service.svc?action=GetPersona&app=People&n=42',
type: 'post',
data: '',
headers: {
"X-OWA-CANARY": canary,
"X-OWA-URLPOSTDATA": encodeURIComponent(JSON.stringify({
"__type": "GetPersonaJsonRequest:#Exchange",
"Header": {
"__type": "JsonRequestHeaders:#Exchange",
"RequestServerVersion": "Exchange2013",
"TimeZoneContext": {
"__type": "TimeZoneContext:#Exchange",
"TimeZoneDefinition": {
"__type": "TimeZoneDefinitionType:#Exchange",
"Id": "Eastern Standard Time"
}
}
},
"Body": {
"__type": "GetPersonaRequest:#Exchange",
"PersonaId": {
"__type": "ItemId:#Exchange",
"Id": persona.PersonaId.Id
}
}
})),
"Action": "GetPersona",
"X-REQ-SOURCE": "People"
},
dataType: 'json',
success: function (data) {
contacts.push(data)
if(gal.length == 0){
console.log(JSON.stringify(contacts))
}else{
if((contacts.length % 100) == 0){
console.log(`Retrieved ${contacts.length} contacts...`)
}
collectPersonas()
}
}
})
}
function getGAL(offset){
var canary = getCookie('X-OWA-CANARY')
var global_address_id = ''
var address_ids = []
$.ajax({
url: '/owa/service.svc?action=GetPeopleFilters',
type: 'post',
data: {},
headers: {
"X-OWA-CANARY": canary,
"Action": "GetPeopleFilters"
},
dataType: 'json',
success: function (data) {
address_ids = data
address_ids.forEach(function(address_id){
if(address_id.DisplayName == "Default Global Address List"){
global_address_id = address_id.FolderId.Id
$.ajax({
url: '/owa/service.svc?action=FindPeople',
type: 'post',
data: JSON.stringify({
"__type":"FindPeopleJsonRequest:#Exchange",
"Header":{
"__type":"JsonRequestHeaders:#Exchange",
"RequestServerVersion":"Exchange2013",
"TimeZoneContext":{
"__type":"TimeZoneContext:#Exchange",
"TimeZoneDefinition":{
"__type":"TimeZoneDefinitionType:#Exchange",
"Id":"Eastern Standard Time"
}
}
},
"Body":{
"__type":"FindPeopleRequest:#Exchange",
"IndexedPageItemView":{
"__type":"IndexedPageView:#Exchange",
"BasePoint":"Beginning",
"Offset":offset,
"MaxEntriesReturned":999999999
},
"QueryString":null,
"ParentFolderId":{
"__type":"TargetFolderId:#Exchange",
"BaseFolderId":{
"__type":"AddressListId:#Exchange",
"Id":global_address_id
}
},
"PersonaShape":{
"__type":"PersonaResponseShape:#Exchange",
"BaseShape":"Default"
},
"ShouldResolveOneOffEmailAddress":false
}
}),
headers: {
"X-OWA-CANARY": canary,
"Action": "FindPeople"
},
dataType: 'json',
success: function (data) {
gal = gal.concat(data.Body.ResultSet)
if(data.Body.ResultSet.length > 9999){
console.log(`Retrieved ${offset + 9999} records... Pulling more`)
getGAL(offset + 10000)
}else{
console.log(`Retrieved ${gal.length} total records... Pulling contacts`)
collectPersonas()
}
}
})
}
})
}
})
}
getGAL(0)
//save this to a file and run with node: "node parseAllContacts.js allcontacts.json > contacts.csv"
var fs = require('fs')
var full_contacts = JSON.parse(fs.readFileSync(process.argv[2],'utf8'))
console.log(`"Firstname","Lastname","Position","Department","Office","Email","Work Phone","Cell Phone"`)
full_contacts.forEach(function(contact){
let person = contact.Body.Persona
let firstname = ''
let lastname = ''
let position = ''
let office = ''
let department = ''
let email = ''
let work_phone = ''
let cell_phone = ''
if(!!person.GivenName){
firstname = person.GivenName
}
if(!!person.Surname){
lastname = person.Surname
}
if(!!person.EmailAddresses){
email = person.EmailAddresses[0].EmailAddress
}
if(!!person.Title){
position = person.Title
}
if(!!person.BusinessPhoneNumbersArray){
work_phone = person.BusinessPhoneNumbersArray[0].Value.NormalizedNumber
}
if(!!person.MobilePhonesArray){
cell_phone = person.MobilePhonesArray[0].Value.NormalizedNumber
}
if(!!person.DepartmentsArray){
department = person.DepartmentsArray[0].Value
}
if(!!person.OfficeLocationsArray){
office = person.OfficeLocationsArray[0].Value
}
console.log(`"${firstname}","${lastname}","${position}","${department}","${office}","${email}","${work_phone}","${cell_phone}"`)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment