Exchange Online makes it easy to assign delegated permissions for user and shared mailboxes. But permissions assigned to people might not be still necessary, so it’s good to do a periodic check. In this post, we describe a script to scan for permissions on Exchange Online user and shared mailboxes and highlight non-standard permissions in a report generated as a CSV file.
Microsoft released Version 1.0.4 of the Teams PowerShell module on March 9. The new module comes with some useful updates and is recommended for anyone working with Teams through PowerShell. And if cmdlets don’t do the job for you, there’s always the Microsoft Graph as you can combine PowerShell and the Graph to solve even more problems.
Large Office 365 tenants with more than 10,000 seats can now use the SharePoint Online site swap feature to replace an old root site with a new communications site. The site swap must be done with PowerShell and needs a new version of the Invoke-SPOSiteSwap cmdlet. Once you prepare your new site for swapping, everything goes smoothly.
A new version of the Exchange Online management PowerShell module is available. The update includes a number of bug fixes (including some security upgrades) and new features. You should upgrade to the new version as soon as possible and keep an eye out for more changes in the future.
Like many other parts of Office 365, you can manage SharePoint Online with PowerShell. At least, you can manage some aspects of SharePoint Online with PowerShell. Microsoft has made it easier to keep up to date with the latest SharePoint Online module and the PnP module, so there’s lots of cmdlets to help Administrators do a better job of automating different aspects of SharePoint Online.
OWA stores user signatures in mailboxes, which makes it a lot easier for Office 365 admins to update signatures centrally with just a few lines of PowerShell and some HTML magic. OK, maybe more than a few lines… but it’s a lot less complicated than it is to mess around with the system registry and points the way to how Microsoft might introduce cloud signatures for all Outlook clients.
Microsoft is working on cloud signatures for Outlook, but how can you update signatures for the current versions of Outlook click to run. Here’s our best attempt with PowerShell. The code works, but it could do with some error handing and various improvements before it could go anywhere near production. Think of it as a working example of why cloud signatures will be so much better,.
Writing code to illustrate a point sometimes falls into the trap that things don’t work so well when you scale things up. Take Graph calls for instance. Code that works well with 100 teams isn’t so good with 4,000. The solution is to keep on telling the Graph to fetch data until it’s all in the safe hands of PowerShell, and then process it.
A question asked what the best way is to add a mailbox to multiple distribution lists. The admin UIs do the job for a few lists, but PowerShell is the way to go when you have lots of lists to process. Two approaches are discussed here: one uses an array as the input, the other uses a CSV file.
The email addresses for Teams channels are interesting objects. Messages sent to channels start conversations in the target channel and are also captured in SharePoint. Any team member can enable or disable the ability of a channel to receive email by creating or removing email addresses and no admin control exists to stop this happening. Events captured in the Office 365 audit log reveal when email addresses are created or removed, meaning that you can at least know what’s going on.
Office 365 Groups (and their underlying teams and sites) can be removed by user action or automatically through the Groups expiration policy. By examining records in the Office 365 audit log, we can track exactly when groups are soft-deleted followed by permanent removal 30 days later. All done with a few lines of PowerShell and some parsing of the audit data held in the records.
A question asked how to be notified when people delete Teams. The answer lies in the Office 365 audit log, and once we’ve found out when Teams are deleted are who deleted them, we can notifications to administrators via email or by posting to a Teams channel. The administrators can then decide if they should restore the deleted team or let it expire and be permanently deleted after 30 days.
The Groups admin role was added to Office 365 in November 2019 to allow tenants to assign responsibility for day-to-day group management to specific users through interfaces like the Microsoft 365 Admin Center. The role is still relatively unknown and probably not used in many tenants. In this post, we discuss how to use PowerShell to assign the role to those allowed to create new groups.
After a couple of years, it’s time to update the Office 365 Groups and Teams Activity Report script. Written in PowerShell, the script analyzes the groups in an Office 365 tenant to figure out if each group or team is in active use. Because it’s a PowerShell script, you can amend the code to your heart’s content.
Finding it hard to keep up to date with Office 365? This post describes how to use PowerShell to post recent Microsoft 365 roadmap updates to a Teams channel.The message cards hold details of what an update contains, its status, the posting date, and the technology categories the item covers. Apart from posting to Teams, the script also creates a CSV file holding details of all the roadmap items that you can use for reporting and analysis.
The Skype for Business Online PowerShell module is not well liked. It works differently to other modules and has some oddities, including the ability to disconnect sessions after 60 seconds and fail to reconnect. The new Enable-CsOnlineSessionForReconnection helps to keep sessions going, so that’s one small but irritating oddity off what could be a long list.
The Get-SPOSite PowerShell cmdlet is used to fetch details about SharePoint Online sites. It works well, but some recent functionality upgrades means that script writers need to be more precise about how they use the cmdlet. Most scripts don’t need to process redirect sites or the sites belonging to Teams private channels, so why would you ask Get-SPOSite to fetch these sites?
Everyone’s PowerShell style is different. Here at Office365ITPros, we try and write code to help people understand what’s possible when working with Office 365. Our scripts are certainly not up to professional standard in that they’re incomplete in many ways (comments are always good). But the code works and proves what you can do, which we think is important.
Multiple PowerShell modules are available to Office 365 administrators to automate common processes. In this case, we want to send a welcome message to new accounts. Three PowerShell modules are available, but what’s the best in terms of performance and ease of use? There’s only one answer and that’s Exchange Online.
The Azure Active Directory Group Naming policy generates display names for new Office 365 Groups created by various applications. You can include a prefix or suffix in a group name, The approach taken by email favored prefixes because this gathered all distribution lists together in one place in the GAL. However, prefixes work better with applications like Teams.
The prospect of allowing user-controlled purchases of Power Platform apps in an Office 365 tenant maddened many administrators. Microsoft promised to release a method to allow administrators control self-service purchases in a tenant. The MSCommerce PowerShell module is now available. Here’s how to use it to disable self-service purchases.
Some new and updated cmdlets in a new version of the Teams PowerShell module are available to support private channels. The cmdlets and parameters are pretty straightforward for anyone used to working with Teams through PowerShell. Remember to read up and understand all about private channels before trying to work with them through PowerShell.
Nine new REST-based PowerShell cmdlets are available for Exchange Online. They offer the prospect of better performance and reliability. Here are the code samples we used to test the new cmdlets for a theater session delivered at the Microsoft Ignite 2019 conference. Anyone wanting to explore the new cmdlets can use these examples to get going.
Microsoft 365 applications create lots of Azure Active Directory guest accounts. Here’s how to find old accounts and check their membership of Microsoft 365 groups. If you know the accounts that are old and stale and aren’t members of any Microsoft 365 group, you can consider removing them from your tenant.
The Office 365 Admin Center includes reports of licenses assigned to users. The same information can be extracted with PowerShell, which means that you can analyze license assignments anyway you wish. The script is quick and easy, mostly because its error handling is non-existent, but it’s enough to get going.
It used to be more difficult to generate a report about the storage used by OneDrive for Business sites in an Office 365 tenant. Now it takes just a few lines of PowerShell. Here’s an example of a simple but powerful script to do the job.
Some Exchange Online mailboxes are quite small (2 GB for frontline users). Tenant administrators might want to monitor mailbox usage to make sure that quotas aren’t unexpectedly exhausted. This post explains how to use a PowerShell script to calculate the percentage of mailbox quota used and highlight the problem if a threshold is passed.
Microsoft has announced that basic authentication for multiple email connection protocols won’t be supported after October 13, 2020. You won’t be able to connect with EWS, EAS, IMAP4, POP3, or Remote PowerShell unless you use modern authentication. There’s just over a year to prepare, but there’s some work to be done.
Microsoft is now rolling out MyAnalytics access to Office 365 accounts with an Exchange Online license.The first sign that anyone gets is when they receive one of MyAnalytics’s well-intended messages to help them organize their work life smarter. Funnily enough, some people don’t like the idea of Office 365 analyzing and reporting their work habits, which is why you might need to disable MyAnalytics for some mailboxes.
If you want to include SharePoint Online and OneDrive for Business locations in an Office 365 content search, you need to know the URLs of the target sites. Finding the URLs can be problematic, but here’s some easy ways to do the job. PowerShell, as usual, comes up trumps…
Being able to generate a report of mailbox activity is nice, but being able to filter the report to find potentially inactive mailboxes and post that information to Teams is even better. A recent Petri.com article explains how to generate the report; in this post we explain how to extract information from the report to and post updates about inactive users to Teams.
Office 365 tenant administrators often make extensive use of PowerShell. It’s a great tool to get work done across all the Office 365 workloads. However, hackers like PowerShell too, and it could be used to attack your tenant. If that happens, having PowerShell logs will allow you to find out exactly what the attacker did and where. With this in mind, shouldn’t you enable PowerShell logging?
It’s easy to create a list of group-enabled SharePoint Online sites using the Get-SPOSite cmdlet. But it’s much more interesting to probe a little deeper to uncover extra information about the group using the GroupId property returned if you specify the Detailed parameter. This post explains a PowerShell script written to examine the possibilities, including how to highlight sites belonging to deleted groups that are kept by retention policies.
Teams App Permissions policies allow Office 365 tenants to exert a fine degree of control over the apps users are allowed to install. You can amend the default policy or create new policies and assign the policies to user accounts through the Teams Admin Center or with PowerShell.
Microsoft has announced the deprecation of the PowerShell module for the Azure Active Directory Rights Management service (AADRM). But don’t worry; it’s replaced by the Azure Information Protection (AIPService) module. Deprecation happens in July 2020, so you’ve lots of time to revise any scripts that use AADRM cmdlets.
Microsoft announced the roll-out of the Site Swap feature for SharePoint Online. You can only do this with PowerShell, but the process is quick and easy and works well (assuming your new site is ready to go). Who doesn’t like one-line PowerShell commands that do a lot of work with minimum effort!
Office 365 Activity Alerts don’t seem to be working too well these days. At least, that’s what we found when we tried to create an alert for Teams creation events. Never mind, PowerShell will do the job as we can quickly whip up a PowerShell script to find audit records for team creations and put them into an email.
A question about how best to set auto-replies for Exchange Online shared mailboxes to respond to messages arriving during a public holiday gives another chance for PowerShell to show how useful it is. You could do the work with Flow, but PowerShell is more flexible and capable when dealing with multiple shared mailboxes.
Exchange Online writes audit records into the Office 365 audit log when messages are deleted by delegates and administrative action. We can analyze the audit records to find out who deleted a specific message. Some challenges exist to interpret the audit records for admin-generated deletions (for example, when you run Search-Mailbox), but it’s easy enough to code the necessary checks in PowerShell.
Microsoft makes a strong case that all Azure Active Directory accounts should be protected with multi-factor authentication (MFA). That’s a great aspiration, but the immediate priority is to check accounts holding administrative roles. This post explains how to use PowerShell to find and report those accounts.
{"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}