Friday, 20 September 2019

Find and Export Manager of All Office 365 Users using Powershell

In this post, I am going to share powershell script to find manager info of all Office 365 users and export the details to CSV file. We can use the Get-AzureADUser command to get user details, but this command does not include manager based details, so we have to use the Get-AzureADUserManager cmdlet to get a user's manager info.

Before proceeding, install Azure AD PowerShell V2 module and run the below command to connect Azure AD Powershell:
Run the following command to retrieve manager information for a single user account.
Get-AzureADUserManager -ObjectId ""

Get Manager of All Azure AD Users

To get the manager detail of all users, first, we have to get all Office 365 users using the Get-AzureADUser command and pipe the result to Get-AzureADUserManager command. The below commands fetch all users and their manager details (ex: name and email address) and store the detail in the $Result array object.
$Result = @()
$AllUsers= Get-AzureADUser -All $true | Select-Object -Property Displayname,UserPrincipalName
$TotalUsers = $AllUsers.Count
$i = 1 
$AllUsers | ForEach-Object {
$User = $_
Write-Progress -Activity "Processing $($_.Displayname)" -Status "$i out of $TotalUsers completed"
$managerObj = Get-AzureADUserManager -ObjectId $User.UserPrincipalName
$Result += New-Object PSObject -property @{ 
UserName = $User.DisplayName
UserPrincipalName = $User.UserPrincipalName
ManagerName = if ($managerObj -ne $null) { $managerObj.DisplayName } else { $null }
ManagerMail = if ($managerObj -ne $null) { $managerObj.Mail } else { $null }
After the successful run of the above commands, you can run the below command to list all office 365 users with their manager info.
$Result | Select UserName, ManagerName, ManagerMail

List All Office 365 Users without Manager :

You can just filter the $Result array with Where-Object filter to list users with no manager.
$Result | Where-Object { $_.ManagerName -eq $null } | Select UserName, UserPrincipalName
Alternatively, you can list users only who have a manager.
$Result | Where-Object { $_.ManagerName -ne $null } | Select UserName, ManagerName

Export the Result to CSV file

You can easily export the result to CSV file using the Export-CSV cmdlet.
$Result | Select UserName, UserPrincipalName, ManagerName,ManagerMail  |
Export-CSV "C:\\O365UsersManagerInfo.CSV" -NoTypeInformation -Encoding UTF8

Find manager info for multiple users from CSV file

In some scenarios, we may need to find manager name for particular set of users. In this case, we can store the user ids in CSV file and import csv in powershell using Import-Csv cmdlet. Consider the CSV file "O365Users.csv" which contains username (or upn) of users with the column header UserPrincipalName.
$Result = @()
Import-Csv 'C:\O365Users.csv' | ForEach-Object {
$managerObj = Get-AzureADUserManager -ObjectId $_."UserPrincipalName"
$Result += New-Object PSObject -property @{ 
UserName = $_."UserPrincipalName"
ManagerName = if ($managerObj -ne $null) { $managerObj.DisplayName } else { $null }
ManagerMail = if ($managerObj -ne $null) { $managerObj.Mail } else { $null }
$Result | Select UserName, ManagerName,ManagerMail  |
Export-CSV "C:\\O365UsersManagerInfo.CSV" -NoTypeInformation -Encoding UTF8

Monday, 16 September 2019

Create a new Team in Microsoft Teams using PowerShell

In this post, I am going share Powershell commands to create a new team, add team (or enable team) in an existing Office 365 group and create a team from an existing SharePoint Online site. This post also includes commands to add members, owners, and channels in the newly created team. We can use the New-Team cmdlet from the Microsoft Teams Powershell module to add a team.

Before proceed run the below command to install Microsoft Teams Powershell module if you have not already installed.
Install-Module MicrosoftTeams -Force
Note: You have to run the powershell with "Run as administrator" privilege to install this module.

Once you have installed the Teams module, then run the following command to connect Microsoft Teams and it will ask your credentials to proceed.

Create a new team

Run the following command to create a new team.
New-Team -DisplayName "Test Team" -Visibility Public -Description "This is test Team"
While creating a team, this command also creates a new Office 365 Group with the same name and associate the new team with this group. On successfull run, this command returns the newly created Group object with GroupId property (which is TeamId), we can note this GroupId for future uses (ex: to add members, owners, and channels).

You can also provide more inputs with New-Team cmdlet, like MailNickName (Mail Alias for Office 365 Group), Owner (Additional owner). You can refer New-Team cmdlet documentation for more details.
New-Team -DisplayName "Test Team" -MailNickName "TestTeam" -Visibility Public -Description "This is test Team"

Create a team from existing Office 365 Group

If you already created and worked with an Office 365 Group, then you can easily convert this group to a team using the New-Team command by just passing the id of the group.
New-Team -GroupId "Existing Group ID - GUID"
Here, you cannot provide the group related values that are already specified in the existing group, ex: Visibility, Alias, Description, or DisplayName.

Create a team from existing SharePoint Online Site

You may have a scenario to enable Office 365 Group (Groupify) and add Team (Teamify) with existing SharePoint Online Site. If you have already connected the site with Office 365 group, then you can easily Teamify the group using the above command. If you yet to integrate the site with Office 365 group, then first you need to run the Set-SPOSiteOffice365Group cmdlet to add a new Office 365 group with the site and you can enable teams feature in the newly created group.

Before proceed run the below command to install the SharePoint Online Powershell module if you have not already installed.
Install-Module -Name Microsoft.Online.SharePoint.PowerShell
The below commands connect the site "TestSite1" with the new group "TestGroup" and teamify the new group.
#Connect SharePoint Service
$Cred = Get-Credential
Connect-SPOService -Url " " -Credential $Cred
#Groupify - Connect the Site to new Office 365 Group
$SiteURL = ""
$GroupName = "TestGroup"
$MailNickName = "TestGroup"
Set-SPOSiteOffice365Group -Site $SiteURL -DisplayName $GroupName -Alias $MailNickName
#Teamify - Create Team from the Site Associated O365 Group
$SiteObj = Get-SPOSite -Identity $SiteURL
New-Team -GroupId $SiteObj.GroupId.Guid

Add Members and Owners

We can use the Add-TeamUser cmdlet to add a user as member or owner in an existing team. The below command adds the user "" to a team with the id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".
Add-TeamUser -GroupId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -User ""
We have to set the parameter Role as Owner to add a user as owner.
Add-TeamUser -GroupId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -User "" -Role Owner

Add New Channels

We can use the New-TeamChannel cmdlet to create a new channel in a team. The below command creates a standard channel with display name as "Support"
New-TeamChannel -GroupId "<GroupId>" -DisplayName "Support"
You can create a private channel by passing the parameter MembershipType as Private.
New-TeamChannel -GroupId "<GroupId>" -DisplayName "Support" -MembershipType Private

Modify Team, Channel and Member Settings

We can use the Set-Team cmdlet to update the properties of a team, including its displayname, description, and team-specific settings.
Set-Team -GroupId "<GroupId>" -DisplayName "Edit Test Team" -Visibility Public
You can refer Set-TeamChannel and Set-TeamMemberSettings commands to update channel and member settings.

Friday, 13 September 2019

Get Calendar Permissions for All Users in Office 365

In Exchange, the calendar data located in a special folder (Calendar) under the user's mailbox. We can use the Exchange powershell cmdlet Get-MailboxFolderPermission to list all permissions that are configured in a Calendar folder.

Before proceed run the below commands to connect Exchange Online (EXO) powershell.
$365Logon = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $365Logon -Authentication Basic -AllowRedirection
Import-PSSession $Session

Get permissions for a single user in a user's calendar :

The below command returns permission entries for an individual user in a specific user's mailbox calendar. Run the below command after replacing the user "" and mailbox identity "" with your user id and mailbox id.
Get-MailboxFolderPermission -Identity "\Calendar" -User ""

Get all permissions in a user's calendar :

You have to exclude the parameter "-User" to list all user permissions in a specific user's mailbox. The below command list all users who have permission in Alex's mailbox calendar.
Get-MailboxFolderPermission -Identity "\Calendar"

Get all permissions in all users calendar :

To extract permissions from all users' calendars, first, we have to fetch all mailboxes with the Get-Mailbox cmdlet and pipe the result to Get-MailboxFolderPermission cmdlet to get the mailbox folder permissions.
Get-Mailbox -ResultSize Unlimited | ForEach {Get-MailboxFolderPermission -Identity "$($_.PrimarySMTPAddress):\Calendar" } | Select Identity,User,AccessRights
The above command returns all permission entries in all users' calendar, the result also includes the default permissions "Default" & "Anonymous". You can exclude the "Default" & "Anonymous" entries with Where-Object filter.
Get-Mailbox -ResultSize Unlimited | ForEach {Get-MailboxFolderPermission -Identity "$($_.PrimarySMTPAddress):\Calendar" } | Where-Object {$_.User.DisplayName -ne "Default" -and $_.User.DisplayName -ne "Anonymous"} | Select Identity,User,AccessRights

Export all users calendar permissions in all mailboxes to CSV file :

$allMailboxes = Get-Mailbox -ResultSize Unlimited | Select-Object -Property Displayname,PrimarySMTPAddress
$totalMailboxes = $allMailboxes.Count
$i = 1 
$allMailboxes | ForEach-Object {
$mailbox = $_
Write-Progress -activity "Processing $($_.Displayname)" -status "$i out of $totalMailboxes completed"
$folderPerms = Get-MailboxFolderPermission -Identity "$($_.PrimarySMTPAddress):\Calendar"
$folderPerms | ForEach-Object {
$Result += New-Object PSObject -property @{ 
MailboxName = $mailbox.DisplayName
User = $_.User
Permissions = $_.AccessRights
$Result | Select MailboxName, User, Permissions |
Export-CSV "C:\\CalendarPermissions.CSV" -NoTypeInformation -Encoding UTF8

Set-MailboxFolderPermission : There is no existing permission entry found for user


You might have received the below error message when you try to add permission for a user in another user's mailbox folder using the Set-MailboxFolderPermission cmdlet.
Set-MailboxFolderPermission -Identity\Calendar -User -AccessRights Editor -SharingPermissionFlags Delegate
There is no existing permission entry found for the user: Kevin Morgan.
    + CategoryInfo          : NotSpecified: (:) [Set-MailboxFolderPermission], UserNotFoundInPermissionEntryException
    + FullyQualifiedErrorId : [Server=XXXXXXXXXXXXX,RequestId=XXXXXXXX-181a-44f7-a613-53fdedb3d83c,TimeStamp=13-09-201
   9 06:31:53] [FailureCategory=Cmdlet-UserNotFoundInPermissionEntryException] F5424EF5,Microsoft.Exchange.Management
    + PSComputerName        :


You are receiving this error since you are trying to edit permission object that does not already exist. The mailbox folder permissions are treated as individual permission objects for every user, the Set-MailboxFolderPermission cmdlet will be used to update the existing permission object and you have to use Add-MailboxFolderPermission cmdlet to add new permission entry for a user.
Add-MailboxFolderPermission -Identity\Calendar -User -AccessRights Editor

Thursday, 12 September 2019

Send Email using PowerShell command and Graph API

We can use the Send-MailMessage cmdlet to send e-mail from Powershell script and you can use Send mail API endpoint to send a message using Microsoft Graph API.

Send Email using PowerShell command with Office 365 SMTP Server settings

You can replace the required parameter values ($username, $password, $from and $to) in below script and run the commands to send mail. Here, we are using Office 365 SMTP server, you can also use different mail server settings with this script by providing required inputs.
$username = ""
$password = "user_password"
$sstr = ConvertTo-SecureString -string $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -argumentlist $username, $sstr
$from = ""
$to = ""
$body = "This is a test email"
$subject = "Test message"
Send-MailMessage -To $to -from $from -Subject $subject -Body $body -BodyAsHtml -SmtpServer "" -UseSSL -Credential $cred -Port 587
Troubleshooting : Fix: Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated

Send Email using Microsoft Graph API

The Send mail API requires the permission Mail.Send. If you have valid Graph AccessToken with this permission, you can easily send mail without providing user credentials from Powershell. Before proceed, replace the parameters $AccessToken and "".
$AccessToken = "eyJ0***Access Token with Mail.Send permission*****"
$ApiUrl = ""
# Create JSON Body object
$Body = 
"message" : {
"subject": "Test message",
"body" : {
"contentType": "Text",
"content": "This is test mail"
"toRecipients": [{"emailAddress" : { "address" : "" }}]
Invoke-RestMethod -Headers @{Authorization = "Bearer $AccessToken"} -Uri $ApiUrl -Method Post -Body $Body -ContentType "application/json"

Fix: Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated

Problem :

You might have received the below error message when you try to send mail using the Send-MailMessage cmdlet.
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server
response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
At line:1 char:1
+ Send-MailMessage -To "" -from "admin ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpExcept
    + FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
I have used the below script to send mail using Office 365 user account. In my case, I have got the above error while providing wrong password in my script and the problem solved after providing correct user credentials.
$username = ""
$password = "user_password"
$sstr = ConvertTo-SecureString -string $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -argumentlist $username, $sstr
$body = "This is a test email"
Send-MailMessage -To "" -From "" -Subject 'Test message' -Body $body -BodyAsHtml -SmtpServer -UseSSL -Credential $cred -Port 587

Cause/Solution :

  • Possible Reason 1: Ensure that you have provided correct user credentials (User name and password).
  • Possible Reason 2: Ensure that you have provided the same user account for both Credential and From field.
  • Possible Reason 3: If you want to send mail on behalf of another user, then ensure that the user account has required permissions (ex: SendAs or SendOnBehalf) for the account that you provided in From field.
  • Possible Reason 4: If you face the issue with MFA enabled account, then you can generate an app password and then use an app password for that account, instead of the regular user password. Related thread:
  • Possible Reason 5: Make sure that you have used the option -UseSSL if your SMTP server requires a secure connection.

Thursday, 5 September 2019

Hide Office 365 Group from GAL via Graph API

We can easily hide Office 365 Groups from Global Address List (GAL) by using the Set-UnifiedGroup cmdlet by setting the property HiddenFromAddressListsEnabled as True. You can refer this post for more details.
Set-UnifiedGroup "group_name" -HiddenFromAddressListsEnabled:$true
In some scenarios, we need to set this property using Graph API. Microsoft Graph introduced the property resourceBehaviorOptions which includes a set of options that are related to Exchange properties of the group. The property resourceBehaviorOptions includes the option HideGroupInOutlook which is equivalent to HiddenFromAddressListsEnabled.

Hide from GAL while creating new Office 365 Group using Graph API

The following Graph API call creates a new group and sets the option HideGroupInOutlook in resourceBehaviorOptions which in-turn hides the group from global address book in Outlook.
Body :
  "description": "This is test group",
  "displayName": "TestO365Group",
  "groupTypes": [
  "mailEnabled": true,
  "mailNickname": "TestO365Group",
  "securityEnabled": false,

Update GAL visibility in existing Office 365 Group using Graph API

As of now, the Graph REST API supports this option only when creating a new group and you can't update the resourceBehaviorOptions property in existing groups. Currently you will get below error when you try to edit this option in existing group.
PATCH :{id}
Body  :

Error :
"code": "Request_BadRequest",
"message": "Property cannot be updated because it is immutable."

Supported values in resourceBehaviorOptions:

  • AllowOnlyMembersToPost
  • CalendarMemberReadOnly
  • ConnectorsEnabled
  • HideGroupInOutlook
  • NotebookForLearningCommunitiesEnabled
  • ReportToOriginator
  • SharePointReadonlyForMembers
  • SubscriptionEnabled
  • SubscribeMembersToCalendarEvents
  • SubscribeMembersToCalendarEventsDisabled
  • SubscribeNewGroupMembers
  • WelcomeEmailDisabled
  • WelcomeEmailEnabled