Values

Values

Values are the fundamental beliefs that guide our behaviors, decisions, and attitudes toward life. They are the principles that define our character, shape our perspective, and determine our priorities. We learn our default values through our community and families. As we grow, we change our values. Sometimes this is to match the communities we are in, sometimes we accept other values. We do this in a subconscious manner. Normally, this process is unintentional. There is a way to create value in our life though. Let’s define how, or Values defined as my dyslexic brain likes to say.

Seven Steps overview

Here is the overview list of each step. These are understandable as they are, but I like to expand on them with the concept of loving yourself or valuing yourself. This method comes from the book “Values Clarification” by Simmon and Kirschenbaum.

  1. freely chosen
  2. chosen from a consideration of alternatives
  3. chosen with clear knowledge of the consequences
  4. prized and cherished
  5. publicly proclaimed
  6. acted on
  7. acted on repeatedly.

Freely Chosen

Firstly, if you wish for your value to stay throughout your life, you must willfully accept it. I grew up in a Christian home. My beliefs and values were given to me by my parents. At the time, I did not freely choose them. As I grew older though, I choose to accept things like, loving others, helping those in need, and more as part of my core values. However, my belief system stated I was a bad person from birth. This birthed a value of self-worthlessness. A sense of unlovability. This value was reinforced through physical and sexual abuse.

For years, I acted upon this core value. I choose not to follow my dreams and stayed in the same job I had in high school. I didn’t believe I was worth more than scooping poop out of toilets. Many years later I started believing that I was worthy of love. Eventually, I broke down the religious dogma that taught me I was worthless. It was then I freely choose the value of self-love. This was the first step to integrating this self-love and care into me.

Other values I have chosen throughout my life are some of the core values of real Christianity. Treating others as equals and not less than. Being there for people. Raising my kids in love and not hate. Allowing anger to flow in a positive way. All of these I freely chose as a child, and as an adult, I still hold true to them.

Chosen from a Consideration of Alternatives

Growing up, you don’t get a chance to consider the alternatives. As an adult, you get to. When creating a new value willfully, it’s a must. Let’s look at the value of isolationism. My Uncle was a strong Republican. When I was younger, he believed in isolationism. I was able to be part of the changing of this value. This is a value he was thought while growing up. Isolationism value states that only those born in the country should receive help from the government and/or be part of the government processes, like voting or holding governmental positions. The alternative to this is a melting pot and involvement.

He changed his view because of an Indian man challenged his political beliefs through his spiritual beliefs. He considered the man’s spiritual standing and decided to consider the alternative to his value. The man was a critical thinker and helped my uncle reach that level of thinking. Using his critical thinking skills, he considered the idea of the Melting pot. He saw that the melting pot value would bring in new ideas and help the country grow. He was able to let go of his thought value for a value that he choose freely and considered himself.

We must weigh out the alternatives. By not doing so, we rob ourselves of the truth and longevity of our value. Now consider the alternatives to not loving yourself. What are they? Hating yourself, being indifferent to yourself, treating yourself less than, treating everyone greater than one? Each value has its own consequences.

Chosen with clear Knowledge of the Consequences

Knowing the alternatives is the first step. Knowing the consequences of your actions is the next part. If you value the diversity of animal life, global warming is painful to watch as destroys animal diversity. In my uncle’s case, accepting the melting pot meant he had to accept people as people and not what he was raised to believe. He had to decode his brain and way of thinking. Undo years of training. Which he was successful at doing. This was a hard process for him as he lost friends and family members. When you share a value with someone else, and you change, it can cause conflict.

It’s important to weigh out the consequences of the value that you choose. Lets look at self-love. The consequences of choosing to love yourself are somewhat painful but fulfilling. In self love, you must learn to say no, and set boundaries. This will push people away from you. As it is natural for people to take advantage of those who don’t love themselves.

