Monday, 14 October 2019

Set Primary Email Address for Office 365 Users using Powershell

In this post, I am going to share Powershell commands to add email alias and set the new alias as the primary email address for Office 365 users. We can use the Set-Mailbox command to add new email alias, remove an old email address and set primary email address.

Note: Before proceed, Connect Exchange Online Remote Powershell.

Add new Email Alias and set as a Primary Email Address:

The below command adds the new alias in the EmailAddresses list and sets it as PrimarySmtpAddress. Replace the parameter "username" with Name or UserPrincipalName of the mailbox user.
Set-Mailbox 'username' -WindowsEmailAddress 'newalias@newdomain.com'

Remove old Email Alias:

The above command just adds the new email address and it will not remove the existing email, the old email address still works as a proxy address for the primary email address, you may want to remove existing email once you confirmed the new email works fine. You can remove the existing email alias by running the below command.
Set-Mailbox 'username' -EmailAddresses @{Remove='oldalias@olddomain.com'}

Add new Email Alias as Proxy Address:

In some cases, you may want to add a new email address for an Office 365 user without affecting the user's existing primary email address, in this case, you can add the new alias in the EmailAddresses list by running the below command.
Set-Mailbox 'username' -EmailAddresses @{Add='newalias@newdomain.com'}

Set Primary Email Address for Bulk O365 Users from CSV:

In some scenarios, we may be required to add email alias for multiple mailbox users in bulk by importing user details from CSV file. Consider the CSV file Office365Users.csv which contains every users` UPN (or Name) and new email address in each row with the column headers UserPrincipalName and NewEmailAddress.
Import-Csv 'C:\Office365Users.csv' | ForEach-Object {
Set-Mailbox $_."UserPrincipalName" -WindowsEmailAddress $_."NewEmailAddress"
}

Change UserPrincipalName to match with Primary Email Address:

In Office 365 cloud, users need to use their UPN (UserPrincipalName) as login name to sign-in to any Office 365 apps, changing user's WindowsEmailAddress (or PrimarySmtpAddress) will not change UPN of the users, so we may be required to update UPN while setting new email address to avoid confusions for end-users when they login-in to Office 365 apps. The Set-Mailbox command includes the parameter MicrosoftOnlineServicesID, this is the equivalent property of UPN which exists in the mailbox's associated Azure AD user object, we can set the new email address in this attribute to update UPN of the user.
Set-Mailbox 'username' -WindowsEmailAddress 'newalias@newdomain.com' -MicrosoftOnlineServicesID 'newalias@newdomain.com'
The above command throws the warning message: WARNING: UserPrincipalName "username@domain.com" should be same as WindowsLiveID "newalias@domain.com", UserPrincipalName should remain as "newalias@domain.com". Ignore this warning message and the UPN will be updated in a few minutes.

Set UPN and Primary Email Address for bulk mailbox users:

The below commands import mailbox users` names and email alias from CSV file and set the new mail address as PrimarySmtpAddress and UserPrincipalName.
Import-Csv 'C:\Office365Users.csv' | ForEach-Object {
Set-Mailbox $_."UserPrincipalName" -WindowsEmailAddress $_."NewEmailAddress" -MicrosoftOnlineServicesID $_."NewEmailAddress"
}
Read More...

Saturday, 28 September 2019

Report Group and Teams Enabled SharePoint Online Sites using Powershell

In this post, I am going to share Powershell commands to find and list all SharePoint Online sites, the returned result object includes the property GroupEnabled (Groupify) which indicates the site is connected with group or not, and the result object also includes the property TeamEnabled (Teamify) which indicates whether the Teams feature enabled in the site's associated group or not.

Before proceeding, install SPO Powershell Module and run the below commands to connect Exchange Online (EXO) and SharePoint Online modules:
$Cred = Get-Credential
#Import Exchange Online Powershell module
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
#Connect SharePoint Service
Connect-SPOService -Url "https://YourTenantName-admin.sharepoint.com " -Credential $Cred

Export all SPO Sites with Group and Team Details

Here, we are fetching site details using the Get-SPOSite command and retrieve Office 365 Group object with Get-UnifiedGroup command, the group object includes the property resourceProvisioningOptions which includes the array of values, we need to check whether this array includes the value "Team" to identify the teams feature is configured or not in the group.
$Result = @()
$AllSites = Get-SPOSite -IncludePersonalSite:$False -Limit All | Select Title,URL
$TotalSites = $AllSites.Count
$i = 1 
ForEach ($Site in $AllSites) {
Write-Progress -Activity "Processing $($Site.Title)" -Status "$i out of $TotalSites completed"
$O365Group = $null;
$TeamEnabled = $false;
#Once again call Get-SPOSite for each site with -Detailed switch to get GroupId property
#The bulk enumeration command (Get-SPOSite -Limit All) do not support -Detailed switch
$GroupId = (Get-SPOSite $Site.URL -Detailed).GroupId.Guid
if($GroupId -ne $null) {
$O365Group = (Get-UnifiedGroup -Identity $GroupId -ErrorAction SilentlyContinue)
if($O365Group -ne $null -and $O365Group.resourceProvisioningOptions -contains "Team") {
$TeamEnabled = $true;
}
}
$Result += New-Object PSObject -property @{ 
SiteName = $Site.Title
SiteURL  = $Site.URL
GroupEnabled = if ($O365Group -ne $null) { $true } else { $false }
GroupName  = if ($O365Group -ne $null) { $O365Group.DisplayName } else { $null }
GroupID  = if ($O365Group -ne $null) { $GroupId } else { $null }
GroupMail  = if ($O365Group -ne $null) { $O365Group.PrimarySmtpAddress } else { $null } 
TeamEnabled  = $TeamEnabled   
}
$i++
}
$Result | Select SiteName,SiteURL,GroupEnabled,GroupName,GroupID,GroupMail,TeamEnabled |
Export-CSV "C:\\AllSPOSites.CSV" -NoTypeInformation -Encoding UTF8
The above commands store the details in the array object $Result, we can generate the required report from this result array.

