Prevent Video Download in OneDrive and SharePoint Sharing Links

In line with the change to Stream videos storage to OneDrive and SharePoint. Microsoft are now enabling the ability to control the download functionality on shared videos. Previously, when sharing documents from OneDrive or SharePoint Online, users had the ability to make a file read-only and restrict download at the time of sharing.

Planned for late October for targeted release tenant and November for all other tenants, this feature should be available to everyone by the end of November. Once enabled, when sharing a video from OneDrive or SharePoint Online, users will have the ‘Block Download’ option. This option will ensure that recipients of the sharing link can only view the video in the web browser via the OneDrive web previewer.

Block download

While it’s not recommended for most use cases, this option can be disabled on a site or tenant level via the below commands in the SharePoint Online Management Shell respectively:


Set-SPOTenant -BlockDownloadLinksFileType:$True


Set-SPOSite -Identity <Site URL> -BlockDownloadLinksFileType:$True

Using Microsoft Teams as a Walkie Talkie for Frontline Workers

There are an amazing number of great apps available to integrate into Microsoft Teams. Some of these apps are published by Microsoft and many more are third part integrations ranging from handy productivity tools to line of business apps surfaced in a users Teams console. One cool app that is now available is the Teams ‘Walkie Talkie’ app. ‘Walkie Talkie’, essentially brings Push to Talk (PTT) functionality to Teams. Among the many use cases for this app, allowing Frontline Workers to communicate efficiently and quickly is a great application of Teams functionality and something that many third party vendors are currently providing.

Deploy Walkie Talkie

To deploy Walkie Talkie, we can create an App Setup Policy and deploy to the users we want the app available to. We add it into the pinned apps and deploy the policy to whoever needs it.

Given a little time to replicate, when our user logs in, they’ll see the app available in their App bar.

Using Walkie Talkie

Using Walkie Talkie is very easy. Simply open the Walkie Talkie app and select that Teams Channel we want to talk in.

Now when we hit ‘Connect’ we simply push the button to talk!

We can see how many other users are connected and also perform our other Teams tasks while remaining connected.

While this functionality is pretty straightforward, the value it provides is pretty impressive. I can definitely see this being used to replace a lot of legacy third party PTT systems.

Creating and Deploying Microsoft Teams Templates

Since its inception, Microsoft Teams has become a core part of the modern Microsoft 365 ecosystem. While it has been steadily gaining users naturally, the daily Teams user count has grown exponentially this year with many organizations being forced to adopt a work from home model. This has meant that a lot of IT departments have had to embrace cloud technology, usually at a quicker pace than initially planned.

At the center of this cloud adoption, is Microsoft Teams. What seems like the ultimate ‘Work from home’ tool, brings together the somewhat disparate Microsoft 365 apps and use cases into a single user interface. The heart of this is of course, the ‘Team’. In a Team, we can attach many apps and tabs to our various channels to help our users locate the functionality that they most need, when they need it. Teams for particular parts of the business can surface the relevant apps for that particular group of users and business function. For example a project Team would probably have a link to the project RAIID log associated with the project management channel.

That’s great, but do we need to set up these tabs, channels and apps every time we set up a new Team? Do we trust that our users will set their Teams up optimally? Also, if our users aren’t using Teams ‘right’, is that really their fault? Well, if Teams adoption suffers because users aren’t seeing the best Teams has to offer, that’s the problem of IT and Change Management.

To help provide users with some of the coolest features of Teams, without turning everyone into a ‘Super User’, Microsoft have recently released the Teams Template functionality. Teams Templates are excatly what they sound like, preconfigured Teams layouts, complete with apps and channels etc. that can be deployed from a list of Templates.

Creating a Teams Template

To create a Teams Template, we first open our Teams Admin Center, and navigate to the Teams – > Teams Templates section. From here we can see the massive amount of preconfigured Templates that Microsoft have made available to us out of the box. I recommend looking into the ‘Adopt Office 365’ template for deploying to your change champions.