Another consequence of self-love is integrating yourself. No longer can you say, I’m just born that way. Instead, you have to face your hurts and work through them. If you are comfortable with your current life and don’t want to grow, loving yourself is going to be hard as it forces you to grow.

However, loving yourself means you will grow. It means you will become whole. It means you will be happier with who you are. At one point or another, you will look in the mirror and not be disappointed to see yourself.

Value must be Prized and Cherished

Looking back at my Uncle. Before changing his values, he use to say something along the lines of, “all these people coming to our country stealing our jobs.” After changing his values, he said “What a beautiful mosaic of people. This is how we grow together.” To his deathbed, he cherished all races and people. He was excited when he heard of a governor for another country taking office. He would call them “Fresh Views” He went out of his way to help everyone equally.

In choosing to love yourself, You have to cherish moments where you do love yourself. For me, I cherish my front porch. I set a boundary of keeping it livable. Now, I sit on the porch each night and watch the sunset. I play with the kids on the front porch. School bus students have a place to sit and talk. I stand firm on my boundary as it is a way of self-love for me. You have to look at where your value brings you and what it does. Hold those to your heart. Remind yourself of them because it’s easy to forget.

Publicly Proclaimed

Next, you must be public about your value. Going back to my uncle, he did this by how he voted. When he spoke with other members of his family, and how he lived his life. Yes, he lost friends, however, going public kept him accountable. Baptists use baptism for this purpose when someone accepts Jesus. They take a public dunking in water to show all their friends and family what they believe and the values attached to that belief. During the start of Christianity, this would get you killed. Now-a-day, people clap.

When it comes to self-love, setting things like setting boundaries shows people that you are treating yourself better. Being willing to say, “I’m going to take some time for myself” and meaning it, shows it publically. Other things like taking care of your hair, shaving, exercising, going to the doctor, and more all show it. With self-love, the act of acting upon it is your public proclamation.

Act-On Your Values

It’s time to act on your values. If you value human life, you will help human life. A pro-life, states they love a child and want to see a child be born. It’s not a true value if the person doesn’t support adoption. It’s not a value if the person wants to defund programs that help mothers take care of their children. Free day care and other items should fall into pro-life. However, we don’t see it.

Acting upon your values is the meat and potato of the value. It gives the value, value. My uncle valued the melting pot. He Choose to vote and support those with good ideas, no matter what their nationality was. I saw him debate more than once with his former isolationists and even converted a few. He acted upon his value which enforced his value.

When it comes to self love, you have to act upon it. Taking care of your body is the start of self-love. When someone starts to value themselves, you will notice they will dress better. I started brushing my teeth each night. A family member chose to go to more social events and meet new people. There are many ways to act upon self-love. One way to proclaim it each morning. Try using the following statement:

I love myself. I will accept myself unconditionally.

Acting upon it over and over again

I am someone who likes to get projects off the ground and launch them into the sky. I’m an activator. If you want a dead project resurrected from its death, call me. However, I struggle with keeping it going once it was in the sky. This is very important. If you start reinforcing your chosen value, previous values will slip back in. As one man told me, it takes half the time to create a new habit when you are intentional than when you created the habit unintentionally.

To build the value, you must build the habit of that value. The action of acting on that value over and over again. It has to be drilled into your head. Especially if you have had values that are alternatives to your current values. Uncle would watch multiple news outlets instead of the same one. Always looking for fresh ideas and such. His actions reinforced his beliefs and values. Thus, at his funeral, he had a large crowd of people. The speaker said he had an open mind and it showed.

To love yourself, you have to take care of yourself daily. Brush your teeth each day. Take time for yourself each day. It’s ok to take care of yourself.

Final thoughts

Taking our values at face level will at some point fail us. We have to reevaluate our values from time to time. We need to make sure they still hold true to us. If they don’t, it’s time to let them go or reup those values. It’s not easy to make a new value. We are talking about the core of self when rebuilding a value. It takes time. There are no overnight changes in this world. As I have learned, there are three stages, initializing, processing, and defaulting. We have to initialize that change. We have to process it each day, sometimes multiple times a day, and then at some point, it becomes default behavior.

