Wednesday, 24 May 2017

How to allow external sender for Office 365 Groups using Powershell

Office 365 Group is a back end service for Microsoft Teams, Planner, and etc. By default Office 365 Groups are not configured to receive external messages either it is public or private group. But most of organizations using Teams, Planner and even standalone Office 365 Groups for external collaboration and conversation, so receiving mails from external domain users is inevitable.

We can use the Exchange Online Powershell cmdlet Set-UnifiedGroup to set the people outside the organization to send mail to a specific group. Before proceed, Connect Exchange Online Powershell module and use the following command to allow external sender.
Set-UnifiedGroup <group> -RequireSenderAuthenticationEnabled $false
Actually we need to set the attribute RequireSenderAuthenticationEnabled as false to remove the authentication check of external senders. You can use the below command if you want set this property for all the Office 365 Groups.
Get-UnifiedGroup | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false
You can use below command if you want allow guest users only for all public groups:
Get-UnifiedGroup | Where-Object {$_.AccessType -eq 'Public'} | Set-UnifiedGroup -RequireSenderAuthenticationEnabled $false
We can list all the groups with external sender access property using below powershell:
Get-UnifiedGroup | Select Alias,AccessType,RequireSenderAuthenticationEnabled
The below command lists only office 365 groups with guest sender access enabled.
Get-UnifiedGroup | Where-Object {$_.RequireSenderAuthenticationEnabled -eq $false} | Select Alias,RequireSenderAuthenticationEnabled
You can also enable via UI using Office 365 Admin center: Office 365 Portal -> Peoples -> Edit Group and set the option "Let people outside the organization email the group"

allow guest sender access for Office 365 Groups

Thursday, 23 March 2017

Enable or Disable In-Place Archive in Exchange Online using Powershell

In Exchange Online, users can have additional mailbox storage space by enabling In-Place Archive. Archive mailboxes also provide an alternate storage location in which to store historical messaging data. You can easily enable or disable In-Place Archive through Exchange Admin Center (EAC), but you should go with Powershell if you want to quickly enable the archive mailbox for all mailboxes in your organization.

Enable In-Place Archive for a mailbox

You can use Enable-Mailbox cmdlet to enable archiving for existing mailbox. You may already used Enable-Mailbox cmdlet to create mailbox for existing users who don't already have mailbox, you can use the same cmdlet to enable In-Place Archive by passing an extra parameter -Archive.

Before proceed, Connect Exchange Online Powershell module and use the following command to enable mailbox archiving.
Enable-Mailbox -Identity <mailbox user id> -Archive
The following command creates an In-Place archive for the existing user AlexD who already has a mailbox.
Enable-Mailbox -Identity AlexD -Archive

Disable In-Place Archive in a mailbox

As like enable archiving, you can use Disable-Mailbox cmdlet to disable archive feature in a mailbox. Use the below command to disable mailbox archive:
Disable-Mailbox -Identity <mailbox user id> -Archive
The below command removes archiving feature from the user AlexD's mailbox.
Disable-Mailbox -Identity AlexD -Archive

Wednesday, 15 February 2017

Read Multiple Users Profile Properties From SharePoint Online Using CSOM

This post is follow-up of the article, in previous post I have clearly explained about how to read current user profile properties, specific user (other user) properties and how to read only required profile properties using client object model (CSOM). One of our user asked the question "How to get a specific profile property (path to profile picture for example) for all of my Sharepoint's website users in one request", so I am writing this post to help every users.


Get All Profile Properties for Multiple SharePoint Online Users

In the below C# code, I have passed only list of SharePoint Online users, you can fetch all SharePoint Online users using your own best method and use it in below code. You can read users using Azure AD powershell cmdlet Get-MsolUser or you can fetch from your own csv file.
public static void GetMultipleUsersProfileProperties()
    string siteUrl = "";

    var passWord = new SecureString();
    foreach (char c in "pass@word1".ToCharArray()) passWord.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("", passWord);
    // Connect to the sharepoint site client context.
    ClientContext clientContext = new ClientContext(siteUrl);
    clientContext.Credentials = credentials;

    // Get the PeopleManager object.
    PeopleManager peopleManager = new PeopleManager(clientContext);

    // Get multiple users
    List<string> Users = new List<string> { "",
"", "" };

    var results = new Dictionary<string, PersonProperties>();
    foreach (var user in Users)
        string loginName = "i:0#.f|membership|" + user;  //claim format login name
        var personProperties = peopleManager.GetPropertiesFor(loginName);
        clientContext.Load(personProperties, p => p.AccountName, p => p.DisplayName,
                           p => p.UserProfileProperties);
        results.Add(loginName, personProperties);

    foreach (var kvp in results)
        if (kvp.Value.ServerObjectIsNull.HasValue && !kvp.Value.ServerObjectIsNull.Value)
            foreach (var property in kvp.Value.UserProfileProperties)
                Console.WriteLine(string.Format("{0}: {1}",
                    property.Key.ToString(), property.Value.ToString()));
            Console.WriteLine("User not found:"+kvp.Key);
        Console.WriteLine("          ");