The prebuilt templates are nice, but let’s create out own. Click ‘Add’ and we’ll select the option to create a new Template from scratch. We also have the option to modify and expand upon an existing Template, or even use an existing Team as a baseline for a Template.

We enter in some basic details and hit next to start building our Template.

Add in the Channels and Apps that the Teams should contain and when done, click ‘Submit’ to save the template. This template is now ready for deployment.

Deploying a Team from a Template

Now for the easy part. To deploy a Team from a Template as a user, simply create a Team as normal and select from the catalog of Templates available. Our custom Template is listed and when we add it, we see the newly created Teams gets created with all of our predefined settings. Don’t worry if the Channels and Apps aren’t there immediately, they can take some time to come through.

And that’s it, we’ve created and deployed a Template for Microsoft Teams, this functionality will no doubt help make Teams easier to use for our end users and really help showcase what it can do!

Setting up an Auto Attendant in Microsoft Teams

Microsoft Teams Calling Features have some great flexibility for standard calling requirements. For some more bespoke requirements there are great integrations available trough a number different contact center ISVs also. One of the cool built in features is the Microsoft Teams Auto Attendant. Auto Attendant has been around for a while now, coming from Skype for Business, and can help Organizations put a front end on customer facing numbers. In this post I’ll go through the steps to configure a Microsoft Teams Auto-Attendant.

Set up a Resource Account

The first requirement for an Auto Attendant is to create a resource account to act as the ‘entry point’ and have the associated front end phone number. Every Auto Attendant must have at least one Resource account associated and can have more than one if multiple numbers are required.

To set up a resource account, open the Teams Admin Center and go to ‘Org Settings‘ -> ‘Resource Accounts‘ and add a new account as below:

Next we assign a phone number to our resource account to enable it for dial-in. Depending on if you are using Dial Plans or Direct Routing this is slightly different.

For Dial Plans, hit the assign button and assign an Online number as below,

Screenshot of the Assign/unassign options

For Direct Routing, this currently needs to be done via the Skype For Business Online Management Shell. Use the command below to set this number on the resource account:

Set-CsOnlineVoiceApplicationInstance -Identity -TelephoneNumber +0000000000

Set up an Auto Attendant

Once we have our number set we can set up our Auto Attendant. Open the ‘Voice‘ -> ‘Auto Attendant‘ section of the Admin Center and create a new Auto Attendant.

On the creation page, select:

  • An Operator – The real person to get called if a user doesn’t want to speak to the Auto Attendant. This can be a real person, another Resource Account or an number that is external to Teams
  • Time Zone – this is for mapping opening hours to your current Time Zone
  • Language – The language the Auto Attendant should be in

On the next page, we can set up an initial greeting, this can be a recorded audio file or have the Teams system read out a typed message.

Next we choose what to do with our auto attendant. We can disconnect, reroute the call to another Resource Account or play a menu with associated triggers. If we choose to play menu options, we again have the option to record the message, or have the system read a written message.

We assign dial keys to trigger one of the below options, we can also add voice commands to each of the dial keys.

  • Operator – Speak to our chosen operator
  • Person in Organization – Search Directory (We’ll get to this in a later section)
  • Voice App – Another Resource Account linked to another Auto Attendant or Call Queue
  • Voicemail – Leave a Voicemail for an Office 365 Group
  • External Phone Number – A Number External to Teams

For our directory search option, we can allow users to search by name or extension.

Next we set our Business hours and choose what happens when we are outside business hours.

We can then set our settings for during holidays:

We configure who is accessible to directory search from this line, this can be a particular group of users or all users with particular excludions.

Finally, we link our resource account to our Auto Attendant and we’re all set. After a little time to propagate changes, our Resource Account number will route directly to our Auto Attendant flow.