Continue Reading

O365 Mobile Devices

O365 Mobile Devices

I needed to grab all the mobile devices that had emails attached to them not too long ago. I could have gone through the GUI, and spent a few days trying my best to document everything, or I could use Powershell to pull the O365 Mobile Devices. Can you guess which one I did? Yep, PowerShell is a way of thinking nowadays in the system admin world.

The Script

Connect-ExchangeOnline
$Mailboxes = get-mailbox -all
$Devices = foreach ($Mail in $Mailboxes) {
    $MobileDevices = Get-MobileDevice -Mailbox $mail.userprincipalname
    foreach ($Device in $MobileDevices) {
        $Stats = Get-MobileDeviceStatistics -Identity $Device.Identity
        [pscustomobject]@{
            User = $mail.userprincipalname
            FriendlyName                  = $Device.FriendlyName
            name                          = $Device.name
            Identity                      = $Device.Identity
            DeviceID                      = $Device.DeviceId
            DeviceOS                      = $Device.DeviceOS
            DeviceType                    = $Device.DeviceType
            DeviceModel                   = $Device.DeviceModel 
            ClientType                    = $Stats.ClientType
            FirstSyncTime                 = $Device.FirstSyncTime
            WhenChanged                   = $Device.WhenChanged
            LastPolicyUpdateTime          = $Stats.LastPolicyUpdateTime
            LastSyncAttemptTime           = $Stats.LastSyncAttemptTime
            LastSuccessSync               = $stats.LastSuccessSync
            DeviceAccessState             = $Device.DeviceAccessState
            DeviceAccessStateReason       = $Device.DeviceAccessStateReason
            IsValid                       = $Device.IsValid
            Status                        = $Stats.Status
            DevicePolicyApplied           = $stats.DevicePolicyApplied
            DevicePolicyApplicationStatus = $stats.DevicePolicyApplicationStatus
        }
    }
}
$Devices

The Break Down

This script is pretty straightforward. We first connect to exchange online. Currently, this script is designed to work with MFA. Then we grab all the mailboxes from O365.

Connect-ExchangeOnline
$Mailboxes = get-mailbox -all

Next, we loop through these mailboxes. We drop all the information get gather from this loop into a variable. I called my devices. Once again, nothing great or grand.

$Devices = foreach ($Mail in $Mailboxes) {}

For each mailbox we have, we pull all of the devices from that mailbox. Since a single mailbox can have more than one device, we loop through these devices. For each loop, we want to grab that device’s stats to gain more insights.