Get Specific Profile Properties for Multiple SharePoint Online Users

The below csom based C# code read only specific set of properties for set of SharePoint Online users.
public static void GetSpecificProfilePropertiesForAllUsers()
    string siteUrl = "";

    var passWord = new SecureString();
    foreach (char c in "pass@word1".ToCharArray()) passWord.AppendChar(c);
    var credentials = new SharePointOnlineCredentials("", passWord);

    // Connect to the sharepoint site client context.
    ClientContext clientContext = new ClientContext(siteUrl);
    clientContext.Credentials = credentials;

    // Get the PeopleManager object.
    PeopleManager peopleManager = new PeopleManager(clientContext);

    // Get multiple users - you can provide all users by fetching with different service
    // Ex: from Get-MsolUser powershell cmdlet
    List<string> Users = new List<string> { "",
"", "" };

    var results = new Dictionary<string, IEnumerable<string>>();
    foreach (var user in Users)
        string loginName = "i:0#.f|membership|" + user;  //claim format login name
        // Retrieve specific properties by using the GetUserProfilePropertiesFor method.  
        string[] profilePropertyNames = new string[] { "PersonalSpace", "PictureURL", "SPS-JobTitle" };
        UserProfilePropertiesForUser profilePropertiesForUser = new UserProfilePropertiesForUser(
            clientContext, loginName, profilePropertyNames);

        IEnumerable<string> profilePropertyValues = peopleManager.GetUserProfilePropertiesFor(profilePropertiesForUser);

        // Load the request for the set of properties. 
        results.Add(loginName, profilePropertyValues);

    foreach (var kvp in results)
        if (kvp.Value != null && kvp.Value.Count() > 0)
            Console.WriteLine("User :" + kvp.Key);
            // Returned collection contains only property values 
            foreach (var value in kvp.Value)
            Console.WriteLine("User not found:" + kvp.Key);

Tuesday, 14 February 2017

Disable AD User based on specific attribute using Powershell

In this article, I am going write powershell script to disable Active Directory user account by using user's specific property like employeeNumber, employeeID, etc...You can disable an ad user account by using the Active Directory powershell cmdlet Disable-ADAccount.
Disable-ADAccount -Identity <adaccount>
The Identity parameter specifies the Active Directory user that you want to disable. You can identify an account by its distinguished name (DN), GUID, security identifier (SID), or samAccountName.

Using the above command, you can not find user by using other AD attributes. So, we need to use another cmdlet Get-ADUser to find user using specific attribute and then we can pipe the result to Disable-ADAccount command to disable.

The following command search an AD user by user's EmployeeID using SQL like filter and disable the user.
Import-Module ActiveDirectory
Get-ADUser -Filter 'employeeID -like "1200547"' | Disable-ADAccount
You can also find an user by using well-known LDAP Filter. The following command find user by LDAP filter using user's EmployeeID and disable the user.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(employeeID=1200547)'  | Disable-ADAccount

Disable Bulk AD Users from CSV by User's EmployeeID

