Category Archives: Scripting

Everything related to Scripting, PowerShell, Pyton. etc

Powershell script to audit users who authenticated against DC servers

The story:

I have got a request from a client asking to find out which server(s) is using which domain admin or a highly privileged account as a service.

To find this I already wrote a powershell script that does this, Search the non standard/(Domain only users) and show the services and name of the servers where those accounts are configured on utilizing Remote powershell to do so and the use of a Domain Admin user.

You can refer to this link to see this article by clicking here

Creating the script process:

The same client wanted to also know which of those accounts did authenticate and wanted to know from which server/Computer did the request originate from and to which DC did it go.

I have started thinking of the process of doing so by again utilizing remote PowerShell to check against certain security events on AD to check which user among the Domain admin members did authenticate.

After sometime and with the help of some forums I managed to get script ready which looks in all Domain Controllers for users that are members of the Domain Admin groups who triggered an event ID 4624 and from which Computer did this request came from.

The Script :

# Get domain admin user list
$DomainAdminList = Get-ADGroupMember -Identity 'Domain Admins'
# Get all Domain Controller names
$DomainControllers = Get-ADDomainController -Filter * | Sort-Object HostName
# EventID
$EventID = '4624'
# Get only last 24hrs
$Date = (Get-Date).AddDays(-3)
# Limit log event search for testing as this will take a LONG time on most domains
# For normal running, this will have to be set to zero
$MaxEvent = 100