$MobileDevices = Get-MobileDevice -Mailbox $mail.userprincipalname
    foreach ($Device in $MobileDevices) {
        $Stats = Get-MobileDeviceStatistics -Identity $Device.Identity

Finally, from there we gather the information into a single object. These commands produce a lot of information. It’s best to parse it down some. That’s what I did with the next part. That’s how I am able to get all the O365 Mobile Devices using PowerShell.

Additional Reading

Set Telemetry with Powershell

Set Telemetry with Powershell

Windows 10 and 11 have a unique feature called telemetry. This feature allows Microsoft to track your device. For security reasons, it’s best to disable this, however, for a home level, this feature is useful. So, let’s Set Telemetry with Powershell.

Registry Keys and Services

There are 4 registry keys that can do this.

  • HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection\AllowTelemetry
  • HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection\AllowDeviceNameInTelemetry
  • HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\AllowTelemetry
  • HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection\AllowTelemetry

Along with the registry keys you will need to work with a service called “Diagtrack“. This service while active, can track your computer. To disable telemetry, we must disable diagtrack from the startup and we can do that with Powershell.

Disable Telemetry

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowDeviceNameInTelemetry" -Type DWord -Value 0
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0
Set-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0

Get-Service -Name "DiagTrack" | Stop-Service -NoWait -Force
Get-Service -Name "DiagTrack" | set-service -StartupType Disabled

Here we are adding different values. We are setting our 4 registry keys to 0. Then we stop the diagtrack server. Then we set the startup to disabled, This way the service can’t be restarted.

Doing this ensures that the service doesn’t come back to life and if it does, it has no idea what to do.

Enable Telemetry

Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry"
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowDeviceNameInTelemetry"
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry"
Remove-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry"

Get-Service -Name "DiagTrack" | set-service -StartupType Manual
Get-Service -Name "DiagTrack" | start-service

To enable telemetry, we are simply doing the opposite. We remove the registry keys. Then we enable the services. Finally, we start the service.

There you have it, We have Set telemetry with Powershell

Additional Reading

Validate Script Explained

Validate Script Explained

PowerShell is a versatile scripting language that can help automate various tasks for system administrators and developers. One of its key features is the ability to validate script parameters, which can help ensure that the user inputs the correct data. In this blog post, we will explore PowerShell’s Validate Script parameter set and provide examples of how it can be used to test if a webpage is active.

Validate Script is a parameter attribute in PowerShell that allows you to validate the data input by the user before the script executes. This parameter set can be used to define a script block that will be used to test if the input value is valid. The script block should return a boolean value, indicating whether the input is valid or not. If the script block returns false, the user will receive an error message.

To use Validate Script, you need to include it in the parameter block of your PowerShell script. For example:

Param(
    [ValidateScript({Test-Path $_})]
    [string]$Path
)

In this example, the ValidateScript parameter is used to validate the Path parameter. The Test-Path cmdlet is used to test if the input path exists. If the path exists, the script block will return true, and the script will continue executing. Otherwise, the user will receive an error message.

Now, let’s see how ValidateScript can be used to test if a webpage is active. For this, we can use the Test-NetConnection cmdlet to test if the webpage is reachable. Here’s an example:

Param(
    [ValidateScript({Test-NetConnection $_})]
    [string]$Webpage
)

Write-Host "Webpage $Webpage is active."

In this example, the ValidateScript parameter is used to validate the Webpage parameter. The Test-NetConnection cmdlet is used to test if the input webpage is reachable. If the webpage is reachable, the script block will return true, and the Write-Host cmdlet will output a message indicating that the webpage is active.

In conclusion, PowerShell’s ValidateScript parameter set is a powerful feature that can help ensure that the user inputs the correct data. By defining a script block to test the input value, you can ensure that the script will only execute if the input is valid. By using PowerShell cmdlets like Test-Path and Test-NetConnection, you can create custom validation rules to suit your needs. Use this feature wisely and make your scripts more robust and reliable.

Truth

This blog post was created with Chat GPT, what do you think? I don’t like doing 100% auto-generated content like chat gpt. Instead, what I would prefer to do is take the information and work it out. Bring something better and easier to understand. The Chat GPT doesn’t produce SEO good items as well. It produces Passive Voice and requires adjustment. I will not be using Chat GPT to auto-generate blogs like this. If I do need to use the tool, I will always work it and make it much better for you all.

Exchange Mailbox Rules

Exchange Mailbox Rules

At one of my previous Jobs, I had to write a script to help me understand rules. Well, I pulled that script out of the vault to do the same thing recently. The following script will allow you to select one user or multiple users to grab their rules. Or you can just forget the flag and get all of the users at once. The idea of the script is to get basic information from the rule, not all the information as it’s not all useful. So let’s look at the script then we will do a breakdown. Here comes Exchange Mailbox Rules through PowerShell.

The script

function Get-MailboxInboxRules {
    [cmdletbinding()]
    param (
        [string[]]$UserPrincipalName,
        [switch]$StayConnected
    )
    begin {
        #Begining tests if the module is installed, loaded, and connected. Correcting each one at each level. 

        #Installs required modules
        Write-Verbose "Installing required modules"
        if (!(Get-InstallEdModule ExchangeOnlineManagement)) { 
            try {
                Install-Module ExchangeOnlineManagement
            }catch {
                Write-Error $_
                exit
            } 
        }
 
        Write-Verbose "Checking and importing required modules"
        # Starts importanting required modules
        if (!(Get-Command Connect-ExchangeOnline)) { 
            try {
                Import-Module ExchangeOnlineManagement
            } catch {
                Write-Error $_
                exit
            }
        }

        #Tests if Exchange Online is connected, If not, we trigger a connection
        if (!(Get-PSSession | Where-Object { $_.Name -match 'ExchangeOnline' -and $_.Availability -eq 'Available' })) { 
            try {
                Connect-ExchangeOnline}
            catch {
                Write-Error $_
                exit
            } 
        }
        if (!(Get-PSSession | Where-Object { $_.Name -match 'ExchangeOnline' -and $_.Availability -eq 'Available' })) {
            Write-Error "Connection failed"
            exit
        }
    }
    Process {
        $mailboxes = @()
        if (!($PSBoundParameters.ContainsKey("UserPrincipalName"))) {
            $Mailboxes = Get-mailbox
        }
        else {
            foreach ($Username in $UserPrincipalName) {
                try {
                    $Mailboxes += get-mailbox $username -ErrorAction SilentlyContinue
                }
                catch {
                    Write-Warning "$username has no mailbox"
                }
            }
        }

        #It has been proven to speed up the script if we drop the output into a return value
        $RulesReturn = Foreach ($Mail in $Mailboxes) {
            
            Write-Verbose "Scanning: $($Mail.UserPrincipalName)"
            #We are now trying to catch the rule in question. 
            #if the mailbox has no rules, which will be presented as an error, then we null out the rules. 
            try {
                $Rules = Get-InboxRule -Mailbox $Mail.Userprincipalname
            }
            catch {
                $Rules = $null  
            }

            #Now that the rules either have value or null, we can test. 
            if ($null -ne $Rules) {
                #Write-Host "$($mail.userprincipalname)"

                #Now we know we have rules, it's time to start working with those rules
                foreach ($Rule in $Rules) {

                    #From my testing I discover that some rules will be null but the rule itself isn't null. 
                    #Thus we need to test if this is the case. 
                    if ($null -ne $rule) {

                        #Now we have confirmed the rule is not empty, we need to test the form
                        #This is because some rules are based on subjects and such and not from people. 
                        if ($null -ne $rule.from) {
                            
                            #since form is not empty we split the string and we get the from information. 
                            $froms = $Rule.from.split('[')[0]
                        }
                        else {

                            #if it is, we just blank string the value. 
                            $froms = ""
                        }

                        #Next we want the description to be on a single line. this way we can export to a csv. 
                        if ($null -ne $rule.description) {

                            #This is programmed for the standard 5.1 powershell. Join-String was introduced in 6.2
                            #to combat this, we create a null return
                            #Then we  split the description rule. 
                            #Then we for each that list and push it back into the return.
                            
                            $dereturn = $Null
                            $rule.description.split("`n") | foreach-object { $dereturn = "$dereturn $($_.trim())" }
                            $description = $dereturn.trim()
                        }
                        else {
                            $description = ""
                        }
                        #Next we create our ps object with items we need for basic level audits. 
                        [pscustomobject]@{
                            Username    = $Mail.Userprincipalname
                            Identity    = $Rule.Identity
                            Enabled     = $Rule.Enabled
                            Name        = $Rule.Name
                            from        = $froms
                            Description = $description
                        } 
                    }
                }
            }
        }
    }
    end {

        #At the end we return
        $RulesReturn

        #Then we disconnect if the user didn't say stay connected. 
        if (!($StayConnected)) { Disconnect-ExchangeOnline -Confirm:$false }
    }
}

The Breakdown

Before we begin, I want to point out, at this point, there is no graph API calls for exchange. Not yet, its promised, but as of right now, it’s not reality yet. Security is a big thing to think about with scripts like these. MFA is a big piece of security. We always want some mfa going. This is why you will not see credentials in the parameters.

Parameters

Our parameters are simple. We have a list of strings of user principal names and we have a switch to determine if we need to stay connected. If we leave the user principal name blank, then we are targeting every mailbox. It may take some time. The stay connected is designed to keep exchange connected. This way once you have the exchange mailbox rules, you can run other commands. You can also leave this blank, if you do, it disconnects from exchange. Good security thinking here.

param (
        [string[]]$UserPrincipalName,
        [switch]$StayConnected
)

Begin

Next is our begin. We are doing some house keeping here. First, We need to know if the exchange online management is installed. if it’s not, we then install it. Next, test if the exchange online management is imported. if not, we import the module. Finally we test if we have an exchange online connection, if not, we use connect-exchange. We use the connect-exchangeonline because it will do the MFA for us. Which is nice.

To test if the module is installed, we use the Get-InstalledModule. This command searches your modules and lets you know if it is installed. Older Powershells do not know this command. If the powershell is not elevated, then this code will error out and exits with the exit code.

Write-Verbose "Installing required modules"
if (!(Get-InstallEdModule ExchangeOnlineManagement)) { 
        try {
            Install-Module ExchangeOnlineManagement
        }catch {
            Write-Error $_
            exit
        } 
}

If we haven’t exited out yet, we then see if the module is loaded by using the get-command command. We are looking for the command Connect-ExchangeOnline. If the command exists, we will continue on, if not, we will use the import-module command and import the exchangeonlinemanagement module. Of course, if we run into an error, we exit with the error.

Write-Verbose "Checking and importing required modules"
# Starts importanting required modules
if (!(Get-Command Connect-ExchangeOnline)) { 
    try {
        Import-Module ExchangeOnlineManagement
    } catch {
        Write-Error $_
        exit
    }
}

Finally, we are going to pull all the PowerShell Sessions currently on this computer. This is where we will gain the ability to pull Exchange Mailbox Rules. The first command is get-pssession. We search the output for a session with the name of ExchangeOnline that is available. If we don’t find one, we connect to exchange using the connect-exchangeonline. Next, if connection errors out, we present the error and disconnect. Now, if the connection is successful, we test once more for a connection. If it’s just not there, we give up and say bye.

#Tests if Exchange Online is connected, If not, we trigger a connection
        if (!(Get-PSSession | Where-Object { $_.Name -match 'ExchangeOnline' -and $_.Availability -eq 'Available' })) { 
            try {
                Connect-ExchangeOnline}
            catch {
                Write-Error $_
                exit
            } 
        }
        if (!(Get-PSSession | Where-Object { $_.Name -match 'ExchangeOnline' -and $_.Availability -eq 'Available' })) {
            Write-Error "Connection failed"
            exit
        }

Process – Exchange Mailbox Rules

Check Mailboxes

Now we are connected to exchange online, it’s time to start grabbing the needed information. Before we start, we need to establish an array for possible mailboxes. We will call these mailboxes to make life easy.

$mailboxes = @()

Now, whether or not the user used the “UserPrincipalName” parameter or not, we are ready. The next step is to test if we used the parameter and grab those mailboxes. We do this by using the $PSBoundParameters variable. Searching the Contains key allows you to see what parameters are being passed to the script. in our case we will be searching for the user principal name. If there is no UPN, we just grab all the mailboxes and dump it into the $mailboxes variable we made.

Now, if we did use the upn, we will loop through the UPN and grab each mailbox accordingly. if there is an issue, we let the user know that that username was an issue. This will give us the mailbox information we need. We do this separately because it causes fewer errors. Best way to describe it is using this method is the bouncer. It bounces issues out the door before we start looking at the inbox rules.

$mailboxes = @()
        if (!($PSBoundParameters.ContainsKey("UserPrincipalName"))) {
            $Mailboxes = Get-mailbox
        }
        else {
            foreach ($Username in $UserPrincipalName) {
                try {
                    $Mailboxes += get-mailbox $username -ErrorAction SilentlyContinue
                }
                catch {
                    Write-Warning "$username has no mailbox"
                }
            }
        }

Exchange Mailbox Rules

The next step is to grab the rules themselves. We start off by making a for each loop. The loop of course is going to drop into a variable. We do this because it has been found that dropping the output of a foreach loop into a variable is a faster method than rebuilding or appending an array.

$RulesReturn = Foreach ($Mail in $Mailboxes) {}

Now, it’s time to hang onto your hats. The rules are tricky as they error out. We see errors because the end user will create a rule, and abandon it. It has nothing to do with your code. It is purely what it is.

The first thing we need to do inside our loop is grab the rules for the mailbox. The command is Get-InboxRule. We will be placing the rules into a variable called Rules. Now here is the catch. This command will produce something. So throw it in a try catch. So if it produces an error, which happens, you can set the Rules to null.

Inbox Rules

try {
    $Rules = Get-InboxRule -Mailbox $Mail.Userprincipalname
} catch {
    $Rules = $null  
}

Next, we test if the Rules are null, if not, we start the loop. Here is another fun part… If the rule is misconfigured, it will present as null from time to time. So we need to test for the null again per rule.

if ($null -ne $Rules) {
    Write-Verbose "$($mail.userprincipalname)"
    foreach ($Rule in $Rules) {
        if ($null -ne $rule) {}
    }
}

Parsing the data

Some rules are based on subject, some rules are based on email. It’s best that we grab useful information. Things like the description, and from are presented in string format with unique structures. However, sometimes those can be null strings and that will explode the results as well. So we have to test them. First we will test the from. if the from is not null, we want to split the from, from the bracket and select the first item. However, if the from is null, we want to give the from a blank string as a psobject doesn’t like null.

if ($null -ne $rule.from) {
    $froms = $Rule.from.split('[')[0]
} else {
    $froms = ""
}

After the From, we need to grab the description. However, I need this description on a single line. As most people are using PowerShell 5, Join-String is not available. Which is sad. So, I built my own join-string. To do this, first create a null return. Then split the Rules description by the enter, `n. Next we do a foreach-object loop, taking that null return value and added itself to itself with a nice trim. Finally, I dropped that information into the description. If the description was null to begin with we drop a blank string into the description variable.

if ($null -ne $rule.description) {
    $dereturn = $Null
    $rule.description.split("`n") | foreach-object { $dereturn = "$dereturn $($_.trim())" }
    $description = $dereturn.trim()
} else {
    $description = ""
}

Bringing it together

Finally, we have all the information we need. It’s time to create the PS Custom Object. Here we will be presenting the username, the ID of the rule, if the rule is enabled, the from, and the description. Since we joined the strings of the description before, this output can be exported to a csv file. Remember at the beginning of the main loop, we are placing all the output of that loop into a variable called Rules Return. Well, this is what will be going into that variable.

[pscustomobject]@{
    Username    = $Mail.Userprincipalname
    Identity    = $Rule.Identity
    Enabled     = $Rule.Enabled
    Name        = $Rule.Name
    from        = $froms
    Description = $description
} 

End

Finally, we reach the end of this script. We are doing two things at the end of this script. First, we are presenting the data. Then we are testing if we need to stay connected. We present the variable Rules Return. Then we check if Stay Connected is true. If it isn’t we disconnect from exchange with a confirmation of false. If you set the flag to stay connected when you executed the code, then this part only shows the rules. No need to disconnect. I always love having this option as exchange online is a pain with multiple MFA layers.

$RulesReturn
if (!($StayConnected)) { Disconnect-ExchangeOnline -Confirm:$false }

Continue Reading:

As always, I like to present some items at the end to encourage you to continue reading.