A question was asked about the best way to find out if shared mailboxes received email from certain domains over the past 60 days. Exchange Online historical message traces can extract trace data to allow us to check, but the process of running the message trace and then analyzing the data is just a little disconnected.
Microsoft will deprecate the Azure AD and MSOL PowerShell modules in June 2023. It’s time to convert scripts that use cmdlets from these modules and the Microsoft Graph PowerShell SDK is probably the best answer. This article explains how to generate a report of Exchange Online distribution list memberships, a task often handled in the past with Azure AD cmdlets.
Several methods exist to add new user accounts to groups automatically. Dynamic group membership is an obvious option, but other choices exist, including org-wide teams (if your organization is under 10,000 accounts) and using PowerShell to manage the automatic addition of new members to a standard distribution list or Microsoft 365 group. This article examines the various methods. Once you understand what’s possible, you can make the right choice.
The automation of Azure AD account creation and password updates are straightforward using the Microsoft Graph PowerShell SDK. A little preparation always helps, but once you have all the necessary information, it’s easy to code up the necessary script to generate a new password and add the account – or set of accounts.
Azure AD custom security attributes can mark user and service principal objects for special processing, which is how the app filter for conditional access policies works. It’s nice to be able to interact with data through PowerShell and the Microsoft Graph PowerShell SDK cmdlets support setting, updating, and retrieval of Azure AD custom security attributes. Everything works, but it’s a pity that it’s a little clunky.
Microsoft Teams doesn’t come with a Teams Directory, so it’s hard to know if a suitable team already exists when people ask for a new team. This fact contributions to teams sprawl where multiple teams exist to serve the same purpose. Teams sprawl creates an obstacle to effective collaboration and runs the danger that some important information is tucked away inside teams that no one ever goes near. Creating a Teams Directory helps team owners and users know what teams already exist inside a tenant. It’s an idea that just makes sense.
A reader asks how to monitor membership changes for some specific high-profile groups. You can buy a commercial product to do the job or use PowerShell to exploit the information held in the Office 365 audit log. A combination of a custom attribute assigned to the sensitive groups and an audit log search does the job.
This article explains how to make Teams policy assignments using an Azure Automation runbook and some of the modernized cmdlets available in the Teams PowerShell module. Not everything worked as smoothly as we’d like, but like most PowerShell scenarios, there’s usually a workaround available to get the job done. It just needs to be found.
In most situations, it’s a good idea to enable Azure AD accounts for SSPR (self-service password reset) to avoid the need for administrators to update user accounts when things go wrong. This article explains how to report accounts that are not yet set up to use SSPR. It’s a check that should happen regularly, perhaps with the aid of Azure Automation.
Before an app or an Azure Automation account can use the Teams PowerShell cmdlets in a script or runbook, it must have the permission to act as an administrator. In this article, we cover how to assign the necessary role to a service principal.
This article explains how to use PowerShell and the Office 365 audit log to report Azure AD license assignments. The output isn’t pretty, but it works. The code works by finding two different audit events for each license assignment and combining information from both events to create a view of what happened. It’s rough and ready and can be improved, but the principal is proven and that’s what I set out to do.
This article describes how to use the Exchange.ManageAsApp permission to allow Azure AD apps to run Exchange Online PowerShell cmdlets. You can do this in the Azure AD admin center for registered apps, but when the time comes to allow Azure Automation runbooks to sign into Exchange Online with a managed identity, you must assign the permission to the automation account with PowerShell. Easy when you know how, hard when you don’t!
A script written by a Microsoft program manager to remove authentication methods from an Azure AD account caused me to write a script to capture all the authentication methods used in a tenant. I have other similar scripts, but this one records some additional detail for each method. And I have a moan about why the Microsoft Graph PowerShell SDK includes so many cmdlets for interacting with authentication methods. Some consolidation would be nice.
Microsoft is moving the listing of archived mailboxes from the Purview Compliance portal to its natural home in the Exchange Admin Center. In this post, we look at how you can report the current status of archive mailboxes (both user and shared mailboxes) in a Microsoft 365 tenant.
Hidden membership is supported for Microsoft 365 Groups and distribution lists. Hidden membership means that no one except members and admins can see who’s in a group. It’s a useful feature if you don’t want people poking around to find out who’s in a group or distribution list. One thing to be aware of is that once a Microsoft 365 group has hidden membership, it has it forever. Distribution lists on the other hand can flip between hidden and visible membership.
This article describes how to adapt the Microsoft 365 licensing report script to highlight Azure AD accounts that haven’t signed in for a long time. Because Microsoft charges for licenses on a monthly basis, every month that goes by racks up cost for underused accounts. The new version of the script tells you what accounts to check to help you focus on driving down licensing costs.
Every time someone reacts to a message in a team chat or channel conversation, Teams captures an audit record and sends it to the Office 365 audit log. The Teams reactions audit records are an interesting source of information. In this article, we show how to use PowerShell to interpret the contents of the reactions, and how to use the data to find the underlying messages.
Entra ID registered devices have 15 extension attributes that tenants can use for their own purposes. In this article, we explore how to use the Microsoft Graph PowerShell SDK to update extension attributes for registered devices, and even better, access the content in the extension attributes afterward.
I’ve spent some time investigating Azure Automation PowerShell recently. In this article, I discuss three learnings that might be of interest to others. Debugging, cost, and tracking the use of Azure Automation PowerShell might not interest everyone, but they’ve certainly helped me to understand how the platform works.
No Microsoft 365 admin portal will tell you about the set of email addresses assigned to Teams channels. Fortunately, it’s relatively easy to create a report with PowerShell and just a little Graph magic.
Document label mismatches happen when users create, upload, or update Office documents in SharePoint sites and give the documents a higher-priority sensitivity label than the one assigned to the site. When this happens, SharePoint Online creates a DocumentSensitivityMismatchDetected audit event. Unhappily, that event doesn’t tell us who caused the mismatch, but some work with PowerShell reveals all.
Exchange Online shared mailboxes only need licenses if they have an archive, exceed 50 GB in size, or are on litigation hold. The rules are there, but how many tenants check their shared mailboxes to make sure that they’re in compliance. This article explains how to use PowerShell to detect shared mailboxes that need licenses.
In this article, we explain how to create a report about the Teams private channels found in a tenant together with the members and owners of each channel. The PowerShell script is relatively straightforward and once the data is extracted from Teams, it can be sliced and diced in different ways.
A previous article explains how to use an Azure Automation runbook to write information to a SharePoint Online site and Teams channel. At the time, I used a stored credential to authenticate and access SharePoint and Teams. Azure Key Vault offers another way to store secrets (bits of information) securely. This article explores how to store secrets in Azure Key Vault and retrieve and use the secrets in a runbook script and interactive PowerShell.
The Get-AssociatedTeam cmdlet is part of V4.6 of the Microsoft Teams PowerShell module. It reports the membership a user account has in teams, including where the account has direct membership of shared channels. The cmdlet makes it easy to generate a report of teams membership, and the PSWriteHTML module makes it easy to output nice PDF reports.
This article explains how to populate the membership of a Teams shared channel using PowerShell. The idea is to create a shared channel that’s used for organization-wide communications, like a HR questions and answers channel. Alternatives like using a dynamic Azure AD group with a filter to find Teams users are also considered.
A new version of the Microsoft 365 user activity report PowerShell script is available. This version extends the activity lookback period to 180 days, which is helpful when assessing if user accounts are active when people might be on parental leave or sabbaticals.
Version 4.6 of the Microsoft Teams PowerShell module includes the Get-TeamAllChannel cmdlet. As the name implies, the cmdlet returns details of all channels in a team (regular, private, and shared). To see what it does, we wrote a script to report all the channels in teams in a tenant.
There are many versions of PowerShell scripts to report SharePoint external users online. Most don’t handle team-connected sites, so we take the time to explain the oddities of the Get-SPOExternalUser cmdlet and create some data that we can report using the PSWriteHTML module. All in day’s work with Microsoft 365.
Cmdlets in the Microsoft Graph PowerShell SDK module can interact with many types of Microsoft 365 data using Graph API requests. Adding the Debug parameter gives you an insight into what happens when SDK cmdlets run Graph requests. The knowledge can help you write better code and avoid mistakes, and that’s always a good thing.
Many example PowerShell scripts exist to report Azure AD accounts and their MFA status. Most of the scripts use the old MSOL module. Now we can use the Microsoft Graph PowerShell SDK and some Graph API requests to do the same job, This article explains how, including how to highlight unprotected Azure AD accounts that hold administrative roles.
Time is ebbing away and the date when the Azure AD PowerShell modules will start not to work is approaching. Microsoft wants customers to upgrade to the Microsoft Graph PowerShell SDK or Graph API requests. That’s fine, but a knowledge gap exists because most of the examples – including in Microsoft’s own documentation – for how to interact with Azure AD via PowerShell use the old modules. And then every other blog on the planet (with some notable exceptions) does the same. So we have work to do to bridge the knowledge gap and help people to make the transition.
The GUI of the Microsoft Purview compliance center doesn’t support the exclusion of selected mailboxes when the special All target is used. However, you can use PowerShell to add mailbox exclusions to sensitivity label policies, including adding the members of a group as exclusions.
Microsoft is introducing new controls for delegate access to encrypted emails accessed via Outlook clients other than Outlook for Windows. The controls are implemented in three new PowerShell cmdlets which can block, validate, and allow delegate access to encrypted messages. It’s nice to see some coherence being introduced for almost all the Outlook clients, even if Outlook for Windows does its own thing.
The Azure AD PowerShell module allows guest accounts to sign into target tenants and update their account photo there. The Microsoft Graph PowerShell SDK includes a cmdlet to do the job, but it doesn’t work when connected to a target tenant. Permissions are the reason why, which is what we explain in this article.
The Microsoft 365 substrate captures Teams compliance records for chats and channel conversations and stores them in Exchange Online. How many do you have? Although you might not care, sometimes it’s good to know (like a tenant to tenant migration), so we explain how to count Teams compliance records for chats and channel conversations.
The new Graph X-Ray extension available for the Chrome and Edge browsers gives developers an insight into how the Azure AD admin center uses Graph API commands to retrieve user and group objects. The insight is invaluable when teasing out some of the syntax needed to get work done with the Graph. It’s much appreciated.
A reader asked if it’s possible to use PowerShell to return the unread count for the Inbox folder in user mailboxes. The standard Exchange Online PowerShell cmdlets tell you a lot about mailbox folder statistics, but they can’t look inside a folder. But the Microsoft Graph APIs can, so a combination of PowerShell and the Graph deliver a solution to the problem.
The upcoming removal of support for basic authentication in seven Exchange Online connectivity protocols could mean trouble for some Office 365 tenants if they don’t take care to ensure that modern authentication is used for PowerShell connections. The old-style Remote PowerShell connection must be replaced with the Connect-ExchangeOnline cmdlet from the Exchange Online management module (aka the V2 module). Apart from anything else, this should improve the performance and robustness of scripts, especially after Microsoft finishes the work to remove the WinRM dependency for older cmdlets.
The ImportExcel PowerShell module is a useful addition to any Microsoft 365 tenant administrator’s toolbox. Although standard cmdlets exist to interact with spreadsheet data, they are limited to CSV files and can’t exploit the full power of Excel in the way that ImportExcel can do, all without needing to install the Excel application on a workstation.
{"id":null,"mode":"button","open_style":"in_modal","currency_code":"EUR","currency_symbol":"\u20ac","currency_type":"decimal","blank_flag_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/blank.gif","flag_sprite_url":"https:\/\/office365itpros.com\/wp-content\/plugins\/tip-jar-wp\/\/assets\/images\/flags\/flags.png","default_amount":100,"top_media_type":"featured_image","featured_image_url":"https:\/\/office365itpros.com\/wp-content\/uploads\/2022\/11\/cover-141x200.jpg","featured_embed":"","header_media":null,"file_download_attachment_data":null,"recurring_options_enabled":true,"recurring_options":{"never":{"selected":true,"after_output":"One time only"},"weekly":{"selected":false,"after_output":"Every week"},"monthly":{"selected":false,"after_output":"Every month"},"yearly":{"selected":false,"after_output":"Every year"}},"strings":{"current_user_email":"","current_user_name":"","link_text":"Virtual Tip Jar","complete_payment_button_error_text":"Check info and try again","payment_verb":"Pay","payment_request_label":"Office 365 for IT Pros","form_has_an_error":"Please check and fix the errors above","general_server_error":"Something isn't working right at the moment. Please try again.","form_title":"Office 365 for IT Pros","form_subtitle":null,"currency_search_text":"Country or Currency here","other_payment_option":"Other payment option","manage_payments_button_text":"Manage your payments","thank_you_message":"Thank you for supporting the work of Office 365 for IT Pros!","payment_confirmation_title":"Office 365 for IT Pros","receipt_title":"Your Receipt","print_receipt":"Print Receipt","email_receipt":"Email Receipt","email_receipt_sending":"Sending receipt...","email_receipt_success":"Email receipt successfully sent","email_receipt_failed":"Email receipt failed to send. Please try again.","receipt_payee":"Paid to","receipt_statement_descriptor":"This will show up on your statement as","receipt_date":"Date","receipt_transaction_id":"Transaction ID","receipt_transaction_amount":"Amount","refund_payer":"Refund from","login":"Log in to manage your payments","manage_payments":"Manage Payments","transactions_title":"Your Transactions","transaction_title":"Transaction Receipt","transaction_period":"Plan Period","arrangements_title":"Your Plans","arrangement_title":"Manage Plan","arrangement_details":"Plan Details","arrangement_id_title":"Plan ID","arrangement_payment_method_title":"Payment Method","arrangement_amount_title":"Plan Amount","arrangement_renewal_title":"Next renewal date","arrangement_action_cancel":"Cancel Plan","arrangement_action_cant_cancel":"Cancelling is currently not available.","arrangement_action_cancel_double":"Are you sure you'd like to cancel?","arrangement_cancelling":"Cancelling Plan...","arrangement_cancelled":"Plan Cancelled","arrangement_failed_to_cancel":"Failed to cancel plan","back_to_plans":"\u2190 Back to Plans","update_payment_method_verb":"Update","sca_auth_description":"Your have a pending renewal payment which requires authorization.","sca_auth_verb":"Authorize renewal payment","sca_authing_verb":"Authorizing payment","sca_authed_verb":"Payment successfully authorized!","sca_auth_failed":"Unable to authorize! Please try again.","login_button_text":"Log in","login_form_has_an_error":"Please check and fix the errors above","uppercase_search":"Search","lowercase_search":"search","uppercase_page":"Page","lowercase_page":"page","uppercase_items":"Items","lowercase_items":"items","uppercase_per":"Per","lowercase_per":"per","uppercase_of":"Of","lowercase_of":"of","back":"Back to plans","zip_code_placeholder":"Zip\/Postal Code","download_file_button_text":"Download File","input_field_instructions":{"tip_amount":{"placeholder_text":"How much would you like to tip?","initial":{"instruction_type":"normal","instruction_message":"How much would you like to tip? Choose any currency."},"empty":{"instruction_type":"error","instruction_message":"How much would you like to tip? Choose any currency."},"invalid_curency":{"instruction_type":"error","instruction_message":"Please choose a valid currency."}},"recurring":{"placeholder_text":"Recurring","initial":{"instruction_type":"normal","instruction_message":"How often would you like to give this?"},"success":{"instruction_type":"success","instruction_message":"How often would you like to give this?"},"empty":{"instruction_type":"error","instruction_message":"How often would you like to give this?"}},"name":{"placeholder_text":"Name on Credit Card","initial":{"instruction_type":"normal","instruction_message":"Enter the name on your card."},"success":{"instruction_type":"success","instruction_message":"Enter the name on your card."},"empty":{"instruction_type":"error","instruction_message":"Please enter the name on your card."}},"privacy_policy":{"terms_title":"Terms and conditions","terms_body":null,"terms_show_text":"View Terms","terms_hide_text":"Hide Terms","initial":{"instruction_type":"normal","instruction_message":"I agree to the terms."},"unchecked":{"instruction_type":"error","instruction_message":"Please agree to the terms."},"checked":{"instruction_type":"success","instruction_message":"I agree to the terms."}},"email":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email address"},"success":{"instruction_type":"success","instruction_message":"Enter your email address"},"blank":{"instruction_type":"error","instruction_message":"Enter your email address"},"not_an_email_address":{"instruction_type":"error","instruction_message":"Make sure you have entered a valid email address"}},"note_with_tip":{"placeholder_text":"Your note here...","initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"empty":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"not_empty_initial":{"instruction_type":"normal","instruction_message":"Attach a note to your tip (optional)"},"saving":{"instruction_type":"normal","instruction_message":"Saving note..."},"success":{"instruction_type":"success","instruction_message":"Note successfully saved!"},"error":{"instruction_type":"error","instruction_message":"Unable to save note note at this time. Please try again."}},"email_for_login_code":{"placeholder_text":"Your email address","initial":{"instruction_type":"normal","instruction_message":"Enter your email to log in."},"success":{"instruction_type":"success","instruction_message":"Enter your email to log in."},"blank":{"instruction_type":"error","instruction_message":"Enter your email to log in."},"empty":{"instruction_type":"error","instruction_message":"Enter your email to log in."}},"login_code":{"initial":{"instruction_type":"normal","instruction_message":"Check your email and enter the login code."},"success":{"instruction_type":"success","instruction_message":"Check your email and enter the login code."},"blank":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."},"empty":{"instruction_type":"error","instruction_message":"Check your email and enter the login code."}},"stripe_all_in_one":{"initial":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"empty":{"instruction_type":"error","instruction_message":"Enter your credit card details here."},"success":{"instruction_type":"normal","instruction_message":"Enter your credit card details here."},"invalid_number":{"instruction_type":"error","instruction_message":"The card number is not a valid credit card number."},"invalid_expiry_month":{"instruction_type":"error","instruction_message":"The card's expiration month is invalid."},"invalid_expiry_year":{"instruction_type":"error","instruction_message":"The card's expiration year is invalid."},"invalid_cvc":{"instruction_type":"error","instruction_message":"The card's security code is invalid."},"incorrect_number":{"instruction_type":"error","instruction_message":"The card number is incorrect."},"incomplete_number":{"instruction_type":"error","instruction_message":"The card number is incomplete."},"incomplete_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incomplete."},"incomplete_expiry":{"instruction_type":"error","instruction_message":"The card's expiration date is incomplete."},"incomplete_zip":{"instruction_type":"error","instruction_message":"The card's zip code is incomplete."},"expired_card":{"instruction_type":"error","instruction_message":"The card has expired."},"incorrect_cvc":{"instruction_type":"error","instruction_message":"The card's security code is incorrect."},"incorrect_zip":{"instruction_type":"error","instruction_message":"The card's zip code failed validation."},"invalid_expiry_year_past":{"instruction_type":"error","instruction_message":"The card's expiration year is in the past"},"card_declined":{"instruction_type":"error","instruction_message":"The card was declined."},"missing":{"instruction_type":"error","instruction_message":"There is no card on a customer that is being charged."},"processing_error":{"instruction_type":"error","instruction_message":"An error occurred while processing the card."},"invalid_request_error":{"instruction_type":"error","instruction_message":"Unable to process this payment, please try again or use alternative method."},"invalid_sofort_country":{"instruction_type":"error","instruction_message":"The billing country is not accepted by SOFORT. Please try another country."}}}},"fetched_oembed_html":false}