Office 365 Teams, webhooks & PowerShell

I do like Office 365 Teams, and have actually started to use the Teams App instead of Skype :-o

If you have not played with it, do, you will  love it.

Anyway, with a Team Channel, you can create an Incoming Webhook connector, that allows you send data to a channel.

In Teams, click on channel and the ellipse (…) and click on Connectors.

In the connectors list find “Incoming Webhook” and click configure.

Give the connector a name and click Create.

This will create the connector and give you it’s url.  Take a copy of it.

You can then use the following PowerShell cmdlets to post to the channel:

$TeamChanneluri = "# the channel url #"

$body=@"
{
  "@type": "MessageCard",
  "id": "list",
  "title": "-TITLE-",
  "TextFormat":"xml",
  "text": "You can use HTML codes like <B>bold</B>  and a <P/>new line or <HR/>line"
}
"@

Invoke-RestMethod -uri $TeamChanneluri -Method Post -body $body -ContentType 'application/json'

How cool is that!  What is good is that you can some standard html codes to make things look nice!

Enjoy

 

Exchange Online Default Email Address Policy

So this was interesting.  I had a user that was failing to create an Exchange Online Mailbox, due to a duplicate tenant address (tenantname.onmicrosoft.com), which us mortal people have zero control over.

After a week of playing I raised a call with Microsoft to see what the hell was going on.

To cut a long story short, the issue was resolved by itself.  “When product group started the troubleshooting mailbox was already created.”  Yeah right! As if by magic after a week it sorts itself .. sorry not convinced!

Anyway, it turns out (according to PSS), that the Default Email Address Policy on Exchange Online actually does nothing, and updating it from the default email template, has zero effect on users!  Which seams a bit odd, but hey!?!

The other interesting thing, is that if two users share the same UPN prefix like bob@domain1.com and bob@domain2.com there will be a conflict because both should get bob@tenantname.onmicrosoft.com as an alias in Office 365.

We have over 100k synced objects and over 600 domains.  So we should have seen this issue before .. but we didn’t.

Anyway, this is where the duplicate attribute resiliency feature of AAD Connect should come in to play, to make sure the attributes are unique. https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnectsyncservice-duplicate-attribute-resiliency.

However, for the user I had an issue with, this didn’t happen!

The expected behavior should be:

1st user to be synced / provisioned:
UPN / primary SMTP: bob@domain1.com
Secondary SMTP / cloud alias: bob@tenantname.onmicrosoft.com
Remote routing address: whatever is set via Exchange console (using the tenantname.mail.onmicrosoft.com domain)

2nd user to be synced / provisioned:
UPN / primary SMTP: bob@domain2.com
Secondary SMTP / cloud alias: bob1234@tenantname.onmicrosoft.com
Remote routing address: whatever is set via Exchange console (using the tenantname.mail.onmicrosoft.com domain)

So, only the IT gods know what happened, and it shouldn’t have happened in the first place, but welcome to the occasional oddness of cloud computing and Office 365.

UPDATE#1: Resolution from Microsoft: Attribute resiliency feature action generated unique onmicrosoft.com smtp address, but unfortunately with significant delay.

Laters

Exchange Online Mailbox Types

That is interesting.  Been playing with Exchange Online Mailbox types.

With the -Type parameter specifies the mailbox type for the mailbox. Valid values are:

  • Regular
  • Room
  • Equipment
  • Shared

Now I had never noticed this before, but when you switch a mailbox to anything other than Regular, the UserAccountControl changes to AccountDisabled.

That would explain why authenticated SMTP relay to smtp.office365.com would stop working :-o

 

Office 365 SMTP Relay Using Windows PowerShell

We are looking to the future, and getting ready to remove OnPrem Exchange.  To do this we need to deal with SMTP Relay.

Microsoft have this doc to help: https://support.office.com/en-gb/article/How-to-set-up-a-multifunction-device-or-application-to-send-email-using-Office-365-69f58e99-c550-4274-ad18-c805d654b4c4

But I wanted to code it ;-)

