Scripts/InitScript.ps1
[CmdLetBinding()] # Detect installed module version $ModuleRootPath = Split-Path -Path $PSScriptRoot -Parent $ManiFestFile = Import-PowerShellDataFile -Path $ModuleRootPath/SEPPmail365cloud.psd1 $Global:ModuleVersion = $ManiFestFile.ModuleVersion.ToString() [string]$requiredPSVersion = '7.4.6' $requiredModules = @{ "ExchangeOnlineManagement" = "3.7.0" "DNSClient-PS" = "1.1.1" "PSWriteHTML" = "1.27.0" } Write-Host "+---------------------------------------------------------------------+" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| Welcome to the SEPPmail.cloud PowerShell setup module version $ModuleVersion |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| Please read the documentation if you are unfamiliar |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| with the module and its CmdLets before continuing ! |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| https://docs.seppmail.com/en/cloud/c07_cloud_powershell.html |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| Press <CTRL><Click> to open the Link |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "| |" -ForegroundColor Green -BackgroundColor DarkGray Write-Host "+---------------------------------------------------------------------+" -ForegroundColor Green -BackgroundColor DarkGray Write-Verbose "Running InitScript.ps1 and doing requirement-checks" if ($sc365noTests -ne $true) { if ((Get-PSRepository -Name PSGallery).InstallationPolicy -ne 'Trusted') { Write-Warning "You do not Trust the PowerShellGallery as a module installation source." Write-Output "Run 'Set-PSRepository -Name PSGallery -Trusted' to avoid confirmation on module installs." } Write-Verbose "Create Helper function for Version checking" <# .SYNOPSIS Parses a semantic version string and converts it into a structured object. .DESCRIPTION The `ConvertTo-SemanticVersion` function takes a version string that conforms to the Semantic Versioning (SemVer) standard and parses it into its components: Major, Minor, Patch, PreRelease, and BuildMetadata. If the input string is not a valid semantic version, the function throws an error. The SemVer format includes: - A version core: `MAJOR.MINOR.PATCH` - Optional pre-release information: `-<pre-release>` - Optional build metadata: `+<build-metadata>` .EXAMPLE ConvertTo-SemanticVersion -VersionString "1.2.3-alpha+build123" Returns: @{ Major = 1 Minor = 2 Patch = 3 PreRelease = "alpha" BuildMetadata = "build123" } .EXAMPLE ConvertTo-SemanticVersion -VersionString "4.5.6" Returns: @{ Major = 4 Minor = 5 Patch = 6 PreRelease = $null BuildMetadata = $null } .INPUTS [string] You must provide a semantic version string as input. The string must conform to the SemVer format. .OUTPUTS [hashtable] The function returns a hashtable with the following keys: - `Major` ([int]): The major version number. - `Minor` ([int]): The minor version number. - `Patch` ([int]): The patch version number. - `PreRelease` ([string]): The pre-release label, or `$null` if not specified. - `BuildMetadata` ([string]): The build metadata, or `$null` if not specified. .NOTES - The function validates the format of the input string using a regular expression. - If the input does not conform to the SemVer format, an exception is thrown. .LINK Semantic Versioning Specification: https://semver.org/ #> function ConvertTo-SemanticVersion { param ( [string]$VersionString ) if ($VersionString -match '^(\d+)\.(\d+)\.(\d+)(?:-([\w\-\.]+))?(?:\+([\w\-\.]+))?$') { return @{ Major = [int]$matches[1] Minor = [int]$matches[2] Patch = [int]$matches[3] PreRelease = $matches[4] BuildMetadata = $matches[5] } } else { throw "Invalid semantic version format: $VersionString" } } Write-verbose "Check PowerShell Version" [String]$instPSVersion = ((($PSVersionTable.PSVersion.ToString())) -Split '\.')[0..2] -join '.' if ($PSVersionTable.PSEdition -eq "Desktop") { Write-Host "+------------------------------------------------------+" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "| !!! Wrong PowerShell EDITION !!! |" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "| The module does not support |" -ForegroundColor Red -BackgroundColor Black Write-Host "| Windows Powershell 5.1 Desktop and earlier |" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "| PLEASE install PowerShell CORE $requiredPSVersion+ |" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "+------------------------------------------------------+" -ForegroundColor Red -BackgroundColor Black Break } else { $minPSVersion = [System.Management.Automation.SemanticVersion]::Parse($requiredPSVersion) $instPSVersion = [System.Management.Automation.SemanticVersion]::Parse($InstPSVersion) if ($minPSVersion -gt $instPSVersion) { Write-Host "+------------------------------------------------------+" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "| !!! Wrong PowerShell VERSION !!! |" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "| PLEASE install PowerShell CORE $minPSVersion+ |" -ForegroundColor Red -BackgroundColor Black Write-Host "| |" -ForegroundColor Red -BackgroundColor Black Write-Host "+------------------------------------------------------+" -ForegroundColor Red -BackgroundColor Black Break } } Write-Verbose "PowerShell version is $instPSVersion and equal or newer than required version $requiredPSVersion" Write-Verbose "Create Helper function for module installation" <# .SYNOPSIS Installs a PowerShell module or resource from a repository using the appropriate installation command. .DESCRIPTION The `Invoke-RepoInstall` function checks if the `Install-PSResource` command is available. If available, it uses it to install or reinstall the specified artifact. If not, it defaults to using `Install-Module` for installation. This function ensures compatibility with both older and newer versions of PowerShell's module management tools. .PARAMETER artefact The name of the module or resource to be installed from the repository. .EXAMPLE Invoke-RepoInstall -artefact 'ExchangeOnlineManagement' This command installs or reinstalls the `ExchangeOnlineManagement` module. .EXAMPLE Invoke-RepoInstall -artefact 'PSWriteHTML' This command installs or reinstalls the `PSWriteHTML` module. .NOTES - This function simplifies module installation by abstracting the differences between `Install-Module` and `Install-PSResource`. - Requires the appropriate repository (e.g., PSGallery) to be registered and accessible. .OUTPUTS None. .INPUTS [string] Accepts the name of the module or resource as a string. #> function Invoke-RepoInstall { param ( [string]$artefact, [string]$artefactVersion ) if (!(Get-Command -Name 'Install-PSResource' -ErrorAction SilentlyContinue)) { #$RepoInstallMethod = 'Module' $InstCommandString = "Install-Module $artefact -requiredVersion $artefactVersion -force -WarningAction SilentlyContinue" } else { $InstCommandString = "Install-PSResource $artefact -Version $artefactVersion -Reinstall -WarningAction SilentlyContinue" } Invoke-Expression $InstCommandString } Write-Verbose "Check required Module availability" foreach ($module in $requiredModules.Keys) { $version = $requiredModules[$module] if (!(Get-Module $module -ListAvailable)) { try { Write-Verbose "Installing required module $module" -InformationAction Continue Invoke-RepoInstall -artefact $module -artefactVersion $version } catch { Write-Error "Could not install required Module $module with version $version. Please install manually from the PowerShell Gallery" } Import-Module $module -Force } } } Write-Verbose 'Initialize argument completer scriptblocks' $script:paramDomSB = { # Read Accepted Domains for domain selection param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $tenantAcceptedDomains.Domain | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { "'$_'" } } # SIG # Begin signature block # MIIVzAYJKoZIhvcNAQcCoIIVvTCCFbkCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDwiv4/dk9TGH7R # ynbW0dCEdwAQfZND9TQP2GHVtjQMYaCCEggwggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M # UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD # VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv # ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5 # NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp # BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G # CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI # ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV # DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3 # 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw # mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm # +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe # dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4 # 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM # dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY # MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU # pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV # HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG # A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG # AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl # U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0 # aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh # w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd # OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj # cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc # WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO # hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs # zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7 # 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J # KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH # j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2 # Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/ # L9Uo2bC5a4CH2RwwggZzMIIE26ADAgECAhAMcJlHeeRMvJV4PjhvyrrbMA0GCSqG # SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw # HhcNMjMwMzIwMDAwMDAwWhcNMjYwMzE5MjM1OTU5WjBqMQswCQYDVQQGEwJERTEP # MA0GA1UECAwGQmF5ZXJuMSQwIgYDVQQKDBtTRVBQbWFpbCAtIERldXRzY2hsYW5k # IEdtYkgxJDAiBgNVBAMMG1NFUFBtYWlsIC0gRGV1dHNjaGxhbmQgR21iSDCCAiIw # DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOapobQkNYCMP+Y33JcGo90Soe9Y # /WWojr4bKHbLNBzKqZ6cku2uCxhMF1Ln6xuI4ATdZvm4O7GqvplG9nF1ad5t2Lus # 5SLs45AYnODP4aqPbPU/2NGDRpfnceF+XhKeiYBwoIwrPZ04b8bfTpckj/tvenB9 # P8/9hAjWK97xv7+qsIz4lMMaCuWZgi8RlP6XVxsb+jYrHGA1UdHZEpunEFLaO9Ss # OPqatPAL2LNGs/JVuGdq9p47GKzn+vl+ANd5zZ/TIP1ifX76vorqZ9l9a5mzi/HG # vq43v2Cj3jrzIQ7uTbxtiLlPQUqkRzPRtiwTV80JdtRE+M+gTf7bT1CTvG2L3scf # YKFk7S80M7NydxV/qL+l8blGGageCzJ8svju2Mo4BB+ALWr+gBmCGqrM8YKy/wXR # tbvdEvBOLsATcHX0maw9xRCDRle2jO+ndYkTKZ92AMH6a/WdDfL0HrAWloWWSg62 # TxmJ/QiX54ILQv2Tlh1Al+pjGHN2evxS8i+XoWcUdHPIOoQd37yjnMjCN593wDzj # XCEuDABYw9BbvfSp29G/uiDGtjttDXzeMRdVCJFgULV9suBVP7yFh9pK/mVpz+aC # L2PvqiGYR41xRBKqwrfJEdoluRsqDy6KD985EdXkTvdIFKv0B7MfbcBCiGUBcm1r # fLAbs8Q2lqvqM4bxAgMBAAGjggGpMIIBpTAfBgNVHSMEGDAWgBQPKssghyi47G9I # ritUpimqF6TNDDAdBgNVHQ4EFgQUL96+KAGrvUgJnXwdVnA/uy+RlEcwDgYDVR0P # AQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwSgYD # VR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9z # ZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6 # Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYu # Y3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEFBQcwAoY4aHR0cDovL2NydC5zZWN0 # aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcnQwIwYIKwYB # BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMB4GA1UdEQQXMBWBE3N1cHBv # cnRAc2VwcG1haWwuY2gwDQYJKoZIhvcNAQEMBQADggGBAHnWpS4Jw/QiiLQi2EYv # THCtwKsj7O3G7wAN7wijSJcWF7iCx6AoCuCIgGdWiQuEZcv9pIUrXQ6jOSRHsDNX # SvIhCK9JakZJSseW/SCb1rvxZ4d0n2jm2SdkWf5j7+W+X4JHeCF9ZOw0ULpe5pFs # IGTh8bmTtUr3yA11yw4vHfXFwin7WbEoTLVKiL0ZUN0Qk+yBniPPSRRlUZIX8P4e # iXuw7lh9CMaS3HWRKkK89w//18PjUMxhTZJ6dszN2TAfwu1zxdG/RQqvxXUTTAxU # JrrCuvowtnDQ55yXMxkkSxWUwLxk76WvXwmohRdsavsGJJ9+yxj5JKOd+HIZ1fZ7 # oi0VhyOqFQAnjNbwR/TqPjRxZKjCNLXSM5YSMZKAhqrJssGLINZ2qDK/CEcVDkBS # 6Hke4jWMczny8nB8+ATJ84MB7tfSoXE7R0FMs1dinuvjVWIyg6klHigpeEiAaSaG # 5KF7vk+OlquA+x4ohPuWdtFxobOT2OgHQnK4bJitb9aDazGCAxowggMWAgEBMGgw # VDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UE # AxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIQDHCZR3nkTLyV # eD44b8q62zANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCD/6nh6xl9mRhoNvFVhtXE/zFAO # wH01vcSF9UmlioVNkDANBgkqhkiG9w0BAQEFAASCAgCT7HzKK3fmj9ftIUPha5v2 # YKBAkMmnCQZOy5bJwtFAsrRkkZ9T3Z7R30RwIKK7j6ltiySxzUrcrfo4WH4pmaZn # yjDNBvuMX/SR1H2fmHnELRX0aapOjiw86hTpMhEpPdWasKsIQ+HsCfzN4ZOkBPS9 # +QRTSCaE28ir9sgqDpv3msIQgC1zMQx/xrgHSiB5mFNkOOhuaDLYV4FlIYC7jVGx # AGHI6tOBUs+rIBgQq5GIiieT7m+AvkwgsWo3LSNjCNFeryiLWdgmIFiaUUGZ0KtD # SLPRD5C3mvSnvamEklktkCZTiy+puauZhizbyqr1K0Tc9LPmDja8/BlWUmpGUNKZ # plUN0CBTC4KZFSllUsKh041Kk1YQ1Me6YxanOm6q1kIqjK/xM3SIEtMakY3mAjm0 # EnLkmST67/5qoTcGm/rNZzNPyiKPXenMwkDjg6fDrme+tC5NVALaw5Q9v0LqBtQE # h7d+qayakmQ3zTrokvusKWHQC+Yea/04iCu7Kb9/Cw4wvYU4UrhF/ZC5nRZ5lpYA # vNSkdu5/b0GZb+wVzofh0if27EG9ukR1pVnD6ZnuO9DnHaJo74FRULkvOX8SW48P # tc8oRFXMQXApeG59ERihCtdPdYbKrU66F8aUPa9ppNPqkqsnxjrUcXwDQk/T70TU # 0BjrhI/W4rAdt8tVt2DvQg== # SIG # End signature block |