← All scripts

Microsoft 365 & Entra ID

M365 User & Security Report

Comprehensive Microsoft 365 audit: an Excel report of every mailbox (licences, MFA status, last logon, size, aliases, delegates) plus a text report of per-domain email security (MX, SPF, DKIM), licence counts, and risky findings like forwarding rules and admin-role holders. Note: uses the legacy MSOnline module, which Microsoft is retiring.

Download .ps1660 lines · PowerShell

Replace generic placeholder values (tenant, domain, secrets) for your own environment before running. Read it first and test safely.

<#
.SYNOPSIS
    Comprehensive Microsoft 365 mailbox, licence and email-security audit report.

.DESCRIPTION
    Connects to Microsoft 365 (MSOnline + Exchange Online) and produces:
      - An Excel report of every mailbox: licences, MFA status, type, last logon,
        inactive days, mailbox/archive size, aliases, and delegate access.
      - A text report of email security per domain: MX, SPF, DKIM (auto-enabling it
        where the correct DNS records already exist), SMTP relay connectors, licence
        counts, and the anti-phishing policy.
    Highlights risky findings: mailbox forwarding rules, licensed non-user mailboxes,
    and accounts holding admin roles.

    Requires the MSOnline, ExchangeOnlineManagement and ImportExcel modules
    (the script installs any that are missing).

.NOTES
    SANITISED FOR PUBLIC RELEASE: removed an internal SharePoint download URL.
    The licence SKU -> friendly-name map below is built from Microsoft's public
    "Product names and service plan identifiers for licensing" reference:
    https://learn.microsoft.com/entra/identity/users/licensing-service-plan-reference
#>

# Ensure the required modules are installed
foreach ($Module in @('MSOnline','ExchangeOnlineManagement','ImportExcel')){
    if ((Get-Module -Name $Module -ListAvailable).count -eq 0){
        if ((Get-Host).Version.Major -ge 5){
           "Module '$Module' not installed, attempting to install now, please approve"
            Install-Module $Module -scope CurrentUser
        }else{
            Write-Host  "Please install the $Module module. In an admin PowerShell run: Install-Module -Name $Module"  -ForegroundColor yellow
            Exit
        }
    }
}

# Clean any existing sessions
Get-PSSession | Remove-PSSession

# The licence friendly-name lookup is embedded inline below ($License_name_mapping),
# built from Microsoft's public licensing reference (see .NOTES above).