Quite simple, you need to use an Exchange Online Account:
$Password = "#mailbox password"
$emailFrom = "#mailbox"
$SMTPServer = "smtp.office365.com"
$SMTPPort = 587
$emailTo = "#recipient"
$msgsubject = "testing testing 1-2-3"
$msgBody = "hello world"
$message = New-Object Net.Mail.MailMessage($emailFrom, $emailTo, $msgsubject, $msgBody)
$message.IsBodyHTML = $True

$smtp = New-Object Net.Mail.SmtpClient($SMTPServer,$SMTPPort)
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($emailFrom, $Password);
$smtp.Send($message)

enjoy

Office 365 Groups and Primary SMTP Addresses

So here is an interesting one.

We know Office 365 groups are a hybrid Exchange Online / SharePoint Online thing.

When you create an Office 365 Group, it creates an MSOLGroup and a UnifiedGroup object, that you can access using Windows Powershell (Get-MsolGroup / Get-UnifiedGrou).

Any email addresses that are set as Primary on the unified group, replicate up to the MSOLGroup object.

Now, you can remove them from the unified group, but they will NEVER be removed the MSOLGroup object.  Try it ;-)

This means, if you need to do say a Tenant to Tenant migration, and the default msoldomain is a vanity domain, all office 365 groups will have the vanity domain as primary and you cannot remove it!

The only fix, is to delete the group! -or- raise a call with Microsoft and have your engineer engage with the Microsoft Online Domain Services Backend team (Azure AD) to remove them for you.

Enjoy

 

 

 

List Office 365 Administrators

So, I had a need to see who the other Global Admin are my Tenant.  Knocked this up to help.

The following assumes you already have a remote powershell session to Office 365!

$msoladmin = @()
$roles = Get-MsolRole
ForEach($role in $roles){
  $n = $role.Name
  Write-Host $n " " -NoNewLine -f Green
  [array]$tAdmin = Get-MsolRoleMember -RoleObjectId $role.ObjectId | Select *, @{Expression={$n};l="Role"}
  Write-Host $tAdmin.Count
  $msoladmin += $tAdmin
}
$msoladmin | sort Role,DisplayName | select DisplayName, Role

DirSync and Office 365

I wanted to share this for my own reference, but wanted to share the love.

Have been having a challenge with people thinking I am talking cr@p, which make me smile.  If I am wrong I will admit it.

When you setup DirSync, users from your onPrem AD are copied to the Office 365 Azure AD. Simple.

When you migrate (onboard) a mailbox to Office 365 the onPrem accounts change:

RecipientType RecipientTypeDetails RecipientType RecipientTypeDetails
UserMailbox UserMailbox -> MailUser RemoteUserMailbox
UserMailbox SharedMailbox -> MailUser RemoteSharedMailbox
UserMailbox RoomMailbox -> MailUser RemoteRoomMailbox

Now if you have a filter based on msExchRecipientTypeDetails you need to watch out, as expected the msExchRecipientTypeDetails changes:

Type Before After
User Mailbox 1 2147483648
Shared Mailbox 4 8589934592
Room Mailbox 16 17173869184
Equipment Mailbox 32 34359738368

This caused me some challenges as we had a filter that would only migrate disabled accounts with a value of 4 or 16 in msExchRecipientTypeDetails.

The net result was that after a Shared or Room mailbox was onboarded to o365 they would drop out of DirSync.  This is okay, as they stay in the Azure AD as a deleted user for 30 days.

You can recover a user from deleted users, they appear in Azure AD as “In Cloud” and any mailbox they had is accessible.

This is the fun bit. If the recovered user is added back in to dirsync, dirsync uses the Azure AD ImmutableId and compares that to an OnPrem Guid.  If a match they are become Dirsynced again.

You can see the ImmutableId when your run a get-msoluser.  Essentially it’s a fudge of the OnPrem AD ObjectGuid.  This post explains and here is a script to convert between the two.

Hope this helps someone, it helped me, get an understanding of what the hell was going on!

If this is complete cr@p let me know please!