Auto Attendants and Call Queues add some great functionality for receiving and routing calls for a lot of basic use cases. While more complex cases such as call center management can be fulfilled with Microsoft Partner integrations, the default functionality provides a lot of out of the box flexibility.

For more on Auto Attendants, Call Queues and licensing required see the Official Microsoft Documentation.

Conditional Access for Office 365 Apps Goes GA

Conditional Access is one of the first steps any organization should take when protecting user identities in Azure AD. The flexibility available through Conditional Access policies is fantastic for meeting sign-in requirements and depending on licensing, can even do some proactive mitigation of breaches using risk and sign-in policies.

Office 365 relies heavily on Azure AD to service authentication for users. Conditional Access is often a minimum requirement to allow users to securely access Office 365 services by enforcing protection on the sign-in activity. Previously, it has been hard to manage Conditional Access policies that only target Office 365 apps as the platform constantly expands and when new apps are published, they are not automatically included in our Conditional Access Policies.

Last year, Microsoft made this much easier by including the ‘Office 365’ app in Conditional Access as a preview feature. This meant that the different components of Office 365 no longer had to be included separately.

Previously Applying Blanket Protection to Office 365 Apps Was Cumbersome
With the Office 365 App Available, This is Much Easier

This week marks the official General Availability of the Office 365 app in Conditional Access. There should now be no excuse not to be using this app to provide holistic protection to Office 365 users.

For more information on what the Office 365 app in Conditional Access applies to, see the Official Microsoft Documentation.

Customize Microsoft Teams Meeting Invitations

Something I find that is missed in a lot of organizations is the branding features available in Microsoft 365. Branding is a really nice feature for users to see when logging into to cloud services, we also tend to not realize the security benefits of having appropriate branding on our sign-in page etc. When we brand correctly, it doesn’t just look nice, it gives users more confidence they are in the right place.

We could even potentially prevent users from getting phished by generic Microsoft 365 login pages as it will look different to their normal branded page. It’s a small thing, but could help prevent an attack when all else fails.

Another piece of branding people tend to miss out on, is branding Teams meeting requests. This helps make our meeting requests look professional, add in legal or support links and also may help protect against malicious requests going to our partners and customers.

Branding is available in the Teams Admin Portal and its really easy to set up. Simply add your logos etc. to the meeting settings page to update your meeting request branding.

You can then preview the change before deploying.

Branding the Teams meeting invites is a small thing and doesnt take a lot of effort to do but can really improve the look of the invites, and also potentially help prevent phishing.

Microsoft Teams Meeting Recordings Moving to OneDrive and SharePoint

Microsoft Teams recordings are a great feature for when people miss meetings and need to catch up, or when they just need to review the content. We’ve used them in the past for technical demos and project handovers. Recordings were were, until now, saved into Microsoft Stream and available to view in the Stream app. This is changing in the near future.

Going forward, Teams recordings will be saved into OneDrive and SharePoint by default instead. For any Channel meetings, recordings will be stored in the appropriate SharePoint library and for regular, non-channel meetings, they will be saved in the OneDrive of the user who hits the record button.

The current schedule for this rollout as issued by the Microsoft Message Center is:

  • mid-October (October 19, 2020) – You can enable the Teams Meeting policy to have meeting recordings saved to OneDrive and SharePoint instead of Microsoft Stream (Classic)
  • End of October (October 31, 2020) – Meeting recordings in OneDrive and SharePoint will have support for English captions via the Teams transcription feature.
  • Early to mid-November (Rolling out between November 1 -15 , 2020) – All new Teams meeting recordings will be saved to OneDrive and SharePoint unless you delay this change by modifying your organization’s Teams Meeting policies and explicitly setting them to “Stream”
  • Q1 2021 – No new meeting recordings can be saved to Microsoft Stream (Classic); all customers will automatically have meeting recordings saved to OneDrive and SharePoint even if they’ve changed their Teams meeting policies to Stream”