$License_name_mapping = @{}
$License_name_mapping.Add('ADV_COMMS','Advanced Communications')
$License_name_mapping.Add('CDSAICAPACITY','AI Builder Capacity add-on')
$License_name_mapping.Add('SPZA_IW','APP CONNECT IW')
$License_name_mapping.Add('MCOMEETADV','Microsoft 365 Audio Conferencing')
$License_name_mapping.Add('AAD_BASIC','AZURE ACTIVE DIRECTORY BASIC')
$License_name_mapping.Add('AAD_PREMIUM','AZURE ACTIVE DIRECTORY PREMIUM P1')
$License_name_mapping.Add('AAD_PREMIUM_P2','AZURE ACTIVE DIRECTORY PREMIUM P2')
$License_name_mapping.Add('RIGHTSMANAGEMENT','AZURE INFORMATION PROTECTION PLAN 1')
$License_name_mapping.Add('SMB_APPS','Business Apps (free)')
$License_name_mapping.Add('MCOCAP','COMMON AREA PHONE')
$License_name_mapping.Add('MCOCAP_GOV','Common Area Phone for GCC')
$License_name_mapping.Add('CDS_DB_CAPACITY','Common Data Service Database Capacity')
$License_name_mapping.Add('CDS_DB_CAPACITY_GOV','Common Data Service Database Capacity for Government')
$License_name_mapping.Add('CDS_LOG_CAPACITY','Common Data Service Log Capacity')
$License_name_mapping.Add('MCOPSTNC','COMMUNICATIONS CREDITS')
$License_name_mapping.Add('CRMSTORAGE','Dynamics 365 - Additional Database Storage (Qualified Offer)')
$License_name_mapping.Add('CRMINSTANCE','Dynamics 365 - Additional Production Instance (Qualified Offer)')
$License_name_mapping.Add('CRMTESTINSTANCE','Dynamics 365 - Additional Non-Production Instance (Qualified Offer)')
$License_name_mapping.Add('SOCIAL_ENGAGEMENT_APP_USER ','Dynamics 365 AI for Market Insights (Preview)')
$License_name_mapping.Add('DYN365_ASSETMANAGEMENT','Dynamics 365 Asset Management Addl Assets')
$License_name_mapping.Add('DYN365_BUSCENTRAL_ADD_ENV_ADDON','Dynamics 365 Business Central Additional Environment Addon')
$License_name_mapping.Add('DYN365_BUSCENTRAL_DB_CAPACITY','Dynamics 365 Business Central Database Capacity')
$License_name_mapping.Add('DYN365_BUSCENTRAL_ESSENTIAL','Dynamics 365 Business Central Essentials')
$License_name_mapping.Add('DYN365_FINANCIALS_ACCOUNTANT_SKU','Dynamics 365 Business Central External Accountant')
$License_name_mapping.Add('PROJECT_MADEIRA_PREVIEW_IW_SKU','Dynamics 365 Business Central for IWs')
$License_name_mapping.Add('DYN365_BUSCENTRAL_PREMIUM','Dynamics 365 Business Central Premium')
$License_name_mapping.Add('DYN365_ENTERPRISE_PLAN1','Dynamics 365 Customer Engagement Plan')
$License_name_mapping.Add('DYN365_CUSTOMER_INSIGHTS_VIRAL ','Dynamics 365 Talent: Attract ')
$License_name_mapping.Add('Dynamics_365_Customer_Service_Enterprise_viral_trial ','Dynamics 365 Customer Service Enterprise Viral Trial ')
$License_name_mapping.Add('DYN365_AI_SERVICE_INSIGHTS','Dynamics 365 Customer Service Insights Trial')
$License_name_mapping.Add('FORMS_PRO','Dynamics 365 Customer Voice Trial')
$License_name_mapping.Add('DYN365_CUSTOMER_SERVICE_PRO','Dynamics 365 Customer Service Professional')
$License_name_mapping.Add('Forms_Pro_AddOn','Dynamics 365 Customer Voice Additional Responses')
$License_name_mapping.Add('DYN365_CUSTOMER_VOICE_ADDON','Dynamics 365 Customer Voice Additional Responses')
$License_name_mapping.Add('Forms_Pro_USL','Dynamics 365 Customer Voice USL')
$License_name_mapping.Add('CRM_ONLINE_PORTAL','Dynamics 365 Enterprise Edition - Additional Portal (Qualified Offer)')
$License_name_mapping.Add('Dynamics_365_Field_Service_Enterprise_viral_trial ','Dynamics 365 Field Service Viral Trial ')
$License_name_mapping.Add('DYN365_FINANCE','Dynamics 365 Finance')
$License_name_mapping.Add('DYN365_ENTERPRISE_CUSTOMER_SERVICE','DYNAMICS 365 FOR CUSTOMER SERVICE ENTERPRISE EDITION')
$License_name_mapping.Add('DYN365_FINANCIALS_BUSINESS_SKU','DYNAMICS 365 FOR FINANCIALS BUSINESS EDITION')
$License_name_mapping.Add('DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE','DYNAMICS 365 FOR SALES AND CUSTOMER SERVICE ENTERPRISE EDITION')
$License_name_mapping.Add('DYN365_ENTERPRISE_SALES','DYNAMICS 365 FOR SALES ENTERPRISE EDITION')
$License_name_mapping.Add('DYN365_BUSINESS_MARKETING ','Dynamics 365 Marketing Business Edition ')
$License_name_mapping.Add('DYN365_REGULATORY_SERVICE ','Dynamics 365 Regulatory Service - Enterprise Edition Trial ')
$License_name_mapping.Add('Dynamics_365_Sales_Premium_Viral_Trial ','Dynamics 365 Sales Premium Viral Trial ')
$License_name_mapping.Add('D365_SALES_PRO ','Dynamics 365 For Sales Professional')
$License_name_mapping.Add('D365_SALES_PRO_IW ','Dynamics 365 For Sales Professional Trial ')
$License_name_mapping.Add('D365_SALES_PRO_ATTACH','Dynamics 365 Sales Professional Attach to Qualifying Dynamics 365 Base Offer')
$License_name_mapping.Add('DYN365_SCM','DYNAMICS 365 FOR SUPPLY CHAIN MANAGEMENT')
$License_name_mapping.Add('SKU_Dynamics_365_for_HCM_Trial','Dynamics 365 for Talent')
$License_name_mapping.Add('Dynamics_365_Hiring_SKU ','Dynamics 365 Talent: Attract ')
$License_name_mapping.Add('DYN365_ENTERPRISE_TEAM_MEMBERS','DYNAMICS 365 FOR TEAM MEMBERS ENTERPRISE EDITION')
$License_name_mapping.Add('GUIDES_USER','Dynamics 365 Guides')
$License_name_mapping.Add('Dynamics_365_for_Operations_Devices','Dynamics 365 Operations - Device')
$License_name_mapping.Add('Dynamics_365_for_Operations_Sandbox_Tier2_SKU','Dynamics 365 Operations - Sandbox Tier 2:Standard Acceptance Testing')
$License_name_mapping.Add('Dynamics_365_for_Operations_Sandbox_Tier4_SKU','Dynamics 365 Operations - Sandbox Tier 4:Standard Performance Testing')
$License_name_mapping.Add('DYN365_ENTERPRISE_P1_IW','DYNAMICS 365 P1 TRIAL FOR INFORMATION WORKERS')
$License_name_mapping.Add('MICROSOFT_REMOTE_ASSIST','Dynamics 365 Remote Assist')
$License_name_mapping.Add('MICROSOFT_REMOTE_ASSIST_HOLOLENS','Dynamics 365 Remote Assist HoloLens')
$License_name_mapping.Add('D365_SALES_ENT_ATTACH','Dynamics 365 Sales Enterprise Attach to Qualifying Dynamics 365 Base Offer')
$License_name_mapping.Add('DYNAMICS_365_ONBOARDING_SKU','DYNAMICS 365 TALENT: ONBOARD')
$License_name_mapping.Add('DYN365_TEAM_MEMBERS','DYNAMICS 365 TEAM MEMBERS')
$License_name_mapping.Add('Dynamics_365_for_Operations','DYNAMICS 365 UNF OPS PLAN ENT EDITION')
$License_name_mapping.Add('EMS','ENTERPRISE MOBILITY + SECURITY E3')
$License_name_mapping.Add('EMSPREMIUM','ENTERPRISE MOBILITY + SECURITY E5')
$License_name_mapping.Add('EMS_GOV','Enterprise Mobility + Security G3 GCC')
$License_name_mapping.Add('EMSPREMIUM_GOV','Enterprise Mobility + Security G5 GCC')
$License_name_mapping.Add('EOP_ENTERPRISE_PREMIUM','Exchange Enterprise CAL Services (EOP DLP)')
$License_name_mapping.Add('EXCHANGESTANDARD','Exchange Online (Plan 1)')
$License_name_mapping.Add('EXCHANGESTANDARD_GOV','Exchange Online (Plan 1) for GCC')
$License_name_mapping.Add('EXCHANGEENTERPRISE','EXCHANGE ONLINE (PLAN 2)')
$License_name_mapping.Add('EXCHANGEARCHIVE_ADDON','EXCHANGE ONLINE ARCHIVING FOR EXCHANGE ONLINE')
$License_name_mapping.Add('EXCHANGEARCHIVE','EXCHANGE ONLINE ARCHIVING FOR EXCHANGE SERVER')
$License_name_mapping.Add('EXCHANGEESSENTIALS','EXCHANGE ONLINE ESSENTIALS (ExO P1 BASED)')
$License_name_mapping.Add('EXCHANGE_S_ESSENTIALS','EXCHANGE ONLINE ESSENTIALS')
$License_name_mapping.Add('EXCHANGEDESKLESS','EXCHANGE ONLINE KIOSK')
$License_name_mapping.Add('EXCHANGETELCO','EXCHANGE ONLINE POP')
$License_name_mapping.Add('EOP_ENTERPRISE','Exchange Online Protection')
$License_name_mapping.Add('INTUNE_A','INTUNE')
$License_name_mapping.Add('AX7_USER_TRIAL','Microsoft Dynamics AX7 User Trial')
$License_name_mapping.Add('MFA_STANDALONE','Microsoft Azure Multi-Factor Authentication')
$License_name_mapping.Add('THREAT_INTELLIGENCE','Microsoft Defender for Office 365 (Plan 2)')
$License_name_mapping.Add('M365EDU_A1','Microsoft 365 A1')
$License_name_mapping.Add('M365EDU_A3_FACULTY','Microsoft 365 A3 for Faculty')
$License_name_mapping.Add('M365EDU_A3_STUDENT','MICROSOFT 365 A3 FOR STUDENTS')
$License_name_mapping.Add('M365EDU_A3_STUUSEBNFT','Microsoft 365 A3 for students use benefit')
$License_name_mapping.Add('M365EDU_A3_STUUSEBNFT_RPA1','Microsoft 365 A3 - Unattended License for students use benefit')
$License_name_mapping.Add('M365EDU_A5_FACULTY','Microsoft 365 A5 for Faculty')
$License_name_mapping.Add('M365EDU_A5_STUDENT','MICROSOFT 365 A5 FOR STUDENTS')
$License_name_mapping.Add('M365EDU_A5_STUUSEBNFT','Microsoft 365 A5 for students use benefit')
$License_name_mapping.Add('M365EDU_A5_NOPSTNCONF_STUUSEBNFT','Microsoft 365 A5 without Audio Conferencing for students use benefit')
$License_name_mapping.Add('O365_BUSINESS','MICROSOFT 365 APPS FOR BUSINESS')
$License_name_mapping.Add('SMB_BUSINESS','MICROSOFT 365 APPS FOR BUSINESS')
$License_name_mapping.Add('OFFICESUBSCRIPTION','MICROSOFT 365 APPS FOR ENTERPRISE')
$License_name_mapping.Add('OFFICESUBSCRIPTION_FACULTY','Microsoft 365 Apps for Faculty')
$License_name_mapping.Add('MCOMEETADV_GOC','MICROSOFT 365 AUDIO CONFERENCING FOR GCC')
$License_name_mapping.Add('O365_BUSINESS_ESSENTIALS','MICROSOFT 365 BUSINESS BASIC')
$License_name_mapping.Add('SMB_BUSINESS_ESSENTIALS','MICROSOFT 365 BUSINESS BASIC')
$License_name_mapping.Add('O365_BUSINESS_PREMIUM','MICROSOFT 365 BUSINESS STANDARD')
$License_name_mapping.Add('SMB_BUSINESS_PREMIUM','MICROSOFT 365 BUSINESS STANDARD - PREPAID LEGACY')
$License_name_mapping.Add('SPB','MICROSOFT 365 BUSINESS PREMIUM')
$License_name_mapping.Add('BUSINESS_VOICE_MED2','Microsoft 365 Business Voice')
$License_name_mapping.Add('BUSINESS_VOICE_MED2_TELCO','Microsoft 365 Business Voice (US)')
$License_name_mapping.Add('BUSINESS_VOICE_DIRECTROUTING','Microsoft 365 Business Voice (without calling plan) ')
$License_name_mapping.Add('BUSINESS_VOICE_DIRECTROUTING_MED','Microsoft 365 Business Voice (without Calling Plan) for US')
$License_name_mapping.Add('MCOPSTN_5','MICROSOFT 365 DOMESTIC CALLING PLAN (120 Minutes)')
$License_name_mapping.Add('MCOPSTN_1_GOV','Microsoft 365 Domestic Calling Plan for GCC')
$License_name_mapping.Add('SPE_E3','MICROSOFT 365 E3')
$License_name_mapping.Add('SPE_E3_RPA1','Microsoft 365 E3 - Unattended License')
$License_name_mapping.Add('SPE_E3_USGOV_DOD','Microsoft 365 E3_USGOV_DOD')
$License_name_mapping.Add('SPE_E3_USGOV_GCCHIGH','Microsoft 365 E3_USGOV_GCCHIGH')
$License_name_mapping.Add('SPE_E5','Microsoft 365 E5')
$License_name_mapping.Add('INFORMATION_PROTECTION_COMPLIANCE','Microsoft 365 E5 Compliance')
$License_name_mapping.Add('IDENTITY_THREAT_PROTECTION','Microsoft 365 E5 Security')
$License_name_mapping.Add('IDENTITY_THREAT_PROTECTION_FOR_EMS_E5','Microsoft 365 E5 Security for EMS E5')
$License_name_mapping.Add('SPE_E5_NOPSTNCONF','Microsoft 365 E5 without Audio Conferencing ')
$License_name_mapping.Add('M365_F1','Microsoft 365 F1')
$License_name_mapping.Add('SPE_F1','Microsoft 365 F3')
$License_name_mapping.Add('M365_F1_GOV','Microsoft 365 F3 GCC')
$License_name_mapping.Add('SPE_F5_SECCOMP ','Microsoft 365 F5 Security + Compliance Add-on ')
$License_name_mapping.Add('FLOW_FREE','MICROSOFT FLOW FREE')
$License_name_mapping.Add('MCOMEETADV_GOV','MICROSOFT 365 AUDIO CONFERENCING FOR GCC')
$License_name_mapping.Add('M365_E5_SUITE_COMPONENTS','Microsoft 365 E5 Suite features')
$License_name_mapping.Add('M365_F1_COMM','Microsoft 365 F1')
$License_name_mapping.Add('M365_G3_GOV','MICROSOFT 365 G3 GCC')
$License_name_mapping.Add('MCOEV','MICROSOFT 365 PHONE SYSTEM')
$License_name_mapping.Add('MCOEV_DOD','MICROSOFT 365 PHONE SYSTEM FOR DOD')
$License_name_mapping.Add('MCOEV_FACULTY','MICROSOFT 365 PHONE SYSTEM FOR FACULTY')
$License_name_mapping.Add('MCOEV_GOV','MICROSOFT 365 PHONE SYSTEM FOR GCC')
$License_name_mapping.Add('MCOEV_GCCHIGH','MICROSOFT 365 PHONE SYSTEM FOR GCCHIGH')
$License_name_mapping.Add('MCOEVSMB_1','MICROSOFT 365 PHONE SYSTEM FOR SMALL AND MEDIUM BUSINESS')
$License_name_mapping.Add('MCOEV_STUDENT','MICROSOFT 365 PHONE SYSTEM FOR STUDENTS')
$License_name_mapping.Add('MCOEV_TELSTRA','MICROSOFT 365 PHONE SYSTEM FOR TELSTRA')
$License_name_mapping.Add('MCOEV_USGOV_DOD','MICROSOFT 365 PHONE SYSTEM_USGOV_DOD')
$License_name_mapping.Add('MCOEV_USGOV_GCCHIGH','MICROSOFT 365 PHONE SYSTEM_USGOV_GCCHIGH')
$License_name_mapping.Add('PHONESYSTEM_VIRTUALUSER','MICROSOFT 365 PHONE SYSTEM - VIRTUAL USER')
$License_name_mapping.Add('PHONESYSTEM_VIRTUALUSER_GOV','Microsoft 365 Phone System - Virtual User for GCC')
$License_name_mapping.Add('M365_SECURITY_COMPLIANCE_FOR_FLW','Microsoft 365 Security and Compliance for Firstline Workers')
$License_name_mapping.Add('MICROSOFT_BUSINESS_CENTER','MICROSOFT BUSINESS CENTER')
$License_name_mapping.Add('ADALLOM_STANDALONE','Microsoft Cloud App Security')
$License_name_mapping.Add('WIN_DEF_ATP','MICROSOFT DEFENDER FOR ENDPOINT')
$License_name_mapping.Add('MDATP_Server','Microsoft Defender for Endpoint Server')
$License_name_mapping.Add('CRMPLAN2','MICROSOFT DYNAMICS CRM ONLINE BASIC')
$License_name_mapping.Add('ATA','Microsoft Defender for Identity')
$License_name_mapping.Add('ATP_ENTERPRISE_GOV','Microsoft Defender for Office 365 (Plan 1) GCC ')
$License_name_mapping.Add('THREAT_INTELLIGENCE_GOV','Microsoft Defender for Office 365 (Plan 2) GCC')
$License_name_mapping.Add('CRMSTANDARD','MICROSOFT DYNAMICS CRM ONLINE')
$License_name_mapping.Add('IT_ACADEMY_AD','MS IMAGINE ACADEMY')
$License_name_mapping.Add('INTUNE_A_D','Microsoft Intune Device')
$License_name_mapping.Add('INTUNE_A_D_GOV','MICROSOFT INTUNE DEVICE FOR GOVERNMENT')
$License_name_mapping.Add('POWERAPPS_DEV ','Microsoft Power Apps for Developer ')
$License_name_mapping.Add('POWERAPPS_VIRAL','Microsoft Power Apps Plan 2 Trial')
$License_name_mapping.Add('FLOW_P2','MICROSOFT POWER AUTOMATE PLAN 2')
$License_name_mapping.Add('INTUNE_SMB','MICROSOFT INTUNE SMB')
$License_name_mapping.Add('POWERFLOW_P2','Microsoft Power Apps Plan 2 (Qualified Offer)')
$License_name_mapping.Add('STREAM','MICROSOFT STREAM')
$License_name_mapping.Add('STREAM_P2','Microsoft Stream Plan 2')
$License_name_mapping.Add('STREAM_STORAGE','Microsoft Stream Storage Add-On (500 GB)')
$License_name_mapping.Add('TEAMS_FREE','MICROSOFT TEAMS (FREE)')
$License_name_mapping.Add('TEAMS_EXPLORATORY','MICROSOFT TEAMS EXPLORATORY')
$License_name_mapping.Add('MEETING_ROOM','Microsoft Teams Rooms Standard')
$License_name_mapping.Add('MS_TEAMS_IW','Microsoft Teams Trial')
$License_name_mapping.Add('EXPERTS_ON_DEMAND','Microsoft Threat Experts - Experts on Demand')
$License_name_mapping.Add('OFFICE365_MULTIGEO','Multi-Geo Capabilities in Office 365')
$License_name_mapping.Add('NONPROFIT_PORTAL','Nonprofit Portal')
$License_name_mapping.Add('STANDARDWOFFPACK_FACULTY','Office 365 A1 for faculty')
$License_name_mapping.Add('STANDARDWOFFPACK_IW_FACULTY','Office 365 A1 Plus for faculty')
$License_name_mapping.Add('STANDARDWOFFPACK_STUDENT ','Office 365 A1 for students ')
$License_name_mapping.Add('STANDARDWOFFPACK_IW_STUDENT','Office 365 A1 Plus for students')
$License_name_mapping.Add('ENTERPRISEPACKPLUS_FACULTY','Office 365 A3 for faculty')
$License_name_mapping.Add('ENTERPRISEPACKPLUS_STUDENT','Office 365 A3 for students')
$License_name_mapping.Add('ENTERPRISEPREMIUM_FACULTY','Office 365 A5 for faculty')
$License_name_mapping.Add('ENTERPRISEPREMIUM_STUDENT','Office 365 A5 for students')
$License_name_mapping.Add('EQUIVIO_ANALYTICS','Office 365 Advanced Compliance')
$License_name_mapping.Add('EQUIVIO_ANALYTICS_GOV','Office 365 Advanced Compliance for GCC')
$License_name_mapping.Add('ATP_ENTERPRISE','Microsoft Defender for Office 365 (Plan 1)')
$License_name_mapping.Add('SHAREPOINTSTORAGE_GOV','Office 365 Extra File Storage for GCC')
$License_name_mapping.Add('TEAMS_COMMERCIAL_TRIAL','Microsoft Teams Commercial Cloud')
$License_name_mapping.Add('ADALLOM_O365','Office 365 Cloud App Security')
$License_name_mapping.Add('SHAREPOINTSTORAGE','Office 365 Extra File Storage')
$License_name_mapping.Add('STANDARDPACK','OFFICE 365 E1')
$License_name_mapping.Add('STANDARDWOFFPACK','OFFICE 365 E2')
$License_name_mapping.Add('ENTERPRISEPACK','Office 365 E3')
$License_name_mapping.Add('DEVELOPERPACK','OFFICE 365 E3 DEVELOPER')
$License_name_mapping.Add('ENTERPRISEPACK_USGOV_DOD','Office 365 E3_USGOV_DOD')
$License_name_mapping.Add('ENTERPRISEPACK_USGOV_GCCHIGH','Office 365 E3_USGOV_GCCHIGH')
$License_name_mapping.Add('ENTERPRISEWITHSCAL','OFFICE 365 E4')
$License_name_mapping.Add('ENTERPRISEPREMIUM','Office 365 E5')
$License_name_mapping.Add('ENTERPRISEPREMIUM_NOPSTNCONF','OFFICE 365 E5 WITHOUT AUDIO CONFERENCING')
$License_name_mapping.Add('DESKLESSPACK','OFFICE 365 F3')
$License_name_mapping.Add('STANDARDPACK_GOV','Office 365 G1 GCC')
$License_name_mapping.Add('ENTERPRISEPACK_GOV','OFFICE 365 G3 GCC')
$License_name_mapping.Add('ENTERPRISEPREMIUM_GOV','Office 365 G5 GCC')
$License_name_mapping.Add('MIDSIZEPACK','OFFICE 365 MIDSIZE BUSINESS')
$License_name_mapping.Add('LITEPACK','OFFICE 365 SMALL BUSINESS')
$License_name_mapping.Add('LITEPACK_P2','OFFICE 365 SMALL BUSINESS PREMIUM')
$License_name_mapping.Add('WACONEDRIVESTANDARD','ONEDRIVE FOR BUSINESS (PLAN 1)')
$License_name_mapping.Add('WACONEDRIVEENTERPRISE','ONEDRIVE FOR BUSINESS (PLAN 2)')
$License_name_mapping.Add('POWERAPPS_INDIVIDUAL_USER','POWERAPPS AND LOGIC FLOWS')
$License_name_mapping.Add('POWERAPPS_PER_APP_IW','PowerApps per app baseline access')
$License_name_mapping.Add('POWERAPPS_PER_APP','Power Apps per app plan')
$License_name_mapping.Add('POWERAPPS_PER_USER','Power Apps per user plan')
$License_name_mapping.Add('POWERAPPS_PER_USER_GCC','Power Apps per user plan for Government')
$License_name_mapping.Add('POWERAPPS_P1_GOV','PowerApps Plan 1 for Government')
$License_name_mapping.Add('POWERAPPS_PORTALS_LOGIN_T2_GCC','Power Apps Portals login capacity add-on Tier 2 (10 unit min) for Government')
$License_name_mapping.Add('POWERAPPS_PORTALS_PAGEVIEW_GCC','Power Apps Portals page view capacity add-on for Government')
$License_name_mapping.Add('FLOW_BUSINESS_PROCESS','Power Automate per flow plan')
$License_name_mapping.Add('FLOW_PER_USER','Power Automate per user plan')
$License_name_mapping.Add('FLOW_PER_USER_DEPT','Power Automate per user plan dept')
$License_name_mapping.Add('FLOW_PER_USER_GCC','Power Automate per user plan for Government')
$License_name_mapping.Add('POWERAUTOMATE_ATTENDED_RPA','Power Automate per user with attended RPA plan')
$License_name_mapping.Add('POWERAUTOMATE_UNATTENDED_RPA','Power Automate unattended RPA add-on')
$License_name_mapping.Add('POWER_BI_INDIVIDUAL_USER','Power BI')
$License_name_mapping.Add('POWER_BI_STANDARD','Power BI (free)')
$License_name_mapping.Add('POWER_BI_ADDON','POWER BI FOR OFFICE 365 ADD-ON')
$License_name_mapping.Add('PBI_PREMIUM_P1_ADDON','Power BI Premium P1')
$License_name_mapping.Add('PBI_PREMIUM_PER_USER','Power BI Premium Per User')
$License_name_mapping.Add('PBI_PREMIUM_PER_USER_ADDON','Power BI Premium Per User Add-On')
$License_name_mapping.Add('PBI_PREMIUM_PER_USER_DEPT','Power BI Premium Per User Dept')
$License_name_mapping.Add('POWER_BI_PRO','Power BI Pro')
$License_name_mapping.Add('POWER_BI_PRO_CE','Power BI Pro CE')
$License_name_mapping.Add('POWER_BI_PRO_DEPT','Power BI Pro Dept')
$License_name_mapping.Add('POWERBI_PRO_GOV','Power BI Pro for GCC')
$License_name_mapping.Add('VIRTUAL_AGENT_BASE','Power Virtual Agent')
$License_name_mapping.Add('CCIBOTS_PRIVPREV_VIRAL','Power Virtual Agents Viral Trial')
$License_name_mapping.Add('PROJECTCLIENT','PROJECT FOR OFFICE 365')
$License_name_mapping.Add('PROJECTESSENTIALS','Project Online Essentials')
$License_name_mapping.Add('PROJECTESSENTIALS_GOV','Project Online Essentials for GCC')
$License_name_mapping.Add('PROJECTPREMIUM','PROJECT ONLINE PREMIUM')
$License_name_mapping.Add('PROJECTONLINE_PLAN_1','PROJECT ONLINE PREMIUM WITHOUT PROJECT CLIENT')
$License_name_mapping.Add('PROJECTONLINE_PLAN_2','PROJECT ONLINE WITH PROJECT FOR OFFICE 365')
$License_name_mapping.Add('PROJECT_P1','PROJECT PLAN 1')
$License_name_mapping.Add('PROJECT_PLAN1_DEPT','Project Plan 1 (for Department)')
$License_name_mapping.Add('PROJECTPROFESSIONAL','Project Plan 3')
$License_name_mapping.Add('PROJECT_PLAN3_DEPT','Project Plan 3 (for Department)')
$License_name_mapping.Add('PROJECTPROFESSIONAL_GOV','Project Plan 3 for GCC')
$License_name_mapping.Add('PROJECTPREMIUM_GOV','Project Plan 5 for GCC')
$License_name_mapping.Add('RIGHTSMANAGEMENT_ADHOC','Rights Management Adhoc')
$License_name_mapping.Add('RMSBASIC','Rights Management Service Basic Content Protection')
$License_name_mapping.Add('DYN365_IOT_INTELLIGENCE_ADDL_MACHINES','Sensor Data Intelligence Additional Machines Add-in for Dynamics 365 Supply Chain Management')
$License_name_mapping.Add('DYN365_IOT_INTELLIGENCE_SCENARIO','Sensor Data Intelligence Scenario Add-in for Dynamics 365 Supply Chain Management')
$License_name_mapping.Add('SHAREPOINTSTANDARD','SHAREPOINT ONLINE (PLAN 1)')
$License_name_mapping.Add('SHAREPOINTENTERPRISE','SHAREPOINT ONLINE (PLAN 2)')
$License_name_mapping.Add('Intelligent_Content_Services','SharePoint Syntex')
$License_name_mapping.Add('MCOIMP','SKYPE FOR BUSINESS ONLINE (PLAN 1)')
$License_name_mapping.Add('MCOSTANDARD','SKYPE FOR BUSINESS ONLINE (PLAN 2)')
$License_name_mapping.Add('MCOPSTN2','SKYPE FOR BUSINESS PSTN DOMESTIC AND INTERNATIONAL CALLING')
$License_name_mapping.Add('MCOPSTN1','SKYPE FOR BUSINESS PSTN DOMESTIC CALLING')
$License_name_mapping.Add('MCOPSTN5','SKYPE FOR BUSINESS PSTN DOMESTIC CALLING (120 Minutes)')
$License_name_mapping.Add('MCOPSTNPP','Skype for Business PSTN Usage Calling Plan')
$License_name_mapping.Add('MCOTEAMS_ESSENTIALS','Teams Phone with Calling Plan')
$License_name_mapping.Add('MTR_PREM','Teams Rooms Premium')
$License_name_mapping.Add('MCOPSTNEAU2','TELSTRA CALLING FOR O365')
$License_name_mapping.Add('UNIVERSAL_PRINT','Universal Print')
$License_name_mapping.Add('VISIO_PLAN1_DEPT','Visio Plan 1')
$License_name_mapping.Add('VISIO_PLAN2_DEPT','Visio Plan 2')
$License_name_mapping.Add('VISIOONLINE_PLAN1','VISIO ONLINE PLAN 1')
$License_name_mapping.Add('VISIOCLIENT','VISIO ONLINE PLAN 2')
$License_name_mapping.Add('VISIOCLIENT_GOV','VISIO PLAN 2 FOR GCC')
$License_name_mapping.Add('TOPIC_EXPERIENCES','Viva Topics')
$License_name_mapping.Add('WIN_ENT_E5','Windows 10/11 Enterprise E5 (Original)')
$License_name_mapping.Add('WIN10_ENT_A3_FAC','Windows 10 Enterprise A3 for faculty')
$License_name_mapping.Add('WIN10_ENT_A3_STU','Windows 10 Enterprise A3 for students')
$License_name_mapping.Add('WIN10_PRO_ENT_SUB','WINDOWS 10 ENTERPRISE E3')
$License_name_mapping.Add('WIN10_VDA_E3','WINDOWS 10 ENTERPRISE E3')
$License_name_mapping.Add('WIN10_VDA_E5','Windows 10 Enterprise E5')
$License_name_mapping.Add('WINE5_GCC_COMPAT','Windows 10 Enterprise E5 Commercial (GCC Compatible)')
$License_name_mapping.Add('CPC_B_2C_4RAM_64GB','Windows 365 Business 2 vCPU 4 GB 64 GB')
$License_name_mapping.Add('CPC_B_4C_16RAM_128GB_WHB','Windows 365 Business 4 vCPU 16 GB 128 GB (with Windows Hybrid Benefit)')
$License_name_mapping.Add('CPC_E_2C_4GB_64GB','Windows 365 Enterprise 2 vCPU 4 GB 64 GB')
$License_name_mapping.Add('CPC_E_2C_8GB_128GB ','"Windows 365 Enterprise 2 vCPU, 8 GB, 128 GB "')
$License_name_mapping.Add('CPC_LVL_2 ','"Windows 365 Enterprise 2 vCPU, 8 GB, 128 GB (Preview) "')
$License_name_mapping.Add('CPC_LVL_3','"Windows 365 Enterprise 4 vCPU, 16 GB, 256 GB (Preview) "')
$License_name_mapping.Add('WINDOWS_STORE','WINDOWS STORE FOR BUSINESS')
$License_name_mapping.Add('WSFB_EDU_FACULTY ','Windows Store for Business EDU Faculty')
$License_name_mapping.Add('WORKPLACE_ANALYTICS','Microsoft Workplace Analytics')