# Loop through Dcs
$DALogEvents = $DomainControllers | ForEach-Object {
    $CurDC = $_.HostName
    Write-Host "`nSearching $CurDC logs..."
    Get-WinEvent  -ComputerName $CurDC -FilterHashtable @{Logname='Security';ID=$EventID;StartTime = $Date} -MaxEvents $MaxEvent |`
    Where-Object { $_.Properties[5].Value -in $DomainAdminList.SamAccountName } |`
    ForEach-Object {
        [pscustomobject]@{SourceIP = $_.Properties[18].Value; SamAccountName = $_.Properties[5].Value;Time = $_.TimeCreated;LogonEventLocation = $CurDC}

How to run:

The Script must be run on DC with a privileged account in order to get the write results, The default time interval is set to 3 days but you can choose to increase that.

You can also change the default group where you want to search for members by changing Domain Admin groups to something else.

Screenshot of the result

Slow Migration – Office 365

The story:

In office 365 when you’re working on Exchange 2010,2013, 2016 or 2019 in a hybrid environment things might look easy but in a big enterprises where Internet security is something being taken into account very seriously. It might cause many issues that you don’t expect at all.

One of my clients whom I was doing Exchange Migration for had an issue with the Migration. The error was as follows:

Error occurs after Office 365 Exchange online connects to Exchange on-premises 2010 mailbox server

Error in Office 365

         : 20.

                                           27.04.2016 08:03:17 [DB3PR05MB0778] Transient error DataExportTransientExcep

                                           tion has occurred. The system will retry (2/1280).

                                           27.04.2016 08:04:53 [DB3PR05MB0778] The Microsoft Exchange Mailbox Replicati

                                           on service ‘’ (15.1.466.25 caps:03FFF

                                           F) is examining the request.

                                           27.04.2016 08:04:55 [DB3PR05MB0778] Connected to target mailbox ‘lcwonline.o

                                 \ec96e315-1059-4710-b358-1c4b42f3edeb (Primary)’, database ‘EU

                                           RPR05DG049-db131′, Mailbox server ‘’

                                           Version 15.1 (Build 466.0).RequestExpiryTimestamp                   : 03.04.2116 07:42:38

ObjectState                              : New


To troubleshoot issues, You need to put so many things into account! The architecture of the infrastructure of where you are doing the project is very important and the need of knowing how things are working matters.

Things that could always come in mind and handy are what you will need to start your troubleshooting:

– Bandwidth Limitations or Performance:

– Exchange Configuration (MRS)

To troubleshoot the MRs, You need to know what kind of error you’re getting and to see this you can use the following powershell after you connect to Office 365 powershell.

Get-MoveRequest {email} | Get-MoveRequestStatistics -Diagnostic -IncludeReport | Export-Clixml c:\logfile.xml

The resultant report will reveal the error and shows you where is the exact culprit.

– Disk Latency
– Firewall Configuration (IPS/IDS)

From Exchange 2016 to 2019 or 2013 to 2016 The transient error might be related to MRSProxy or at least this is the case with me 90% of the time. To resolve this issue you will need to change the MRSProxy values on the target server and depending on the error might also be the Source server too.



1. Some instability was detected in communications as well as saturation by the size of the link.
2. The procedure to increase the timeout for the service through the file MRSProxy

File: MsExchangeMailboxReplication.exe.config

Object / line: DataImportTimeout.

New Value: 00:10:00


New Configuration



The Story (Finding Domain Joined Servers Services users)

If you’re wondering which of your servers are using domain joined account or a non regular account like network service or system. You will need to go through every server’s service console and check that one by one but thanks to PowerShell this job was made like a piece of cake.


The requirement to run this script is a domain admin account since the PowerShell will require access to other servers using Remote PowerShell using Invoke command and run a Get-WMIObject script to find out those details. So in short I will write the required things for this to work

1- Logged in to Active Directory (In order for AD PowerShell module to run and find computers).

2- Domain admin account (To run the remote PowerShell on other servers and get service details)

3- Firewall for domain joined computers is open (To allow remote PowerShell to work) or have remote PowerShell enabled via GPO.

The Script will also show you the offline (inaccessible servers) and will state those servers as down as you can see in the screenshot below.

The script will also prompt you for a path to save the output. You can enter something like C:\Services.csv  as soon as you type the file path and extension it’ll be opened using Notepad.


#Check servers down and get services from the responsive servers

$Computers = Get-ADComputer -Filter { OperatingSystem -Like ‘*Windows Server*’}

$Input = ForEach ($computer in $computers){

$comp = $Computer.DNSHostName

$dist = $Computer.DistinguishedName

if (Test-Connection -Computername $comp -count 2 -Quiet )


Invoke-Command -ComputerName $comp -ScriptBlock {Get-WmiObject win32_service | where {$_.StartName -notlike “*LocalSystem*” -and $_.StartName -notlike “*LocalService*” -and $_.StartName -notlike “*NetworkService*” -and $_.StartName -notlike “*System*”} | select DisplayName,StartName,State }}

else{ Write-host $comp is down -foregroundColor red -BackGroundColor black



$Output = Read-Host “Enter File path and Name to save output to”

Out-File -FilePath $Output -InputObject $Input -Encoding ascii

Notepad $Output



Windows 10 powershell’s Linux sudo apt-get install like CMDlet with Chocolately app

The Story

Windows 10 has arrived finally and with it came lot of new features, and one of my favorite new features is that you can finally install applications through powershell just like Linux OS’s terminal window command (apt-get install).

Although the command is still pretty new and lack many repositories where you can find and install applications from.

There’s already some people who are working on adding sources of applications which you can test initially before Microsoft asks product companies to start making their own repositories so Powershell can trust these sites and applications.

One of the sites that are working on providing Windows 10 with repositories is which provides hundreds of softwares that can be installed through PS.

To install Chocolately repository simply do the following

Open powershell as an administrator and paste the following cmdlet

@powershell -NoProfile -ExecutionPolicy Bypass -Command “iex ((new-object net.webclient).DownloadString(‘’))” && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin


Then this

iex ((new-object net.webclient).DownloadString(‘’))



As soon as you have installed chocolately, you will get a new huge list of applications that can be installed with a very simple and short cmdlet as in the below screenshots.

The good things about these cmdlets is it can be used to deploy an app for a huge number of clients by simply running the script through GPO or batch file.

I am going to install VLC and Google drive on my computer using these cmdlet …


Find-package -Name VLC







Checking if the app is really installed or not?



Find and install google drive package






If an application doesn’t install, how to troubleshoot it?

If for instance you were trying to install a package or app and that doesn’t work or get stuck then you can navigate to the Chocolately directory and delete any package that you tried to install but were suspended for any reason.



You can simply delete the whole directory or the file that ends with extension .nupkg and try again to install…


Useful Powershell script to resolve the X500 address

In migration, Powershell can be a very crucial tool to achieve success and finalize projects within deadline or even fix issues.

During the time of working with Exchange we had lots of issues with users not able to send an email to their migrated colleagues due to some issues with contacts which was caused by the Legacy Exchange DN not being migrated with the user or lost due to some wrong deletion.

Once users try to send an email to that particular user with the missing Legacy Exchange DN. The receiving Exchange server will result an error and send it to the user as NDR message explaining to them that the error is due to not finding the particular address.


The solution to this particular problem is very simple especially if it’s couple of users however to resolve the address you’ll need to google and understand the language that Exchange server users to match the original used address in the missing user’s attributes.

The below script would work accordingly with whatever situation that faced me and it became very handy to me.

How to use:

1- Copy the script to a notepad and save as convert.ps1 on Desktop

2- Run script and try to type in powershell convert-X500 then hit enter.

3- Copy and paste the address you got from the error message above.


Once you copy and paste hit enter and you’ll get the final result


Note: Make sure you remove the @domain.local in the end

Function Convert-X500{ # Define the Legacy Exchange DN here

Write-Host “”Enter your X500 Address here…”” -ForegroundColor Green -BackgroundColor Black

$X500Source = read-host

# Converts the various strings to the proper syntax

$X500 = $X500Source.Replace(“_”, “/”)

$X500 = $X500.Replace(“+20″, ” “)

$X500 = $X500.Replace(“IMCEAEX-“, “”)

$X500 = $X500.Replace(“+28”, “(“)

$X500 = $X500.Replace(“+29”, “)”)

$X500 = $X500.Replace(“+2E”, “.”)

$X500 = $X500.Replace(“+5F”, “_”)

$X500 = $X500.Replace(“@YourDC.localHere“, “”)

Write-Host X500:$X500}

Preparing, Migrating users and Handling contacts between two forests in Microsoft Exchange Cross Forest migration

This article presumes that you have setup all the initial steps for the Cross Forest migration to work:

– Configure DNS resolution and trust between two AD forests.

– Create and configure Send connector between and

– Create and configure Availability service between and

– Configure as accepted domain in

– Install and configure ADMT server at the target domain

– Install and configure Password Encryption Server (PES) on the source domain

– Configure MRSProxy on Source and Target CAS Servers (Enabling MRSProxy, Increase limits..etc.).

– Configured Public Certificates between both CAS Servers or installed self signed CA certs.


In order for two Cross forest Exchange users to send an E-mail to one another before or during Cross forest migration; Each forest have to have the other forest’s users as external contacts on their Exchange environment to ease the finding of any particular user in that other organization and avoid X500 errors after the migration.

During the migration this process is critical and very important to be up to date in order to not mess users included in distribution groups before, during and after user migration from source to target forests.

For Cross forest user migration, User has to be prepared via Microsoft’s own prepare-moverequest Powershell which is included in the $Exscript directory that prepares the target user’s attributes (Before or after ADMT copy) for the migration using the Powershell script new-moverequest.

However, before that user is migrated and before doing the prepare move request the user must have their user object mail user enabled in order to get all the proper attributes for the move request to work which means the Contact has to either be deleted or lose the SMTP which is goin to be enabled on the mail enabled user.

For this process and in a big environment a tool, 3rd party or a script must be used to hasten the migration of users otherwise it would take ages and would be a very problematic process.

User Creation:

Using ADMT then Prepare-Moverequest script

Starting with the creation of target user using ADMT or by Prepare-MoveRequest Script, If ADMT is used prior to PrepareMoveRequest. The target user will have exchange attributes migrated and mail-user enabled by default but due to some incomplete or incorrect attributes the user will most probably have a corrupted mail user object that needs to be disabled and re-enabled with the proper mail address.

Using Prepare-MoveRequest before ADMT

In the case of using Prepare-Moverequest the user will be created in the target forest properly without any issue but will not have their SIDHistory copied so after creation of the user account ADMT must be used to copy user’s SIDHistory with Exchange attributes excluded.


– This method has an advantage over using ADMT first, User don’t have to create a new outlook profile in order to use their target mailbox after migration.

– You don’t have to mailenable user.

Mail Enabling User:

The first step for the migration to work is to Mail enable user in the target forest. Assuming you have a user called the user gets his AD Object copied to the target forest with ADMT and user gets his UPN changed from to tim@target.localautomatically, still user will get his SIDhistory and the Groups he’s in if groups are migrated prior to that however, in some rare cases that I have seen while doing this kind of project the SIDHistory might not get copied and you might not notice that unless you take a very close look at the log that ADMT is generating for you, In the script I am attaching below and prior to preparing the user for migration I added a script to bulk check user list for SIDHistory. The script below will disable mailuser that’s migrated with ADMT and show you their SIDHistory attribute in order to double check before you migrate their mailbox.

$Users = import-csv -path “C:\List\List1.csv”

foreach ($User in $Users)


$Identity = $User.Alias

$UIdentity = $User.Sam

$Mail = $User.Proxy

$NProxy = $User.NewProxy

#Before Migration, Show if user has SIDHistory or Not, If not don’t migrate User

$UserSID = dsquery * -filter “&(objectcategory=user)(samaccountname=$Identity)” -attr objectsid sIDHistory

Write-host User $User.Alias has $UserSID -ForegroundColor Green -BackgroundColor Black

The CSV file format for this powershell should be as following, I will explain why in detail below




In order for the Prepare-Moverequest to work we will have to MailUser enable this user by using the following script

Enable-Mailuser –Identity SamAccountName –ExternalAddress PrimarySMTPAddress

Enable-Mailuser –Identity Tim –

In this case user will be ready for the prepare moverequest script to work and get his source Exchange attributes to be copied to the target one.

Prepare-MoveRequest for Single mailbox:

The Prepare-Moverequest powershell is pretty easy to use for a single user and all you need is to enter target and Remote credentials in a variable to use it with the command.

Once you use the script it’ll copy the source user and their Exchange attributes including Proxy Addresses, it’ll convert the LegacyExchangeDN into X500 address in the target user’s mailbox object so users in the source forest wont get any cache issue reaching to the migrated user and will set other attributes like Displayname, MailNickName..etc like in the screenshot below.

Script is as the following

$TargetCredentials = Get-Credential

$RemoteCredentials = Get-Credential

.\Prepare-MoveRequest.Ps1 -Identity -RemoteForestDomainController “SourceDCHostname.SourceDC.local” -RemoteForestCredential $RemoteCredentials -LocalForestDomainController “TargetDCHostname.TargetDC.local” -LocalForestCredential $TargetCredentials -TargetMailUserOU “OU=DestinationOU,DC=TargetDC,DC=local” -UseLocalObject -OverwriteLocalObject –Verbose


Prepare-MoveRequest for Bulk mailboxes:

For bulk users the script is simpler but for it to work you’ll need to prepare a CSV file that meets the requirements of the powershell script.

Bulk Users Script:

cd $exscripts

Write-Host “Starting to Prepare-MoveRequest for users in your CSV List….” -ForegroundColor Green -BackgroundColor Black

Import-Csv C:\Identity\Identity_1.csv | .\Prepare-MoveRequest.ps1 -RemoteForestDomainController “SourceDCHost.SourceDC.local” -RemoteForestCredential $RemoteCredentials -UseLocalObject -OverwriteLocalObject –Verbose

CSV Example:




–Moving Users

Moving Single Mailbox:

After preparing the Move request, The only thing left to do is to move users. This process is pretty easy and only one script line is used.

[PS] C:\Exchange 2010\scripts>New-MoveRequest -Identity “” -RemoteHostName “” -Remote -RemoteCredential $RemoteCredentials -TargetDatabase DestinationDB1 –TargetDeliveryDomain


Moving Multiple Mailboxes:

Import-Csv C:\Identity\Identity_15.csv | New-MoveRequest -RemoteHostName “” -Remote -RemoteCredential $RemoteCredentials -TargetDatabase CEDB12 -TargetDeliveryDomain

CSV Example:



Once the list is ready and you run the powershell script the target CAS server would connect to the source CAS and start migration as in the following screenshot.


Once users migration is finished, On the source forest user will be converted to MailUser so non-migrated users in the source forest will still be able to send emails to this user however, The Groups on target forest must be manually maintained and updated with users that are being migrated.


– Contacts Issue

In the target forest those two migrated users were already contacts there prior to migrating them and thus Target forest users who have sent those two users email have the LegacyExchangeDN Address of those contacts cached in their Outlook in X500 format which will create an issue if those contacts are deleted without exporting their LegacyExchangeDN and add it to the migrated users’s ProxyAddress Attributes.

Prior to deleting those contacts, From the Target forest I have exported their info to CSV with the following attributes.

Name, Alias, PrimarySMTPAddress and LegacyExchangeDN Attribute using the following powershell script

Get-MailContact -result unlimited | where {$_.PrimarySmtpAddress -like*} | select Name,Alias,Primarysmtpaddress,legacyExchangeDN | Export-Csv c:\TargetContacts.csv -notypeinfo -encoding utf8

The PowerShell will export contacts in the following format and in order to import them you’ll need to bulk edit the file using Notepad or Notepad++


In notepad replace “/o= with X500:/o=


and Replace all “ with nothing


After you save the file in the target forest, Only in the condition of migrating Source users to the target forest use the following script to Import those users’ LegacyExchangeDN as X500 to their migrated Mailbox objects.

Import-CSV “C:\TargetContacts.csv” | foreach{Set-Mailbox -identity $_.Name -EmailAddresses @{add=$_.LegacyExchangeDN}}

Hope this helps and if you have any questions in mind please don’t hesitate to contact me at or call me 320-200-9663.

Mohammed JH

Get all mailbox Exchange Servers IP address remotely

Sometimes while we do Exchange projects in big environments where there more than 10 or 15 servers we need to quickly get a particular server’s hostname or IP.

I created a simple PowerShell script that does the work for you

#Get all mailbox Exchange Servers IP address remotely

#Import Exchange Management Shell if ran from PowerShell

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn

# Find Mailbox Server Roles

$Servers = Get-ExchangeServer | Where-Object {$_.Serverrole -eq “mailbox”}

# Print Servername and IP

foreach ($Server in $Servers) {Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName $Server | Select-Object -Property IPAddress,PsComputerName,Name}


Exchange 2010 CrossForest group Migration

In an Exchange Crossforest migration the distribution groups can be a very painful operation that would cause loss of time, lots of issues and continues headache if not solved within a timely manner.

The migration can be a long boring process that needs to be as accurate as possible to avoid any issue related to members in the group or/and Group’s Primary SMTP details.

While doing a Crossforest migration I came through through this headache and tried to seek a script that would satisfy my migration’s requirements but only thing I found is the exportPowershell made by Satheshwaran Manoharan.

Export Process:

The script exports all groups and their members from the source forest, but to import there’s no option and I had to write my own script.

To make use of this script first make sure you that you have migrated the Groups with ADMT in the recommended order otherwise the migration would be problematic.

  • First: Universal Groups
  • Second: Global Groups
  • Third: Domain Local Groups

Once groups are migrated to the target forest you can check how they look like through Exchange management shell and whether they have members added or SMTP address set.


After I checked it apparently shows that group is empty and has no Primary SMTP address associated with it.

Import Process:

In order to add members during the migration since this is a Hybrid/Coexistence migration not cutover, It took time to migrate users and therefore I have to add non-migrated users in target forest as External Contacts to the Distribution Groups and add migrated users as Mailbox users.

Then after adding the users I have to setup Primary SMTP address for the groups according to the exported CSV file from the Source Forest.


To Import users, I had to setup a CSV file with the following format:

In this format, the Display name, Alias, RecipientType and PrimarySMTPAddress belong to the User object that’s included in the group meanwhile, The Dgroup is the Distribution group’s Alias and DGSMTP is the Group’s Primary SMTP address.


The following script imports groups members to their relative groups


# If user type is Usermailbox then it’ll be in Target forest as a Contact #


$Users = Import-Csv “C:\Groups\dgs.csv”

Foreach ($User in $Users){

$GroupAlias = $User.Dgroup

$GroupSMTP = $User.DGSMTP

Write-Host “$User.Alias” has been Added to the Group $User.Dgroup -ForegroundColor Green -BackgroundColor Black

if ($User.RecipientType -Match “UserMailbox”){

Add-DistributionGroupMember -Identity $GroupAlias -Member $User.PrimarySMTP -BypassSecurityGroupManagerCheck}}

Fixing Distribution Groups Primary SMTP Address:

Since distribution groups are mostly imported without Primary SMTP address through ADMT then we’ll have to also make sure that we fix this for our groups, but what if the destination forest has similar groups or the SMTP is used already ? In order to avoid any mistake when associating the Primary SMTP address I have created a script that would check distribution groups with null value in their primary SMTP Address and copy the SMTP address to these groups avoiding any overwrite or change of the destination Distribution groups.


# Setup groups with Primary SMTP Address


$Groups = Import-Csv “C:\Groups\Group_test.csv”

Foreach ($Group in $Groups){

$GroupAlias = $Group.dgroup

$GroupSMTP = $Group.DGSMTP

if ((Get-DistributionGroup $GroupAlias | %{$_.PrimarySmtpAddress}) -match “$GroupSMTP”) {

Write-Host Group $GroupAlias already has $GroupSMTP Setup as primary SMTP address -ForegroundColor Yellow -BackgroundColor Red}else{

Set-DistributionGroup -Identity $GroupAlias -PrimarySmtpAddress $GroupSMTP -EmailAddressPolicyEnabled $False

Write-Host Group $GroupAlias has $GroupSMTP Setup as primary SMTP -ForegroundColor Green -BackgroundColor Black }}

The script will check if the groups has primary SMTP matches the one in the CSV file, if it doesn’t it’ll setup the primary SMTP address for that group with green color like in the below screenshot


You can use this script with the same CSV file that you will use for adding members to the groups too , If groups SMTP exists already you’ll get the following error



Attached below, You can find the new version of the powershell and the CSV along with it.

Useful Powershell Cmdlets

Export users licenses and information O365

In order to Export users licenses and information from Office 365 you will have to use the following script.

First you will need to connect to MS Online service with a Global admin account


Get-MsolUser -All |Where {$_.IsLicensed -eq $true } |Select DisplayName,UsageLocation,@{n=”Licenses Type”;e={$_.Licenses.AccountSKUid}},SignInName,UserPrincipalName,@{n=”ProxyAddresses”;e={$_.ProxyAddresses}}| Export-csv -Path C:\ExportlicenseUsage.csv –notype


This will export a file called “ExportLicenseUsage.csv” to your C root drive. you can open this file with Microsoft Excel and find out all the useful information that you’re looking for.

Hope this helps

Testing Office 365 SMTP relay

In order to test Office 365 SMTP relay you will have to create a user with an Exchange online license. After the email is activated for this user you can test this user for relay with the following powershell.

First connect to Microsoft Online service with this user that you’ll be using for relaying.

$msolcred = Get-Credential

Next edit the following powershell with the user’s e-mail and the recipient’s too

Send-MailMessage –From –To –Subject “Test Email” –Body “Test SMTP Relay Service” -Credential $msolcred -UseSsl -Port 587


This test is known as Client SMTP submission you can also use a different method for multiple devices where you can configure them all to point to a single server (IIS) in a method known as IIS for relay with Office 365 however, all the methods what involve office 365 (Only) for relay will require a user with Exchange online license assigned to it.

Search for users start with particular letters in the display name

Mohammed Hamada 5:49 AM Exchange Online , Office 365 , Office365 , Powershell

To search your Office 365 users with particular initial characters

First connect to Microsoft Online Service

To Search for users whom their display names contain “Top” you can use the following powershell

get-msoluser -all | where-object {$_.displayname -like “top*”} | ft displayname,userprincipalname,proxyaddresses


Search for users whom their UPN contains “TOP” in the start

get-msoluser -all | where-object {$_.userprincipalname -like “top*”} | ft displayname,userprincipalname,proxyaddresses


Office 365: Add additional accepted domain to SMTP Address

Mohammed Hamada 5:50 AM Exchange Online , Office 365 , Office365 , Powershell

If you have configured Hybrid integration between Exchange 2010/2013 with Office 365 using dirSnyc or Azure active directory sync tool and then stopped the synchronization. The accepted domains and additional domains will be removed from the user’s Attributes on the cloud and in order to add these accepted domains again to all of the Office 365 users..

First we’ll have to connect to Exchange online with the following powershell tool. so Launch Azure powershell as Admin and copy the following line by line.

1- $UserCredential = Get-Credential

2- $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri -Credential $UserCredential -Authentication Basic -AllowRedirection

3- Import-PSSession $Session


First we’ll show/view user’s existing SMTP addresses, in order to do so we’ll use the following PowerShell cmdlet

For all users

4- Get-Mailbox | fl –property Alias, WindowsLiveID, EmailAddresses

For one user

Get-Mailbox –Identity | fl –property Alias, WindowsLiveID, EmailAddresses


Procedure to add an additional accepted domain to all users in the Office 365 tenant.


The domain must be verified on Office 365 first before applying those steps


$users = Get-Mailbox


foreach ($a in $users) {$a.emailaddresses.add(“smtp:$($a.alias)”)}




$users | %{Set-Mailbox $_.Identity -WindowsEmailAddress $_.WindowsEmailAddress}