Fixed: Outlook desktop unable to render SharePoint hosted images embedded in to mail body through PowerAutomate send email action

This post comes out from a recent support experience to one of my clients. He was trying to use Microsoft PowerAutomate flow to embed a SharePoint library hosted image in to an email notification which sent regularly across the organization for all users. Usual way for doing this is using the <img src tag in the send email action but interestingly, these behaviors was a showstopper until I figured out the solution after several hours (described at the end of the article).

111

Behaviors:

  1. Embedded images from a SharePoint URL did not render in Outlook desktop App
  2. Same image renders in OWA (Outlook Web App) however, there was a slight delay in loading the image.
  3. Same image hosted in public hosting locations rendered nicely as well (e.g – https://www.w3schools.com/, Google etc..)

SharePoint hosted image in Outlook Desktop App: Strange enough !

3

External hosted image in Outlook Desktop App:

4

Tried and did not work for my case:

  • Change the text format to HTMLOutlook client application (File -> Options -> Mail -> Compose message in HTML format). This was already in place for my scenario.
  • Add the domain to safe/trusted sites in the browser settings
  • Plethora of other solutions from Microsoft articles and forums

clip_image002[6]

The real solution:

To overcome this issue, you simply have to use these additional lines in your email step. Add a compose action and point it to ‘Get file content using path’ SharePoint action (or you can directly add this line to the mail body HTML)

Add a new Compose action in to the PowerAutomate flow 

Set the Expression as below (you can copy and paste this)

dataUri(outputs('Get_file_content_using_path')?['body'])

67

Amend the Mailbody to reflect the following or add the above mentioned expression directly to the HTML body. Either way should work.

<p><br>
File content using path<br> 

<img src="@{outputs('Compose_2')}"></img>
</p>

8

Full flow: Tested and working perfectly across web client and desktop client of Outlook

9

Result: SharePoint hosted image is now rendered perfectly in Outlook desktop App.

10

Root cause analysis:

The key point is the use of dataUri() to convert the file content to the right format that HTML can understand. An image or a file in general from a SharePoint link is not public link. Only authenticated users can view the image which is the root cause of this issue.

If a user logs in into Outlook on the web from  a browser, their Microsoft identification data are stored locally within the browser context as cookies. As a result, when opening an email that contains a SharePoint link in HTML image tags, a request will be sent to SharePoint servers with the same identification and the image can be downloaded if the user has enough privilege.

It’s the same way that if you have already logged in into one of the google services, you won’t have to login again when accessing other Google services in deferent tabs.

On the other hand, Outlook client is simply an email application which does not share the same architecture as a browser. Outlook account credentials are stored differently and Outlook does not have mechanism to detect and pass credentials to other Microsoft services. Hence, when it sees a SharePoint link in HTML image tags, a request without any authorization data will be sent to the SharePoint servers and of course, it will be refused. If a hyperlink added to the email, clicking on the link will open a browser and you will need to sign in.  In the end, the main purpose of Outlook client is for email-related tasks and it will not handle authentication for other services.

Remove orphaned delegation permissions of a deleted user in Exchange Online mailbox

You might think that a user’s delegate permissions for other mailboxes will be removed up on deleting the account in the Azure Active Directory, apparently it wasn’t in my case.

access20delegation-01_thumb

Scenario:

Location – Calendar folder of ‘manoj@mantoso.live:\Calendar’

Delegated editor permissions to – ‘Marie Jonas’ (Abandoned identity after AD account deletion)

Even though this particular account was permanently deleted from Azure AD after 30 days of marking deletion, the delegation access (editor) to other users’ Exchange mailboxes remained intact which caused the following strange behaviors that I had to get rid of.

  • Others can still spot this user’s name in the calendar invites
  • Possibly in other various occasions too based on the permissions the user had before deleted

Here’s the PowerShell command to fetch the permissions of a specific location. This will list down all the delegated permissions of ‘Manoj’s’ Exchange calendar. In my case, the abandoned user also popped up in the results.

Get-EXOMailboxFolderPermission "manoj@mantoso.live:\calendar" 

e.g0.1

Now, to dig further down to be more specific to this mysterious user, let’s run this command

Get-EXOMailboxFolderPermission "manoj@mantoso.live:\calendar" | where {$_.user.tostring() -like "Marie Jonas*"}

e.g0

This means the permission thumbprint is intact even after the account was permanently deleted which is a mystery. Now to get rid of this, we can use this command below. I tried several other approaches from various Microsoft articles and forum posts but none of them worked but the following.

Get-EXOMailboxFolderPermission "<user@domian.com:\calendar>" | where {$_.user.tostring() -like "<FirstName Last Name>*"} | Remove-MailboxFolderPermission -Confirm:$False

After running that with no errors/warnings. I ran Get command again to verify if it really was a success. And Yes ! Nothing returned, which means the permissions are now cleared for this abandoned identity of ‘Marie Jonas’.

2

Allowed it a couple of hours, her name disappeared from the calendar invites as well.

Get-EXOMailboxFolderPermission "<user@domian.com:\calendar>" | where {$_.user.tostring() -like "<FirstName Last Name>*"} | Remove-MailboxFolderPermission -Confirm:$False

Enable Microsoft Whiteboard for Teams

Whiteboard in Teams is powered by Whiteboard for the web and this is a very useful feature for collaborating in group meetings. A shared canvas space allows meeting participants to collaborate. In Office 365, Whiteboard feature is enabled by default unless you disabled it manually (mostly customers disable it due to data residency concerns).

Microsoft Note: The ability to start a new whiteboard is currently limited to the Microsoft Teams clients on Windows 10, macOS, and for the web. The Teams apps for iOS and Android cannot initiate sharing a whiteboard, but they can collaborate once a whiteboard is shared.

Now let’s get this configured. Login to Office 365 Admin center using admin credentials and type ‘Whiteboard’ in the global search field. You will get the Whiteboard global settings option in a search result dropdown.

image

Check the ‘Turn on’’ tick box to enable it globally in your Tenancy. Diagnostic data collection by Microsoft is disclosed via three options here.

image

Connected experiences and sharing from Surface Hub are two optional settings depending on the organizational requirements. Finally hit ‘Save’ to complete it.

image

Now the global setting is enabled, we need to ensure the Whiteboard capability is also enabled in the Meeting policies. If you have multiple policies, make sure this is enabled for all of them to affect it to the desired target audiences.

From the Teams admin center, navigate to Meetings –> Meeting policies

image

Then click on the desired policy (in my case, the ‘Default’ as it affects to all users)

image

Toggle the ‘Allow Whiteboard’ switch to ‘On’ state to enable it and hit ‘Save’

image

Notes: This might take a couple of ours to reflect to all users (in my case it took 7+ hours).

Testing the feature.

  1. Now to try this out, you can create a test meeting with another user and ensure the Whiteboard is appearing once ‘Share’ option is clicked.

image

  1. Also, if you login to office.com, you should be able to see the ‘Whiteboard’ App under the Apps list.

clip_image001[4]

clip_image002[4]

Troubleshooting:

If you still don’t see the feature in Teams meetings, try to toggle ‘Off’ the Whiteboard feature from Teams meeting policy. Then turn in it on again and try it in a couple of hours.

Error when accessing Exchange Online classic Admin Center (EAC): 403 Access denied :(

We have been pulling our hair out for several days due to this issue. Office 365 Exchange admin center gives the following error whereas the new admin center worked well.

when you click that “Exchange” blade from the Office 365 admin center, it usually takes you to the classic Admin center which we still need for some functions that new Admin center doesn’t have.

image 

clip_image001

After lots of struggle, we managed to figure out the Root cause and reported to Microsoft through an incident.

Root cause: Group based access assignments in Privileged Identity Management.

image

Workaround: We had assigned Azure AD Roles such as Global Administrator, Exchange Administrator via Group based PIM which did not work properly with classic EAC. Assigning Direct permissions fixed this and we managed to open the classic console immediately, right after the direct assignment. If you are facing the same, try to get rid of “Group Assignments” for Exchange Admins at least for the time being and go for “Direct Assignments

Official reference: https://docs.microsoft.com/en-us/azure/active-directory/roles/groups-concept 

KnownIssue

I will update this post up-on Microsoft’ support responses.

Renew Apple MDM Push Certificate in Microsoft Endpoint Manager (Intune)

Apple MDM Push certificate is the key element for Microsoft EndPoint Manager to manage iOS/iPadOS and macOS devices in the MEM portal. After you add the certificate to EndPoint Manager, your users can enroll their devices using: The Company Portal app or Apple’s bulk enrollment methods such as the Device Enrollment Program (a.k.a DEP), Apple School Manager, or Apple Configurator.

digital

This renewal is crucial:  Ensure that you take necessary actions before the expiry date as revoking or allowing this certificate to expire will require existing devices to be re-enrolled with a new push certificate.

Prerequisites for renewal:

  1. Apple Identity portal account (mostly different from the Apple ID) which was used to setup the integration for your organization. – https://identity.apple.com/pushcert/
  2. MFA code (sends to the device registered for MFA under above account)

  3. Appropriate access to MEM (Microsoft Endpoint Manager a.k.a Intune portal) – https://endpoint.microsoft.com/ 

First we need to sign-in to MEM portal using your admin credentials copy paste this link and sign in https://endpoint.microsoft.com/ 

Navigate to Devices blade from the left panel and go to Apple iOS/iPadOS enrolment section as shown below and then click on ‘apple MDM Push Certificate’ widget

0

From the screen popped up, simply click on download CSR file on the 2nd option. Save it to a secure/temporarily location as we will delete this after the renewal.

5

Let’s now switch in to Apple Identity portal. This is where you need the original credentials which was used to setup the integration with Intune. Login from that account to this site – https://identity.apple.com/pushcert/

1

You can avoid MFA using other options but this may not be the same in your case. Hence make sure you have the device associated to the account to receive the MFA code. Hit ‘Continue“’ to enter the code or go to ‘other options’ to avoid it.

2

Highly recommended to associate a mobile device for MFA if you haven’t already, or, chose ‘don’t upgrade’ option to avoid it.

3

Once logged in, you will see all your certificates listed with the expiry date stated.

4

That little ‘i” button will show you more details of each certificate if you have multiple (mostly used for different tenancies under a single account). Serial Number is the key to identity which is which from the Intune portal. Ensure that you are renewing the correct certificate by cross-checking the Serial No here againts Intune. Once confirmed, simply click on that ‘Renew” button above and you should see a new dialog box prompting.

6

Add a note to indicate who renew it which might be useful in a organization this will be done by another person next year.

And now choose the CSR file you downloaded from Intune and hit ‘Upload’

7

That’s it and you can see the green tick indicates everything went well. Simply download the certificate and store in the same secure location you store CSR previously.

8

You should see the new expiry date for this certificate now.

9

Let’s head back to MEM (Intune) portal now and upload the new certificate file there. You should also provide the original Apple ID which was used to create the MDM push cert. Once done, hit ‘Upload’ button.

10

That’s about it and now you will see a green status prompts indicates it went well.

11

Certificate should now be valid for another year !

12

Outlook Error: Unable to convert a generic Outlook meeting to a Teams meeting (online meeting)

Article Updated: This issue is now resolved

Due to the popular demand, Microsoft has re-deployed this feature on 14th September 2020. If you restart the Outlook, Teams clients and try to convert a occurrence now, you should be able to do so.

This is one appointment in a series, To make it an online meeting, open the meeting series and try again

image

Did you get this error just out of the blue in Outlook as well ? – If so, this is an ongoing issue with Outlook clients and you are not the only one impacted, and, not everyone impacted either. Recurring meeting in Outlook had the ability to edit one occurrence out of the series and we could convert these generic meetings in to Teams meetings (online meeting) until last week 14-08-2020). However this has somehow changed for some customers probably due to an Outlook/Teams update (not yet confirmed).

In my case, the following version of Outlook 2016 had the issue (and it’s not the only version impacted)

clip_image001

This may not be one of those common features used by majority but, it is indeed an important feature for those who are having busy calendars to manage.

clip_image002

Usually when you try to edit an single occurrence in a series.

clip_image003

It prompts you to choose a one or the entire series. The following steps are captured from my device as it seems not impacted.

clip_image004

The problem starts when you click on “Teams Meeting” icon to convert the meeting to a Teams meeting.

clip_image005

This is how it supposed to look like when it converted. You can simply send the update and the generic meeting will become a “Teams Meeting” and the meeting details will be inserted to the bottom of the screen.

clip_image006

So far I have tried the following but nothing made any difference.

  1. Clear Outlook cache and restart Outlook and PC
  2. Clear teams cache and restart
  3. Disable and enable Teams Add-in for Outlook

Workaround: (this is verified to be working): There is an alternative way of changing meetings using OWA for now. I truly understand this is frustrating but until Microsoft come back to us, perhaps Mary can use this workaround from Outlook Online ? (Web version from https://www.office.com )

Workaround: Outlook on the web is the only workaround as of now. It works well on OWA but if you have shared calendars it may not be the best option. To test it out follow these steps:

From outlook web, go to Calendar tab à from the desired series of events, double click on one of the occurrence in the series

clip_image008

And Edit “This Event”

clip_image009

Go to “More options”

clip_image010

And toggle the “Teams Meeting” switch next to room location

clip_image011

Then Save it. You should be able to see this occurrence has now set to a Teams Meeting.

clip_image012

There are many who impacted as per this forum post and keeps growing. If you are facing the issue as well, just post a comment there  – https://answers.microsoft.com/en-us/msoffice/forum/msoffice_outlook-mso_win10-mso_o365b/cannot-add-teams-meeting-to-a-single-occurrence-of/fbf2db7e-e8b3-443f-bed9-ec1f9dd6ce31?messageId=517049e8-c2c4-4ff9-ae55-1a3e778999a2

I am currently working with a Microsoft support engineer to engage the backend team and will keep this post updated as soon as I have an update. If you have faced it too or have found a fix, please reach out to me on manojviduranga@hotmail.com and share the ideas !!

Update: Due to the popular demand, Microsoft has re-deployed this feature on 14th September 2020. If you restart the Outlook, Teams clients and try to convert a occurrence now, you should be able to do so.

Transfer ownership of a PowerApp using PowerShell

    PowerApps administration capabilities have considerably evolved from where it was and now we can easily transfer the ownership of a specific App using a simple PowerShell command. This article will cover that specific task.

    clip_image001

    However, If you look at the latest Power Platform Admin center (https://admin.powerplatform.microsoft.com/) you’ll figure out there’s nothing much we could do there as admins, so PowerShell comes again for the rescue.

    clip_image002

    PowerApps offers two separate PowerShell packages for Creators (a.k.a Makers) and Administrators respectively. Before you can do anything, you need this Admin module installed in your machine.

    you can download the NUGPKG manually from the first link, or run the command below to install it directly.

Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -RequiredVersion 2.0.1

Once you have the module installed, the following command will give you an idea of the number of apps created in your environment. This is important so that you can standardize the permissions and accessibility for all your Apps via proper governance.

Before we begin, here’s the first command to login to PowerApp service. Run PowerShell as admin and then execute this.

Add-PowerAppsAccount

This command will list-down all the apps in your environment with basic information for you to understand the App Name, Display Name Current Ownership etc..

Get-AdminPowerApp

To retrieve the current permissions for a specific PowerApp:

Get-AdminPowerAppRoleAssignment -AppName <APP ID>

This will list down the deep down information of a specific app including all assigned permissions for that particular app.

clip_image003

So now that we have all the information, to change ownership, we can either run this simple command and input the details as prompted, or use the full command below. To run this, ensure that you login from the new owner.

Set-AdminPowerAppOwner

If you get this error (Conflict) it means that the app is opened and being edited. Close all the session for this app and try to execute the command again.

clip_image004

This is the full command with all the parameters and inputs are predefined. The new Owner must run this command as it uses the current logged in user to execute the change.

Set-AdminPowerAppOwner -AppName '895a38f1-f3c3-4cb6-a2d4-64b199badb3d' -AppOwner $Global:CurrentSession.userId -EnvironmentName 'Default-f50d5133-e13c-4359-85f6-ef76484f4c32'

clip_image005

That should easily run and change the new Owner. However, the previous owner will still remain as a normal user which allows the new Owner to decide whether to keep remove. As new owner can use the User Interface to manage the app, he can simply manage the permission there.

clip_image006

Resources:

Determine On-Premise and Cloud Mailbox Users

During an Exchange online management activity for one of our enterprise clients, I had to determine which mailboxes are on cloud and which ones still resides on-premise. After going through several PS commands, I had to come up with a customized basic script to get this done neatly. This script will run against Office 365 and check for the following.

Get licensed users, fetch Display Name, UPN and IsLicensed properties and format the output then export the result to an CSV file.

Connect to Exchange online PowerShell using Connect-ExchangeOnline and then run the following  after customizing the output path to suit your environment.

Get-MsolUser -MaxResults 50000 |
Where-Object isLicensed -eq $true |
Select-Object -Property DisplayName, UserPrincipalName, isLicensed,
                        @{label='MailboxLocation';expression={
                            switch ($_.MSExchRecipientTypeDetails) {
                                      1 {'Onprem'; break}
                                      2147483648 {'Office365'; break}
                                      default {'Unknown'}
                                  }
                        }} | Export-Csv c:\Official\Tools\mailusers.csv

You can run it directly from PowerShell which would result as below if everything went well.

clip_image001

Or use PowerShell ISE

clip_image002

Result would look something similar to this.

image

Get-MsolUser -MaxResults 50000 |
Where-Object isLicensed -eq $true |
Select-Object -Property DisplayName, UserPrincipalName, isLicensed,
                        @{label='MailboxLocation';expression={
                            switch ($_.MSExchRecipientTypeDetails) {
                                      1 {'Onprem'; break}
                                      2147483648 {'Office365'; break}
                                      default {'Unknown'}
                                  }
                        }} | Export-Csv c:\Official\Tools\mailusers.csv

Export All Sites, libraries and lists of a SharePoint Online Site Collection

If you remember classic SharePoint, it had that nice looking (and yet unreliable sometimes) feature called “SharePoint Site Structure” which was eventually deprecated as move & copy functions were introduced. This was very insightful to understand the site and content hierarchy across the entire SharePoint farm.site-content-and-structure1

However, let’s assume you want to review your modern day SharePoint Online hierarchy every once in a while, and make sure your sites, libraries and lists are aligning to best practices as far as the depth of the site levels? Or, you just want to know what sort of sites exist in your site collection, we still have a manual way of getting those information out using a simple PowerShell script. This may not be the best sophisticated way of getting a handy report which can probably be obtained using a 3rd party tool.

Unless its a test environment, we rarely notice any Office 365 tenant without MFA enabled, so this script is Modern-Auth friendly and supports MFA. You can generate a basic report of all sites, libraries and lists in a specific site collection by defining the site collection name and CSV path to save it.

###Function to Get Lists and Libraries of a web
Function Get-SPOSiteInventory([Microsoft.SharePoint.Client.Web]$Web)
{
    Write-host -f Yellow "Getting Lists and Libraries from site:" $Web.URL
 
    ###Get all lists and libraries
    $SiteInventory= @()
    $Lists= Get-PnPList -Web $Web
    foreach ($List in $Lists)
    {
        $Data = new-object PSObject
        $Data | Add-member NoteProperty -Name "Site Name" -Value $Web.Title
        $Data | Add-member NoteProperty -Name "Site URL" -Value $Web.Url
        $Data | Add-member NoteProperty -Name "List Title" -Value $List.Title
        $Data | Add-member NoteProperty -Name "List URL" -Value $List.RootFolder.ServerRelativeUrl
        $Data | Add-member NoteProperty -Name "List Item Count" -Value $List.ItemCount
        $Data | Add-member NoteProperty -Name "Last Modified" -Value $List.LastItemModifiedDate
        $SiteInventory += $Data
    }
 
    ###Get All Subwebs
    $SubWebs = Get-PnPSubWebs -Web $Web
    Foreach ($Web in $SubWebs)
    {
        $SiteInventory+= Get-SPOSiteInventory -Web $Web
    }
    Return $SiteInventory
}
 
###Config Variables
$SiteURL = "https://sitename.sharepoint.com/sites/PWA"
$CSVFile = "C:\temp\filename.csv"
 
###Get Credentials to connect
 
Try {
    #Connect to PNP Online
    Connect-PnPOnline -Url $SiteURL -UseWebLogin
 
    ###Get the Root Web
    $Web = Get-PnPWeb
 
    ###Call the function and export results to CSV file
    Get-SPOSiteInventory -Web $Web | Export-CSV $CSVFile -NoTypeInformation
}
Catch {
    write-host "Error: $($_.Exception.Message)" -foregroundcolor Red

As you execute it, you’ll be prompted for credentials and the report will be generated (duration might depend on the number of site collections and the weight of each)

image

image

Original script used in this scenario was published in this article of SharePoint Diary

Step by Step: fetching Microsoft Teams conversation history (chat history)

Scenario A: Targeting an specific Team

An uncommon but definitely one of those once in a while query from the HR or compliance/security leadership you will get is “Can we search for Microsoft Teams chat” in Office 365.

clip_image001

The answer depends on the type of content/period that you need. Here are some of the use cases I worked on (probably not the exact case as yours but you might get some clarity here about where to look for)

Teams stores an individual’s chat history in a hidden file in the users mailbox which is not accessible via OWA or Outlook. Users or Administrators cannot access these hidden files. Skype for Business used to archive these in the users mailbox which they could delete but we didn’t worry about that because our email archive still had a record of those IMs.

You can see in the following screenshot that I have tried to add the Internal IT channel mailbox in to the Outlook and obviously “Conversation History” is empty because it’s a hidden folder. So, with that in mind, we will have to dig in through a different way.

clip_image002

clip_image003

clip_image004

Scenario A: How to retrieve the conversation history of a particular Team/Channel?

First lets connect to Exchange online PowerShell to put up a foundation in to what we are looking for.

Connect-EXOPSSession

Login as a Global Admin

clip_image005

All the chat history from Microsoft Teams is saved into a mailbox with the name of the Team. So I’m looking for a mailbox called “Internal IT”. Easiest way is to fire up trusty PowerShell and run:

Let’s run this line to retrieve all the group mailboxes we have in this tenant.

get-mailbox -groupmailbox

I see all the shared mailboxes in my tenant. As you can see I find one called “Internal IT” as shown below.

clip_image006

Now this is the Channel I am interested in (Internal IT). This simply means that each channel has a dedicated database which brings the initial satisfaction ! We could surely get something out now.

clip_image007

With that in mind, we now know what is the address of the Team channel I need to look in to. And, here comes the e-Discovery content search for the rescue. Yes we can fetch the Teams chat history from there !

Head on to Compliance Admin blade from office 365 Admin center

clip_image008

Go to “e-Discovery”

clip_image009

Start by creating a new case here. Hit “+ Create a case” to begin

clip_image010

Give it a simple name and a description and save

clip_image011

Click on the blue “Open” button to get inside the case

clip_image012

It brings you to the search interface

clip_image013

From Searches, add the following search parameters.

clip_image014

You can customize your query to suite your needs and I have done it as below. Feel free to click that little “X” to close each parameter and add another to match your target result.

clip_image015

Use the “Add Conditions” button to refine your search criteria

clip_image001[6]

clip_image002[7]

I am not going to search based on a keyword so it’s going to be the participants parameter and the value is my target Team (Project Delivery)

clip_image016

From the locations, choose the following and unselect everything else.

clip_image017

You can further customize your search query to get a more refined search result but it’s totally up to you. My target is to get the entire chat history of “Project Delivery Team” Team chat.

Finally hit the search button and give it a few seconds/minutes (based on the content size of the tenant).

clip_image001

And, here we are ! It now shows me all the IM’s under this Team.

clip_image018

You can export the result in two ways, a report or the result

clip_image019

Also, it allows you to choose what you want to export.

clip_image020

clip_image021

Once done, click on the relevant export batch and download it.

clip_image022

When you download, there’ll be a small tool to obtain the batch. Make sure you are on the Microsoft Edge browser for this final task.

clip_image023

Warning: You must use Microsoft Edge or Internet Explorer to download search results or reports. Please switch to one of these browsers to download the content.

The following error means you are not using Microsoft Edge for this task. Just switch your browser and you should be good to go !

clip_image024