Function Get-M365FriendlyName{
    param (
        [string]$SKU_ID
    )
    if ($License_name_mapping[$SKU_ID]){
        $License_name_mapping[$SKU_ID]
    }else{
        $SKU_ID
    }
    <#
    foreach ($item in $licenselist){
        if ($item.String_Id.Trim() -eq $SKU_ID){
            (Get-Culture).TextInfo.ToTitleCase($item.Product_Display_Name.ToLower())
            break
        }
    }#>
}




$cred = Get-Credential
"Connecting to Office 365 / AzureAD v1"
try {Connect-MsolService -Credential $cred}
Catch {Connect-MsolService}
"Connecting to Exchange Online"
Connect-ExchangeOnline -UserPrincipalName $cred.UserName

Import-Module ImportExcel

#Create Log file
$global:textlog =''
function log_con {
    param( [string]$text, [string]$type='normal' )
    switch ($type){
        'warning' {Write-host $text -ForegroundColor Yellow -BackgroundColor Black}
        'error'{Write-host $text -ForegroundColor Red -BackgroundColor Black}
        'pass'{Write-host $text -ForegroundColor Green}
        default {$text}
        }
    $global:textlog = "$global:textlog$text`r`n"
}

#Create vars
$Result=""
$Output=@()
$MBUserCount=0
$OutputCount=0
$ListNonUserMailboxWithLicense=''
$ListForwarders=''
$ListForwardersRules=''
$ListAdmins=''