To delay this change until Q1 2020, you can run the below command in the Skype Online Management Shell (Yes it’s still around and very much needed to manage Teams, however it’s now installed as part of the Microsoft Teams PowerShell Module)

Set-CsTeamsMeetingPolicy -Identity Global -RecordingStorageMode "Stream"

The above command will allow you to defer this change to 2021 but not prevent it entirely.

For more information on the benefits of this change – and the limitations after moving, see the below Microsoft Article:

eDiscovery Functionality Moves to Microsoft 365 Compliance Center

eDiscovery and content search has been a staple of Microsoft 365 compliance since the early days of Office 365. Providing extremely flexible and efficient searching and actioning of data that resides anywhere in Microsoft 365, it has improved over time with a lot of extra functionality and is one of the most widely used compliance tools in the Microsoft 365 platform.

eDiscovery, which has first found in the Exchange Online Admin Center for mail discovery, was subsequently moved to the Microsoft 365 Security & Compliance Center ( The Security & Compliance Center itself has undergone a lot of changes recently and is coming near its end of life, being replaced with the Microsoft 365 Security Center ( and the Microsoft 365 Compliance Center ( which cater to Security tools and Data Governance/Compliance tools respectively.

The splitting of the SCC into two different portals makes sense as a lot of the time, in enterprise scenarios, these aspects of the tenancy are managed by two, completely separate teams. There will often be a dedicated security team, who deal with the identity protection and security aspects of the tenancy, and a dedicated Data Protection Team who are more concerned with the information governance side of things.

As of Oct 30th 2020, the eDiscovery suite of tools will be moving fully to the Microsoft 365 Compliance Center and the Security & Compliance Center links will redirect to the new page. This is the next step in the process of moving all the features from the old portal to the new model so if you haven’t checked out the two new pages, see below for more information.

Microsoft 365 Compliance Center:

Microsoft 365 Security Center:

Direct links:




Using Graph API in PowerShell Example – OneDrive File Structure Report

Due to an issue on a file migration, I recently had a requirement to compare source and destination OneDrive structures. The easiest way I could come up with to do this was to use Graph API to expand the folder structure and export to CSV. I’ve always been a big PowerShell users so that is usually the basis for my Graph scripts.

I decided to share this basic script to help anyone who is trying to figure out how it works. The source for this script can be found on GitHub here.

The below script is intended to illustrate how you can use PowerShell and Graph calls together, not as a production Script

##Author: Sean McAvinue
##Details: Used as a Graph/PowerShell example, 
##          Returns a report of OneDrive file and folder structure to CSV file
function GetGraphToken {
    Azure AD OAuth Application Token for Graph API
    Get OAuth token for a AAD Application (returned as $token)

    # Application (client) ID, tenant ID and secret
    $clientId = ""
    $tenantId = ""
    $clientSecret = ""
    # Construct URI
    $uri = "$tenantId/oauth2/v2.0/token"
    # Construct Body
    $body = @{
        client_id     = $clientId
        scope         = ""
        client_secret = $clientSecret
        grant_type    = "client_credentials"
    # Get OAuth 2.0 Token
    $tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
    # Access Token
    $token = ($tokenRequest.Content | ConvertFrom-Json).access_token
    #Returns token
    return $token

function expandfolders {
    Expands folder structure and sends files to be written and folders to be expanded
    .PARAMETER folder
    -Folder is the folder being passed
    .PARAMETER FilePath
    -filepath is the current tracked path to the file
    General notes
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]


    write-host retrieved $filePath -ForegroundColor green
    $filepath = ($filepath + '/' + $
    write-host $filePath -ForegroundColor yellow
    $apiUri = ('' + $user.UserPrincipalName + '/drive/root:' + $FilePath + ':/children')

    $Data = RunQueryandEnumerateResults -ApiUri $apiUri -Token $token

    ##Loop through Root folders
    foreach ($item in $data) {

        ##IF Folder
        if ($item.folder) {

            write-host $ is a folder, passing $filePath as path
            expandfolders   -folder $item -filepath $filepath

        }##ELSE NOT Folder
        else {

            write-host $ is a file
            writeTofile -file $item -filepath $filePath



function writeTofile {
    Writes files and paths to export file

    -file is the file name found
    .PARAMETER FilePath
    -filepath is the current tracked path
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]


    ##Build file object
    $object = [PSCustomObject]@{
        User         = $user.userprincipalname
        FileName     = $
        LastModified = $File.lastModifiedDateTime
        Filepath     = $filepath

    ##Export File Object
    $object | export-csv OneDriveReport.csv -NoClobber -NoTypeInformation -Append

    ##Reset workingfilepath


function RunQueryandEnumerateResults {
    Runs Graph Query and if there are any additional pages, parses them and appends to a single variable
    .PARAMETER apiUri
    -APIURi is the apiUri to be passed
    .PARAMETER token
    -token is the auth token
        [parameter(Mandatory = $true)]
        [parameter(Mandatory = $true)]


    #Run Graph Query
    $Results = (Invoke-RestMethod -Headers @{Authorization = "Bearer $($Token)" } -Uri $apiUri -Method Get)
    #Output Results for debug checking
    #write-host $results

    #Begin populating results
    $ResultsValue = $Results.value

    #If there is a next page, query the next page until there are no more pages and append results to existing set
    if ($results."@odata.nextLink" -ne $null) {
        write-host enumerating pages -ForegroundColor yellow
        $NextPageUri = $results."@odata.nextLink"
        ##While there is a next page, query it and loop, append results
        While ($NextPageUri -ne $null) {
            $NextPageRequest = (Invoke-RestMethod -Headers @{Authorization = "Bearer $($Token)" } -Uri $NextPageURI -Method Get)
            $NxtPageData = $NextPageRequest.Value
            $NextPageUri = $NextPageRequest."@odata.nextLink"
            $ResultsValue = $ResultsValue + $NxtPageData

    ##Return completed results
    return $ResultsValue


function main {
    Main function, reports on file and folder structure in OneDrive for all imported users


    ##Get in scope Users from CSV file##
    $Users = import-csv userlist.csv

    #Loop Through Users
    foreach ($User in $Users) {
        #Generate Token
        $token = GetGraphToken

        ##Query Site to get Site ID
        $apiUri = '' + $User.userprincipalname + '/drive/root/children'
        $Data = RunQueryandEnumerateResults -ApiUri $apiUri -Token $token

        ##Loop through Root folders
        ForEach ($item in $data) {

            ##IF Folder, then expand folder
            if ($item.folder) {

                write-host $ is a folder
                $filepath = ""
                expandfolders -folder $item -filepath $filepath

                ##ELSE NOT Folder, then it's a file, sent to write output
            else {

                write-host $ is a file
                $filepath = ""
                writeTofile -file $item -filepath $filepath




Office 365 Outlook Insider Build – ‘Pin Email’ Feature

On my personal laptop, I run the Office Insider Build so that I can assess new features before they come into production. One of the cool new features that has been released to Beta recently is the ability in Outlook to Pin an email.

If you’re anything like me you can spend hours sifting through emails and trying to add follow up actions so you don’t lose track of multiple tasks that have come in by mail. Personally, having zero unread emails in my inbox stopped being an option for me years ago.

The new Pin email functionality is a life save for me as it essentially “pins” an email to the very top of your inbox. This puts it right in your face until you remove it, forcing you to get back to that demanding co-worker who is just full of questions.

The pin option is available on the ribbon menu and the context menu by right clicking an email and selecting Pin/Unpin.

Once pinned, you’ll see the mail at the top of your inbox in Outlook. This also works for different folders so can match your mailbox structure no matter how granular it is.

More information on this feature and other insider features are available on the Insider website: