Category Archives: Exchange Online

AADSTS165000 after enabling Modern Auth in Exchange Online

If you enable Modern Auth in Exchange Online with Set-OrganizationConfig -OAuth2ClientProfileEnabled $true , and then start seeing this error in Office 2016 or 2013 clients:

AADSTS165000: Invalid request: the request tokens do not match the user context. One or more of the user context values (cookies; form fields; headers) were incorrect or invalid, these values should not be copied between requests or user sessions; always maintain ALL of the supplied values across a complete single user flow. Failure reasons:[Token is invalid;]

You need to re-activate Office.

Copy local AD contacts to O365

Recently I needed a basic method to copy over contacts from a local AD to O365, and in cases where a read-write contact already exists; update it. The scenario made sense, as we were working with multiple source AD’s where some had contacts of each other’s mail users, causing adsync conflicts. Thus we decided to take contacts out of ADsync scope and just copy them once.

The logic of the attached script is as follows:

 

 

 

 

 

 

 

 

Note that the script ONLY imports the displayname, primary and all secondary email addresses, and sets an extra X500 address for the legacy exchangeDN to avoid outlook cache hit misses.

If you need it, here’s a download link:

O365ContactImporter.ps1

Removing .onmicrosoft.com and .mail.onmicrosoft.com aliases from all groups, users and contacts in your Active Directory

My current customer had a little dabble in Office 365, they set up their Hybrid configuration and added their @xxx.onmicrosoft.com email alias to all their users and groups. This mostly happens automatically.

They then later decided to go with a new, different Office 365 tenant for production purposes, the old tenant was dismantled and the AADConnect server was deleted.

However, all AD objects still had their alias for the old Office 365 tenant, syncing that to the new tenant would be a bad idea and I cleaned that up just to be sure it wouldn’t cause trouble in the future, here’s how I did that:

cleanupAllADObjectProxyAddresses.ps1

O365GroupSync beta release

O365GroupSync is a tool that I am building for a large global NGO, because AADConnect creates Read-Only objects in Office 365.test

Read-Only objects cannot be edited in Office 365, thus users are unable to edit distribution lists in Office 365’s Outlook Web Accress (OWA) even if they are managers of said lists.

O365GroupSync was built to take over the synchronisation and initial seeding of all distribution lists, both ways, to allow users to edit distribution lists while in a hybrid Office 365 Exchange Online scenario, both on premises and in the cloud.

This beta version has been tested, but is not yet running in any production environments.

Get it here

Programmatically enabling or disabling the Unified Audit Log in Office 365

For our enrollment process of customers in Office 365, we enable the Unified Audit Log by default, as this has a great number of benefits.

At first, the only way to do this was through the UI, but now we can enable the Unified Audit Log with the following  Powershell command in the Exchange Online Remote Shell:

Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled:$True

Or to disable the Unified Audit Log through Powershell:

Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled:$False

Note that disabling the Unified Audit Log can only be done through Powershell.

Snippet to build a TLS connector in Exchange Online for a list of domains

Some organisations, in particular German ones, require encryption between your Exchange Online mail servers and their mail servers. This can be enforced by adding their domains to an outbound TLS connector in Office 365.

In my case, this had to be enforced (the default is oppertunistic). If you get a long list, you’ll want to script this with the following snippet. Remember to make sure the first line of your CSV has the header ‘domains’ 🙂


#Author: Jos Lieben
#Help: www.lieben.nu
$UserCredential = Get-Credential $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session -AllowClobber -DisableNameChecking

$connector = Read-Host "Type the name you wish to give this connector"
$csv = Read-Host "Type the path to the file with TLS domains"

$domains = Import-CSV -LiteralPath $csv

$newDomains = @()
foreach($domain in $domains){
$ND = [String]$domain.domain
$ND = $ND.Trim()
$newDomains += $ND
}

try{
New-OutboundConnector -Name $connector -recipientdomains $newDomains -ConnectorType "Partner" -TlsSettings "CertificateValidation" -ErrorAction Stop
}catch{
Write-Error "Failed to modify outbound connector $connector $($Error[0])"
}

Configure TLS relay on IIS for Exchange Online / Office 365

A while ago, you may have read that Microsoft will no longer allow relaying everything by default in Exchange Online when using normal authentication starting in february 2017.

So I went about and set my SMTP relay in IIS to use a certificate instead, as the article explains.  This resulted in a flood of bad mail drops with the following error:

Action: failed
Status: 5.7.57
Diagnostic-Code: smtp;530 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM

After messing around with this for a while, I discovered the outbound port you have to use when connecting to smtp.office365.com to relay a message using anonymous TLS is port 25, NOT port 587 as we were using before to submit mail using a user account + password.

For those who want to configure a relay server on IIS to allow applications and devices that don’t support TLS, I’ll set out the steps to configure this properly: Continue reading Configure TLS relay on IIS for Exchange Online / Office 365

Setting calendar permission in bulk

A simple snippet that’ll allow you to give a certain group PublishingAuthor rights to all calendars in your organization:


$mailboxes = get-mailbox -Resultsize Unlimited
foreach ($mailbox in $mailboxes){
try{
Remove-MailboxFolderPermission -Identity "$($mailbox.alias):\Calendar" -User INSERTUSERORGROUPNAMEHERE -Confirm:$False -ErrorAction Stop | Out-Null
Add-MailboxFolderPermission -Identity "$($mailbox.alias):\Calendar" -User INSERTUSERORGROUPNAMEHERE -AccessRights PublishingEditor -ErrorAction Stop | Out-Null
Write-Host "$($mailbox.alias) processed" -ForeGroundColor Green
}catch{
Write-Host "$($mailbox.alias) failed" -ForeGroundColor Red
}

}

A warning though, calendar permissions in Exchange Online can easily become corrupted. I’ve been in touch with support several times, but their only fix is to tell the user to remove and reapply the permissions, which is a sure way to annoy your users during migration.

So, communicate this in advance!

Exchange Forwarding Report

This powershell snippet will tell you which mailbox is actively forwarding email, in what method (dual delivery or pure forwarding), to which email address and if the corresponding contact still exists and is active.

#Module name: findForwarderDetails
#Author: Jos Lieben (OGD)
#Date: 01-04-2016
#Description: this snippet will discover all active forwarders in your organization, and will print the original mailbox, target contact and target address and forwarding method

$output = @()
$mailboxes = Get-Mailbox -ResultSize Unlimited | Where {$_.ForwardingAddress -ne $Null}

foreach ($mailbox in $mailboxes){

    $obj = New-Object PSObject
    $obj | Add-Member NoteProperty mailboxName($mailbox.DisplayName)
    if($mailbox.DeliverToMailboxAndForward){
        $obj | Add-Member NoteProperty forwardingMode("Dual delivery")
    }else{
        $obj | Add-Member NoteProperty forwardingMode("Forward Only")
    }
    try{
        $contact = Get-MailContact -Identity $mailbox.ForwardingAddress.DistinguishedName -ErrorAction Stop
        $obj | Add-Member NoteProperty forwardingToName($contact.DisplayName)
        $obj | Add-Member NoteProperty forwardingToEmail($contact.ExternalEmailAddress)
    }catch{
        $obj | Add-Member NoteProperty forwardingToName("CONTACT DOES NOT EXIST OR IS DISABLED")
        $obj | Add-Member NoteProperty forwardingToEmail("CONTACT DOES NOT EXIST OR IS DISABLED")
    }
    $output += $obj
}

Write-Output $output