February 7, 2019

Multithreading in PowerShell & Exchange Online (Office 365)


Challenge:
The details of a few (around 300) users' mailbox in Exchange Online were to be fetched, and the approach is via PowerShell. Now, the total users were over 3800, and to filter from those, consumed a lot of time. As a result, going the conventional way of getting those one-by-one took us 39 seconds per user which was around 3.5 hours for the whole script execution.  

Resolution:
We had to find another way to get this done. So, we chose the approach of getting multiple records simultaneously, using background processes. 

And, multi-threading came to the rescue!!

We created the connection to Exchange Online via PowerShell:
$Credentials = Get-Credential

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri  https://outlook.office365.com/powershell-liveid/ -Credential $Credentials -Authentication  Basic -AllowRedirection

Import-PSSession $Session 

Then, we read the user display names from the file, and stored them in an array. 
$accounts = Import-CSV C:\Temp\File.csv

Now, instead of specifying the number of jobs, we would want the jobs to be automatically created.

So, we would be specifying, the batch size of each job. In our case, we chose 50 users per batch.

$accountsperBatch = 50

Then, we iterated the loop for all the accounts to be split into batches as jobs, and then started the job using Start-Job for creating the job. 

This Start-Job  needs:

1. ScriptBlock in order to job to know, what it has to do.
2. ArgumentList in order to job to know, the items using which the job is to be performed.    

On specifying this, PowerShell would begin the creation of jobs, and as the job is created, the code within the ScriptBlock is executed.  
$accountsperBatch = 50
$i = 0
$j = $accountsperBatch - 1
$batch = 1
$csvContents = @() 
  
while ($i -lt $accounts.Count)
{
 $accountBatch = $accounts[$i..$j]
 
 $jobName = "Batch$batch"
 $fileName = "c:\Temp\Details$jobName"
 Start-Job  -Name $jobName `
       -ScriptBlock {
         param([string[]] $accounts)
  foreach($account in $accounts)
  {
   $mailBoxDetail = Get-Mailbox  -Identity  $account | Select  DisplayName, UserPrincipalName 
   $row =  New-Object System.Object
   $row | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value  $mailBoxDetail.DisplayName
   $row | Add-Member -MemberType NoteProperty -Name "UserPrincipalName" -Value  $mailBoxDetail.UserPrincipalName

   $csvContents += $row  
  }
                $csvContents | Export-CSV $fileName
             }`
      -ArgumentList (,$accountBatch)
     
 $batch += 1
 $i = $j + 1
 $j += $accountsperBatch
 
 if($i -gt $accounts.Count) {$i = $accounts.Count}
 if($j -gt $accounts.Count) {$j = $accounts.Count}
}

Then, as per the best practices, we would remove the jobs completed by using Remove-Job  and the PS Session using Remove-PSSession $Session. 

This script helped us to generate the details of the user accounts simultaneously and the results improved drastically and the results were available under 1.5 hours.

Note: If we open too many connections with Office 365, it would suspend the connections, as the security mechanism at Office 365 would consider this as a DDoS attack, thus, giving us an error like remote host not found or the connection was closed. 

If you have any questions you can reach out our SharePoint Consulting team here.

September 5, 2017

Uninstall SharePoint 2013 - One or more required office component failed to complete successfully.

Issue:
While uninstalling SharePoint Server 2013, you may get below error message.

Error:
"One or more required office component failed to complete successfully. For more information, consult the setup log file." as shown in below screenshot.
 

Resolution: To fix the issue follow below steps:
 
1. Go to your Database Server.
2. Go to Services section:- Go to Run (Windows + R) and type "services.msc".
3. Stop the following services:
  • SQL Full-text Filter Daemon Launcher (MSSQLSERVER)
  • SQL Server (MSSQLSERVER)
  • SQL Server Agent (MSSQLSERVER)
  • SQL Server Analysis Services (MSSQLSERVER)
Again go to Control Panel and uninstall SharePoint 2013, you will not get this error this time.

In case, if you reinstall SharePoint server, do not forget to restart all those services.

If you have any questions you can reach out our SharePoint Consulting team here.

September 1, 2017

Office 365 - Exchange Online: Allow specific External Domian Users to send emails to Distribution Groups

Problem Statement:
We came across a requirement to create a Distribution Group where -
1. Users from internal organization can send emails to this Distribution Group.
2. External Users ONLY from partner organization domain can send emails to this Distribution Group.

Distribution Groups in Exchange Online provides a functionality to restrict External Users to send emails. But here, in this case, we need to allow users from one External Domain (let's say domain is demowork.xyz) to send emails to Distribution Group.

Domain based sender filtering is NOT directly available when we create the Distribution Group, but we can achieve this requirements by creating a Transportation Rule in Exchange Online.

Resolution:
We can use Transportation Rule to restrict a Distribution Group to receive emails from internal organization and specific external domain only. Steps to create a new Distribution Group/Distribution List(DL) and configure the Transportation Rule for sender domain restriction are summarized below:

A. Create Distribution Group:
1. Login to Exchange Control Panel (ECP).
2. Navigate to "Recipients" -> "Groups".
3. Click "+" icon and select "Distribution Group".
4. Click "To create a new distribution group, click here" option (as highlighted in below screenshot) from newly opened window:

5. Populate the required information to create new group:
  • Display Name: Desired Group Name (We will name this as "Helpdesk" in this example).
  • Alias: Desired Group Alias Name (We will keep this as "Helpdesk" in this example).
  • Email Address: Desired email address for group (In this example, it is like "helpdesk@binaryrepublik.com")
  • Add Owners and Members of the group as needed.
  • Select Group Membership options as needed. We will select "Closed" for both the options - (1) Choose whether owner approval is required to join the group. (2) Choose whether the group is open to leave.
  • Click "Save".
6. This newly created Distribution Group by default accepts emails only from senders within organization. So, we need to apply a change for this Distribution Group to accept emails from Outside of organization. In order to enable this -
  • Select this Distribution Group and Click Edit icon.
  • Go to "Delivery Management" in newly opened window.
  • Select "Senders inside and outside of my organization" option and click "Save".
7. Now, we have a group created that accepts emails for senders from inside and outside organization (any sender from any domain).

Now, We have to create a Transportation Rule to restrict this Distribution Group to receive emails only from senders inside organization and from specific partner domain (e.g. demowork.xyz).

B. Create Transportation Rule:
1. Go to Exchange Control Panel -> Mail Flow -> Rules.
2. Click "+" icon and select "Create a new rule".
3. Click "More Options" at bottom of the newly opened window.
4. Furnish the information to create new rule -
  • Name: Meaningful name for the rule (e.g. - Helpdesk Restriction)
  • Apply this rule if -> select "The message..." -> "To or Cc box contains this person".
  • Select newly created DL and click OK. (In this example, we will select "Helpdesk").
  • Do the following -> "Block the message..." -> "Reject the message and include an explanation". Specify the desired explanation like "This email address is only for specific people. You are not allowed to send emails to this address" and click OK.
  • Click "add exception" under "except if" section.
  • Select "The sender..." -> "domain is"
  • Add internal organization domain (in this example, binaryrepublik.com) and partner domain (in this example, demowork.xyz) and click OK. Basically, here we need to define domains of allowed senders.
5. Click "Save".

The Distribution Group & Transportation Rule is configured.

Conclusion:
This way, using Transportation Rule, we can allow a Distribution Group in Exchange Online to receive emails only from senders of specific domain(s).

If you have any questions you can reach out our SharePoint Consulting team here.