#Set Document storage path
#$DirSave=[environment]::getfolderpath("mydocuments")
$DirSave = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path

(Get-MsolCompanyInformation).DisplayName

#Set output file
$ExportCSV="$DirSave\$((Get-MsolCompanyInformation).DisplayName) O365 Email User Report $((Get-Date -format yyyy-MM-dd).ToString()).xlsx"
if((Test-Path -Path $ExportCSV) -eq $True) {
    Try { [io.file]::OpenWrite($ExportCSV).close() }
        Catch {$UserInput = (New-Object -ComObject wscript.shell).popup("Failed to open $ExportCSV for write access, please close excel",0,"Error Opening Output File",4) }
    Remove-Item -LiteralPath $ExportCSV -ErrorAction SilentlyContinue
}



$ExportTXT = "$DirSave\$((Get-MsolCompanyInformation).DisplayName) M365 Domain Report $((Get-Date -format yyyy-MM-dd).ToString()).txt"
Remove-Item -LiteralPath $ExportTXT -ErrorAction SilentlyContinue
$EmailList = @()
$mailbox_list = Get-Mailbox -ResultSize Unlimited | Where {$_.DisplayName -notlike "Discovery Search Mailbox"}
foreach($Mailbox in $mailbox_list){
#$mailbox_list | ForEach-Object{
    $AssignedLicense=''
    $Roles = ''
    $MFAStatus = ''
    $Aliases = ''

     $upn=$Mailbox.UserPrincipalName
     $MailboxStatistics = Get-MailboxStatistics -Identity $upn
     $LastLogonTime=$MailboxStatistics.lastlogontime
     $DisplayName=$Mailbox.DisplayName
     $MBType=$Mailbox.RecipientTypeDetails
     $Print=1
     $MBUserCount++
     $RolesAssigned=""
     Write-Progress -Activity "Scanning Mailboxs" -CurrentOperation "$MBUserCount / $($mailbox_list.Count) - $upn" -PercentComplete ($MBUserCount / $mailbox_list.Count * 100)


     #Retrieve lastlogon time and then calculate Inactive days
     if($LastLogonTime -eq $null)
     {
       $LastLogonTime ="Never Logged In"
       $InactiveDaysOfUser="-"
     }
     else
     {
       $InactiveDaysOfUser= (New-TimeSpan -Start $LastLogonTime).Days
       if ($InactiveDaysOfUser -gt 45 -and $MBType -eq 'UserMailbox'){log_con "$upn has not logged in for $InactiveDaysOfUser days" warning}
     }


     $ForwardingAddress = $Mailbox.ForwardingSmtpAddress -replace 'SMTP:'
     if ($ForwardingAddress -ne ''){ $ListForwarders = "$ListForwarders$upn -> $ForwardingAddress`r`n" }

     #Get inbox rules with forwarders
     $ruleforwarders = ''
     foreach ($rule in Get-InboxRule -Mailbox $Mailbox.UserPrincipalName){
        if ($rule.ForwardTo -ne $null -and $rule.ForwardTo -like '*@*'){
            $ruleforwarders += 'Forward to: '+ $rule.ForwardTo +'; '}
        if ($rule.RedirectTo -ne $null -and $rule.RedirectTo -like '*@*'){
            $ruleforwarders += 'Redirect to: '+ $rule.RedirectTo +'; '}
     }
     if ($ruleforwarders -ne ''){ $ListForwardersRules = "$ListForwardersRules$upn -> $ruleforwarders`r`n" }

     #Get mailbox delegates
     $delegates = Get-MailboxPermission -Identity $upn | where {$_.IsInherited -eq $false -and $_.User -like '*@*'}
     $delegates = $delegates.User -join "`r`n"
     
     if (@('SchedulingMailbox') -notcontains $Mailbox.RecipientTypeDetails){
     #Get licenses assigned to mailboxes
     $User=(Get-MsolUser -UserPrincipalName $upn)
     $Licenses=$User.Licenses.AccountSkuId
     
     $Count=0


     #Convert license plan to friendly name
     foreach($License in $Licenses)
     {
        $Count++
        $LicenseItem= $License -Split ":" | Select-Object -Last 1
        $EasyName=Get-M365FriendlyName -SKU_ID $LicenseItem
        if(!($EasyName)){
            $NamePrint=$LicenseItem
        }else{
            $NamePrint=$EasyName
        }
        if ($NamePrint -like '* Free' -or $NamePrint -like '* (Free)'){continue;}
        $AssignedLicense=$AssignedLicense+$NamePrint
        if($count -lt $licenses.count){
          $AssignedLicense=$AssignedLicense+", "
        }
     }
     if ($MBType -ne 'UserMailbox' -and $Licenses.count -ne 0 -and $AssignedLicense -ne ''){$ListNonUserMailboxWithLicense = "$ListNonUserMailboxWithLicense$upn : $AssignedLicense`r`n"}
     if($Licenses.count -eq 0){
        if ($MBType -eq 'SharedMailbox'){   
            $AssignedLicense="N/A (Shared MailBox)"
        }else{
            $AssignedLicense="No License Assigned"
        }
     }

     #Retrieve Mail Aliases
     $null = $User.ProxyAddresses.Remove("SMTP:$upn")
     $Aliases = $User.ProxyAddresses -replace 'smtp:'
     #$Aliases = $Aliases -join "; "
     $Aliases = $Aliases -join "`r`n"

          #MFA Settings
     $MFAStatus= if($User.StrongAuthenticationRequirements.State -ne $null) {
        $User.StrongAuthenticationRequirements.State
     }else{
        "Disabled"
     }

          #Get roles assigned to user
     $Roles=(Get-MsolUserRole -UserPrincipalName $upn).Name
     if($Roles.count -eq 0){
        $RolesAssigned="No roles"
     } else {
        foreach($Role in $Roles) {
            $RolesAssigned=$RolesAssigned+$Role
            if($Roles.indexof($role) -lt (($Roles.count)-1)){
                $RolesAssigned=$RolesAssigned+","
            }
        }
     }
     if ($RolesAssigned -ne 'No roles'){ $ListAdmins = "$ListAdmins$upn  -  $RolesAssigned`r`n" }

     }

     #Inactive days based filter
     if($InactiveDaysOfUser -ne "-"){
     if(($InactiveDays -ne "") -and ([int]$InactiveDays -gt $InactiveDaysOfUser))
     {
      $Print=0
     }}

     #License assigned based filter
     if(($UserMailboxOnly.IsPresent) -and ($MBType -ne "UserMailbox")){
        $Print=0
     }
 

<#     #Never Logged In user
     if(($ReturnNeverLoggedInMB.IsPresent) -and ($LastLogonTime -ne "Never Logged In")){
        $Print=0
     }
#>


     $MailboxSize = $MailboxStatistics.TotalItemSize -replace " \(.+\)"
     if ($Mailbox.ArchiveStatus -eq 'Active'){
        $MailboxArchiveStatistics =  Get-MailboxStatistics -Archive -Identity $upn
        $MailboxArchiveSize = $MailboxArchiveStatistics.TotalItemSize -replace " \(.+\)"
     }Else{
        $MailboxArchiveSize = 'N/A'
     }

     #Export result to CSV file
     if($Print -eq 1)
     {
      $OutputCount++
      $Result=[Ordered]@{'Name'=$DisplayName; 'Email Address'=$upn;'Assigned Licenses'=$AssignedLicense;'MFA Status'=$MFAStatus;'Mailbox Type'=$MBType; 'LastLogon Time'=$LastLogonTime;'Days Inactive'=$InactiveDaysOfUser;'Mailbox Size' = $MailboxSize; 'Archive Size' = $MailboxArchiveSize;'Aliases'=$Aliases;"Delegate Access" = $delegates;}
      $Output= New-Object PSObject -Property $Result
      #$Output | Select-Object Name,EmailAddress,Aliases,MailboxType,CreationTime,LastLogonTime,DaysInactive,MFAStatus,MFAType,AssignedLicenses,Roles | Export-Csv -Path $ExportCSV -Notype -Append
      #$Output | Export-Csv -Path $ExportCSV -Notype -Append
      $EmailList += $Output
      #$Result | Export-Csv -Path $ExportCSV -Notype -Append
     }
}
Write-Progress -Activity "Scanning Mailboxs" -Completed
$EmailList | export-excel -TableName SomeTable -TableStyle Medium2 -AutoSize -path $ExportCSV -FreezeTopRowFirstColumn -BoldTopRow