The following powershell script import AD users from csv file and disable by using user's EmployeeID property. Consider the CSV file Users.csv which contains set of AD users to disable with the attribute EmployeeID as one of the csv column header.
Import-Module ActiveDirectory
Import-Csv "C:\Users.csv" | ForEach-Object {
$employeeID = $_."EmployeeID"
Get-ADUser -LDAPFilter "(employeeID=$employeeID)"  | Disable-ADAccount
Write-Host "User $employeeID disabled"

Monday, 13 February 2017

Get the list of External users in SharePoint Online using Powershell

We can get the list of all external users in a SharePoint Online tenant using SharePoint Online Powershell cmdlet Get-SPOExternalUser and we can also find and list all the Office 365 guest users by using the Azure AD Powershell cmdlet Get-MsolUser. In this post, I am going to write script to export list of all the external user details to csv file.


Get all the External users using Get-SPOExternalUser cmdlet

The below script list the external users from first page. You have to specify your SharePoint Online Admin Center url and Office 365 Admin Credentials to run the following commands.
#Connection to SharePoint Online
$365Logon = Get-Credential
Connect-SPOService -Url $SPOAdminSiteUrl -Credential $365Logon  

Get-SPOExternalUser -Position 0 -PageSize 50 | Select DisplayName,Email | FT
If you want to retrieve users from second page, you have to set the position as 1. The below command returns first 10 external users from the second page of the collection.
Get-SPOExternalUser -Position 1 -PageSize 10
You can also specify the parameter SiteUrl to retrieve external users only for a specific site.
Get-SPOExternalUser -Position 0 -PageSize 50 -SiteUrl <YourSiteUrl>

Fetch all the Office 365 External (Guest) users using Get-MsolUser cmdlet

The above command Get-SPOExternalUser will be very helpful if you have minimum number of external users. But it will be difficult if you have 100s of users as you have to fetch users page by page. So to overcome this problem, we can use the Azure AD Powershell cmdlet Get-MsolUser.
#Connection to Azure AD Module
Import-Module MSOnline
$365Logon = Get-Credential
Connect-MsolService –Credential $365Logon

Get-MsolUser -All | ? {$_.UserType -eq "Guest"} | Select DisplayName,SignInName | FT
The above command returns all the Office 365 external users (guest users). You can also apply more where filter to get users from specific domain. The below command returns users only from the domain
Get-MsolUser -All | ? {$_.UserType -eq "Guest"} | ? {$_.SignInName -like "*"}

Export all the External user details to CSV file

You can easily export the external user details to csv file by using the cmdlet Export-Csv.
Get-MsolUser -All | ? {$_.UserType -eq "Guest"} | Select DisplayName,SignInName |
Export-CSV "C:\\External-Users.csv" -NoTypeInformation -Encoding UTF8

Thursday, 9 February 2017

Update Office 365 License features using Powershell

You can easily add a new license with required features and remove an existing license using Azure AD Powershell cmdlet Set-MsolUserLicense. In certain scenario you may need to update an existing license features (enable or disable license sub plans) using this cmdlet.

Use the below command to set a new license.
Set-MsolUserLicense -UserPrincipalName '' -AddLicenses 'contoso:ENTERPRISEPACK'
To assign multiple licenses, you have to provide AccountSkuId of all the licenses as comma (,) separated values.
Set-MsolUserLicense -UserPrincipalName '' -AddLicenses contoso:ENTERPRISEPACK,contoso:AAD_PREMIUM
You can enable only particular set of features while adding new license to an user. we have to use the powershell cmdlet New-MsolLicenseOptions to set license features that we want to disable (or remove) from new license.
$options = New-MsolLicenseOptions -AccountSkuId 'contoso:O365_BUSINESS_PREMIUM' -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
Set-MsolUserLicense -UserPrincipalName '' -LicenseOptions $options –AddLicenses 'contoso:O365_BUSINESS_PREMIUM'
Note: There is no option EnabledPlans like DisabledPlans, so we can't set only required features in straightforward way, we can achieve this only by excluding non-required features by using DisabledPlans option.

Update existing Office 365 License features

If you want to update or disable license features in existing license, you have to set only LicenseOptions in Set-MsolUserLicense cmdlet (exclude the parameter –AddLicenses).
$options = New-MsolLicenseOptions -AccountSkuId 'contoso:O365_BUSINESS_PREMIUM' -DisabledPlans OFFICE_BUSINESS,MCOSTANDARD
Set-MsolUserLicense -UserPrincipalName '' -LicenseOptions $options

Tuesday, 31 January 2017

Working with Array in Powershell

Array holds a list of data items. The Powershell array items can be the same type or different types.

Create or Initialize an Empty Array

The following syntax just creates an empty array object.
$myArray = @()

Create Array with Items

We can easily create predefined Array by just setting comma separated elements.
$myArray = "A","B","Hello","World"
Using explicit syntax:
$myArray = @(1,2,3,4,5)

Add values to an Array

We can add items to an array object by using the + operator.
$myArray = @(1,2,3,4,5)
$myArray = $myArray + 6
You can simplify the add operation by using assignment operator.
$myArray += 6
You can also add another array object using + operator.
$myArray += $secondArray

Read the contents of an array

We need to specify index number to retrieve an element from array, The Powershell array elements starting at 0th index.

Display all the elements in an array:
This command returns the first element in an array:
This command displays the 2nd,5th,8th elements
Return the range of elements (4th element to the 8th element):
Return the last element in an array:

Contains check in array

If you want to find an array contains a certain value, you don’t have to iterate through elements to compare the values with search term. Instead, you can apply filter with various comparison operators directly to the array.
$myArray = "A","B","C","Hello","World"
This command would check and return the array elements contains the string "Worl".
$myArray -like "*Worl*"
This command would check if the first three array elements contains the string "B" and return values.
$myArray[0..2] -like "*B*"

Set or Update array values

Use the assignment operator (=) to change or update values in an array.

Sort an elements

You can simply sort the elements by using Sort operator.
$myArray = $myArray | Sort

Delete an array and elements

You can easily delete an entire array object by setting its value as null
$myArray = $null
But Arrays are fixed-size, so, you can not easily remove values at different indexes. For this need, you need to use System.Array or System.Collections.Generic.List.

Monday, 30 January 2017

OneDrive for Business Storage Report using Powershell

You may need to see how much space your users are using in OneDrive for Business storage and need to ask them to free up space if they are getting close to your storage limit. We can retrieve the list of users with OneDrive feature provisioned by using SharePoint Online UserProfileService with Powershell.

Steps to Export OneDrive for Business Size Report:

  • Fetch all SharePoint Online users using UserProfileService.
  • Find if OneDrive for Business is provisioned or not.
  • Find Current Size and Storage Limit details.
  • Export Size and Storage Quota details to csv file.
Note: Replace the variable <your tenant name> with your Office 365 tenant name in all the occurrences and provide your own admin credentials.
# Specify your organization admin central url 
$AdminURI = "https://<your tenant name>"

# Specify the User account for an Office 365 global admin in your organization
$AdminAccount = "admin@<your tenant name>"
$AdminPass = "admin_password"

$loadInfo1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$loadInfo2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$loadInfo3 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")

$sstr = ConvertTo-SecureString -string $AdminPass -AsPlainText -Force
$AdminPass = ""
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminAccount, $sstr)
$UserCredential = New-Object System.Management.Automation.PSCredential -argumentlist $AdminAccount, $sstr

