importargparseimportcsvfromoffice365.sharepoint.client_contextimportClientContextfromtests.settingsimportcert_path,cert_thumbprint,client_id,site_url,tenant# Well-known user profile property names exported from UserProfilePropertiesPROFILE_KEYS=["PreferredName","Department","JobTitle","Office","Manager","WorkEmail","PictureURL"]defmain():parser=argparse.ArgumentParser(description="Export user profile properties to CSV")parser.add_argument("--output",default="profile_export.csv",help="output CSV path (default: profile_export.csv)")parser.add_argument("--limit",type=int,default=0,help="max users to export, 0 = all (default: 0)")args=parser.parse_args()ctx=ClientContext(site_url).with_client_certificate(tenant,client_id=client_id,thumbprint=cert_thumbprint,cert_path=cert_path)users=ctx.site.root_web.site_users.get_all().execute_query()ifargs.limit>0:users=list(users)[:args.limit]profiles=[]foruserinusers:ifuser.login_name:profiles.append(ctx.people_manager.get_properties_for(user.login_name))ctx.execute_batch()columns=["AccountName","DisplayName","Email"]+PROFILE_KEYSwithopen(args.output,"w",newline="",encoding="utf-8")asf:writer=csv.DictWriter(f,fieldnames=columns)writer.writeheader()forpinprofiles:props=p.user_profile_propertiesor{}row={"AccountName":p.account_nameorprops.get("AccountName",""),"DisplayName":p.display_nameorprops.get("PreferredName",""),"Email":p.emailorprops.get("WorkEmail",""),}row.update({key:str(props.get(key,"")or"")forkeyinPROFILE_KEYS})writer.writerow(row)print(f"Exported {len(profiles)} profiles to {args.output}")if__name__=="__main__":main()