#Open output file after execution
Write-Host `nScript executed successfully
if((Test-Path -Path $ExportCSV) -eq $True) {
 Write-Host Result contains $OutputCount mailboxes
 Write-Host "Detailed report available in: $ExportCSV"
 $shell = New-Object -ComObject wscript.shell
 $UserInput = $shell.popup("Do you want to open the CSV report file?",0,"Open Output File",4)
 If ($UserInput -eq 6)  { Invoke-Item "$ExportCSV" }
} Else {
  Write-Host No CSV file found
}


if ($ListNonUserMailboxWithLicense -ne ''){log_con "Non user mailbox but has a license assigned`r`n$ListNonUserMailboxWithLicense" warning;}
if ($ListForwarders -ne ''){log_con "User accounts with email forwarders`r`n$ListForwarders";}
if ($ListForwardersRules -ne ''){log_con "User accounts with mailbox rules that forward to another address, Suspicous`r`n$ListForwardersRules" error;}
if ($ListAdmins -ne ''){log_con "User accounts with admin roles`r`n$ListAdmins";}

""
""
"Extra email system checks"

log_con ""
log_con "Domain Name Checks"

Foreach ($domain in Get-MsolDomain | where {$_.Name -notlike "*.onmicrosoft.com"}){
    log_con $domain.Name
    if (($domain.Capabilities.value__ -band 1) -eq 0){
        log_con " > Domain is not email enabled." info
        Continue}
    $MX = Resolve-DnsName -Name $domain.Name -Type MX
    log_con " > MX Record: $($MX.NameExchange)  $($MX.Preference)"
    $spf = (Resolve-DnsName -Name $domain.Name -Type TXT).Strings | where {$_ -like 'v=spf1*'}
    log_con " > SPF record: $spf"

    $DKIM = (Get-DkimSigningConfig -Identity $domain.Name -ErrorAction 0)
    if ($DKIM -eq $Null){
        log_con " > DKIM not configured" error
    }else{
        log_con " > DKIM Enabled: $($DKIM.Enabled)"}
        if ($DKIM.Enabled){
            if ($DKIM.RotateOnDate -lt (Get-Date)){
                $DKIM_Selector = $DKIM.SelectorAfterRotateOnDate 
            }else{
                $DKIM_Selector = $DKIM.SelectorBeforeRotateOnDate
            }
            $DKIM_Host = (Resolve-DnsName -Name "$DKIM_Selector._domainkey.$($domain.Name)" -Type CNAME -ErrorAction SilentlyContinue).NameHost
       
            if ($DKIM_Host -ne $DKIM."$($DKIM_Selector)CNAME"){
                $DKIM_Host = "WARNING: Not Configured, there may be mail delivery issues"}
            $DKIM_Value = (Resolve-DnsName -Name "$DKIM_Selector._domainkey.$($domain.Name)" -Type TXT -ErrorAction SilentlyContinue).Strings -join ''
            if ($DKIM_Value -eq $Null -or $DKIM_Value.Length -eq 0){
                $DKIM_Value = "WARNING: Not Configured, there may be mail delivery issues"
            }elseif ($DKIM_Value -eq $DKIM."$($DKIM_Selector)PublicKey".Substring(0,$DKIM_Value.Length)){
                $DKIM_Value = "Values Match: all fine here"
            }else{
                $DKIM_Value = "WARNING: DKIM Records dont Match, there may be mail delivery issues"
            }
            log_con "  >> DKIM Selector: $DKIM_Selector._domainkey.$($domain.Name)"
            log_con "  >> DKIM Host: $DKIM_Host"
            log_con "  >> DKIM Value: $DKIM_Value"
            log_con ""
        }else{
            $DKIMonline1 = (Resolve-DnsName -Name "Selector1._domainkey.$($domain.Name)" -Type CNAME -ErrorAction SilentlyContinue).NameHost
            $DKIMonline2 = (Resolve-DnsName -Name "Selector2._domainkey.$($domain.Name)" -Type CNAME -ErrorAction SilentlyContinue).NameHost
            
            if ((-not [String]::IsNullOrEmpty($DKIMonline1)) -and (-not [String]::IsNullOrEmpty($DKIMonline2)) -and ($DKIM.Selector1CNAME -eq $DKIMonline1) -and 
                ($DKIM.Selector2CNAME -eq $DKIMonline2)){
                log_con " }} Correct DNS records for DKIM were found" warning
                log_con " }} Attempting to enable DKIM now" warning
                try {Set-DkimSigningConfig -Identity $domain.Name -Enabled $True -ErrorAction Stop}
                Catch {log_con "Set-DkimSigningConfig : $($Error[0])" error}
                
            }else{
                $DKIM_Host = "N/A : DKIM not enabled"
                $DKIM_Value = "N/A : DKIM not enabled"
                log_con " }} to Enable DKIM, add these CNAME records" warning
                log_con " }} Name= Selector1._domainkey.$($domain.Name)" warning
                log_con " }} Value= $($DKIM.Selector1CNAME)" warning
                log_con " }} Name= Selector2._domainkey.$($domain.Name)" warning
                log_con " }} Value= $($DKIM.Selector2CNAME)" warning
            }
        }
log_con ""
}

log_con "License Counts"
$Licenses = Get-MsolAccountSku | Where {$_.FriendlyName -notlike '* Free' -and $_.FriendlyName -notlike '* (Free)' -and $_.SkuPartNumber -notlike '*Trial'}
foreach ($License in $Licenses){Add-Member -InputObject $License -NotePropertyName FriendlyName -NotePropertyValue $(Get-M365FriendlyName -SKU_ID $License.SkuPartNumber)}
log_con ($Licenses | Select FriendlyName,SkuPartNumber,ActiveUnits,ConsumedUnits | Format-Table | Out-String)

log_con "SMTP relay: Authorized IPs"
log_con "Check any IP's listed hare are included in the SPF record"
log_con (Get-InboundConnector | Select Name,SenderIPAddresses,Enabled | Format-Table | Out-String)


log_con "Exchange Defender: Anti-Phishing Policy"
log_con (Get-AntiPhishPolicy | select Identity, Enabled, IsDefault, IsValid | Format-Table | Out-String)

Add-Content -Path $ExportTXT -Value $global:textlog
Invoke-Item $ExportTXT

#Clean up session
Get-PSSession | Remove-PSSession

#Pause if running from console
if ($host.name -eq 'ConsoleHost') # or -notmatch 'ISE'
{
  'Press any key to continue/exit'
  $null = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}