# Add the path of the User Profile Service to the SPO admin URL, then create a new webservice proxy to access it
$proxyaddr = "$AdminURI/_vti_bin/UserProfileService.asmx?wsdl"
$UserProfileService= New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False
$UserProfileService.Credentials = $creds

# Set variables for authentication cookies
$strAuthCookie = $creds.GetAuthenticationCookie($AdminURI)
$uri = New-Object System.Uri($AdminURI)
$container = New-Object System.Net.CookieContainer
$container.SetCookies($uri, $strAuthCookie)
$UserProfileService.CookieContainer = $container

# Sets the first User profile, at index -1
$UserProfileResult = $UserProfileService.GetUserProfileByIndex(-1)
Write-Host "Starting- This could take a while."
$NumProfiles = $UserProfileService.GetUserProfileCount()
$i = 1

Connect-SPOService -Url $AdminURI -Credential $UserCredential

# As long as the next User profile is NOT the one we started with (at -1)...
While ($UserProfileResult.NextValue -ne -1) 
Write-Host "Checking profile $i of $NumProfiles"
# Look for the Personal Space object in the User Profile and retrieve it
# (PersonalSpace is the name of the path to a user's OneDrive for Business site. 
# Users who have not yet created a  OneDrive for Business site might not have this property)
$Prop = $UserProfileResult.UserProfile | Where-Object { $_.Name -eq "PersonalSpace" } 
$Url= $Prop.Values[0].Value
# If "PersonalSpace" exists, then OneDrive Profile provisioned for the user...
if ($Url) {
$siteUrl = "https://<your tenant name>"+ $Url.Substring(0,$Url.Length-1)

# Find size and storage limit
$temp = Get-SPOSite $siteurl -Detailed
$Result += New-Object PSObject -property @{ 
UserName = $temp.Title
UserPrincipalName = $temp.Owner
Size_inMB = $temp.StorageUsageCurrent
StorageQuota_inGB = $temp.StorageQuota/1024
WarningSize_inGB =  $temp.StorageQuotaWarningLevel/1024
# And now we check the next profile the same way...
$UserProfileResult = $UserProfileService.GetUserProfileByIndex($UserProfileResult.NextValue)
$Result | FT
You can also export the output into csv file:
$Result | Export-CSV "C:\\OneDrive-for-Business-Size-Report.csv" -NoTypeInformation -Encoding UTF8