List all sites without group feature

You can just filter the $Result array with Where-Object to list sites without a group.
$Result | Where-Object { $_.GroupEnabled -eq $false } | Select SiteName,SiteURL
Alternatively, you can list sites only that are connected with a group.
$Result | Where-Object { $_.GroupEnabled -eq $true } | Select SiteName,SiteURL,GroupName

Get all sites without group and teams feature

$Result | Where-Object { $_.GroupEnabled -eq $false -and $_.TeamEnabled -eq $false} | Select SiteName,SiteURL
Alternatively, you can list sites with group, but without teams feature.
$Result | Where-Object { $_.GroupEnabled -eq $true -and $_.TeamEnabled -eq $false} | Select SiteName,SiteURL,GroupName

Get all sites with group and teams feature

$Result | Where-Object { $_.GroupEnabled -eq $true -and $_.TeamEnabled -eq $true} | Select SiteName,SiteURL,GroupName

Sample CSV Report:

Find Group and Teams Enabled SharePoint Online Sites using Powershell
Read More...

Friday, 27 September 2019

Groupify and Teamifiy a SharePoint Online Site using Powershell

In this post, I am going to explain how to programmatically connect an existing SharePoint Online site with Office 365 Group and add Teams feature using Powershell (and Office 365 CLI). We can use the SPO Powershell command Set-SPOSiteOffice365Group to integrate a site with a new Office 365 group and use New-Team command to create a team from the site connected Office 365 group.

Before proceeding, install SPO and Teams Powershell Modules and run the below commands :
$Cred = Get-Credential
#Connect Teams module
Connect-MicrosoftTeams -Credential $Cred
#Connect SharePoint Service
Connect-SPOService -Url "https://YourTenantName-admin.sharepoint.com " -Credential $Cred

Groupify a SharePoint Online Site

Run the following command to connect the root site collection with a new group.
#Groupify - Connect the site to new O365 Group
$SiteURL = "https://YourTenantName.sharepoint.com/sites/TestSite1"
$GroupName = "TestGroup"
$MailNickName = "TestGroup"
Set-SPOSiteOffice365Group -Site $SiteURL -DisplayName $GroupName -Alias $MailNickName

Teamify the group which is connected with the site

Once the site is integrated with a modern group, we can get the id (GroupId) of the connected group from spo_site object and create a new team from this new group.
#Teamify - Add Teams feature in the site associated O365 Group
$SiteObj = Get-SPOSite -Identity $SiteURL
New-Team -GroupId $SiteObj.GroupId.Guid
Office 365 CLI : If you are a big fan of Office 365 CLI, you can refer this post to achieve this functionality using Office 365 CLI.
Read More...

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:
Connect-AzureAD
Run the following command to retrieve manager information for a single user account.
Get-AzureADUserManager -ObjectId "username@domain.com"

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 }
}
$i++
}
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
Read More...

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.
Connect-MicrosoftTeams

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 "https://YourTenantName-admin.sharepoint.com " -Credential $Cred
#Groupify - Connect the Site to new Office 365 Group
$SiteURL = "https://YourTenantName.sharepoint.com/sites/TestSite1"
$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 "user@domain.com" to a team with the id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".
Add-TeamUser -GroupId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -User "user@domain.com"
We have to set the parameter Role as Owner to add a user as owner.
Add-TeamUser -GroupId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -User "admin@domain.com" -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.
Read More...

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 https://outlook.office365.com/powershell-liveid/ -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 "Kevin@contoso.com" and mailbox identity "Alex@contoso.com" with your user id and mailbox id.
Get-MailboxFolderPermission -Identity "Alex@contoso.com:\Calendar" -User "Kevin@contoso.com"

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 "Alex@contoso.com:\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 :

$Result=@()
$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
}}
$i++
}
$Result | Select MailboxName, User, Permissions |
Export-CSV "C:\\CalendarPermissions.CSV" -NoTypeInformation -Encoding UTF8
Read More...

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

Problem:

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 Alland@contoso.com:\Calendar -User KevinM@contoso.com -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
  .StoreTasks.SetMailboxFolderPermission
    + PSComputerName        : outlook.office365.com

Fix/Solution:

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 Alland@contoso.com:\Calendar -User KevinM@contoso.com -AccessRights Editor
Read More...

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 = "user@domain.com"
$password = "user_password"
$sstr = ConvertTo-SecureString -string $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -argumentlist $username, $sstr
$from = "user@domain.com"
$to = "user2@domain.com"
$body = "This is a test email"
$subject = "Test message"
Send-MailMessage -To $to -from $from -Subject $subject -Body $body -BodyAsHtml -SmtpServer "smtp.office365.com" -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 "to_address@domain.com".
$AccessToken = "eyJ0***Access Token with Mail.Send permission*****"
$ApiUrl = "https://graph.microsoft.com/v1.0/me/sendMail"
# Create JSON Body object
$Body = 
@"
{
"message" : {
"subject": "Test message",
"body" : {
"contentType": "Text",
"content": "This is test mail"
},
"toRecipients": [{"emailAddress" : { "address" : "to_address@domain.com" }}]
}
}
"@ 
Invoke-RestMethod -Headers @{Authorization = "Bearer $AccessToken"} -Uri $ApiUrl -Method Post -Body $Body -ContentType "application/json"
Read More...