๐ฅ Recipe ยท User & Group Management
List All Users in a Microsoft 365 Tenant with Name and Email
Export every user's first name, last name, and email address from Entra ID using the admin center, Microsoft Graph, or PowerShell
Complexity
Beginner
Impact
reporting + user-management + audit + low-risk + read-only
Context
Why This Matters
Getting a complete, accurate list of every user in your Microsoft 365 tenant is one of the most common admin tasks. Whether you're preparing a license audit, building a distribution list, handing a roster to HR, or validating that directory sync is producing the right set of accounts, you need a clean export of first name, last name, and email address.
The M365 admin center exposes this information in the Active users blade, but it caps the export at a fixed schema and doesn't always surface every user type (e.g., guest accounts, unlicensed service accounts). Microsoft Graph and the Microsoft.Graph PowerShell module give you full control over the fields returned, pagination, and filtering โ which is what you want for any list larger than a few hundred users.
Run this recipe whenever you need a point-in-time snapshot of your directory for reporting, migration planning, or compliance evidence.
Expected Outcomes
After completing this recipe you will have:
- A CSV or on-screen list of every user in the tenant showing givenName, surname, and mail (falling back to
userPrincipalNamewhen no primary SMTP is set). - A repeatable method โ manual, API, or scripted โ that correctly paginates through tenants with more than 100 users.
- A baseline you can diff against future exports to track joiners, leavers, and account changes.
Risks & Considerations
Watch out for
- Guest vs. member accounts. The default
/usersendpoint returns both. If you only want employees, filter with$filter=userType eq 'Member'. - Missing
mailvalues. Cloud-only accounts and unlicensed users often havemailset to null. Always fall back touserPrincipalNameso no row is blank. - Pagination. Graph returns at most 999 users per page. Always follow
@odata.nextLinkuntil it's absent โ otherwise your export is silently truncated. - PII handling. The exported CSV contains personal data. Store it on an encrypted share, limit who can read it, and delete it when the task is complete. Don't email it unencrypted.
- Throttling. On very large tenants (50k+), issue requests sequentially and respect
Retry-Afterheaders. Parallelizing the paged calls is not supported because each page depends on the previousnextLink.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| User.Read.All | Minimum scope required to enumerate all users and read basic profile properties (givenName, surname, mail, userPrincipalName). |
| Directory.Read.All | Alternative broader scope if you also need to read related directory objects (groups, roles) in the same workflow. |
| Global Reader (role) | For interactive admin-center or PowerShell-with-delegated-auth usage, Global Reader is sufficient and avoids granting write privileges. |
The fastest way to get this done โ just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex CoAdmin