Powershell - Move Mail - powershell

I'm newbie to powershell, and I have a challenge on process my script. It did everything perfectly, but it wont move the message to the target folder and I don't know why.
I thought maybe to process at end cycle, but the issue is that I can encour that will transfer also file that have not any reference, and I would avoid to process something that I have no info about.
I tried this
$MailboxName = "fatture#abc.com"
write-host "Now Processing" -ForegroundColor Yellow
write-host "Searching on Fatture" -ForegroundColor Yellow
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$namespace = $outlook.GetNameSpace("MAPI");
$recipient = $namespace.CreateRecipient($MailboxName)
$inbox = $namespace.GetSharedDefaultFolder($recipient,6)
$messages = $inbox.Folders.Item("Carriers").folders.Item("Gpac").folders.item("BLR")
$MoveTarget = $inbox.Folders.Item("Carriers").folders.Item("Gpac").folders.item("BLS")
$filepath = "C:\temp\FATTURE\Automation\"
$messages.Items | % {
Write-Host "New Message " $_.Subject
$msg = $_
$Ref = $_.Subject -replace ' ',''
$RefStr = $ref.split('#')
$SearchSTR = $RefStr[2]
write-host $SearchStr
# $invNbr = $body.Substring($body.IndexOf("INVOICE NO")+19,10)
#write-host "The Invoice Number is : $invNbr" -ForegroundColor Cyan
write-host "Querying for $SearchSTR" -ForegroundColor Green
$t = (Query_file($SearchSTR))[-1].CONSOL_REF
write-host "File Found : $t" -ForegroundColor Cyan
write-host $t
if ($t -ne $null) {
$filetype = $t.Substring(0,1)
$date = Get-Date -format "yyyyMMddhhmmss"
write-host "Today is Date is $date" -ForegroundColor Red
Switch($filetype.tostring())
{
{($_ -eq 1) -or ($_ -eq 2) -or ($_ -eq 7) -or ($_ -eq 7) -or ($_ -eq 8) }{($dept = "0001"), ($dept1 = "ZLAG")}
{($_ -eq "F") -or ($_ -eq "V") -or ($_ -eq "M")}{($dept = "0002"), ($dept1 = "Zero"), ($type = "MOR")}
{($_ -eq 3) -or ($_ -eq 5) -or ($_ -eq "J")} {($dept = "0028"), ($dept1 = "One"), ($type = "OBR") }
{($_ -eq 9)} {($dept = "0031"), ($dept1 = "CONSOLE")}
}
write-host "The KEY TYPE is $dept1 " -ForegroundColor Yellow
$fileStr = $t + "_INV_" + $dept + "_$date_.tsk"
write-host " FILE Path: " $fileStr -ForegroundColor Cyan
$msg.attachments | ?{$_.filename -like "*.pdf"} | %{
$file = $filestr
$_.saveasfile((Join-Path $filepath $filestr))
}
$msg.UnRead = $false
$msg.Move($MoveTarget)
}
#fine cycle messages
}
I tried to move from the cycle but the issue is that it goes for all of email, instead, I want to process only the email that should be. I would like when the attachment has being downloaded, that the email will be moved.

Related

Convert DOC with macro to DOTM

I am trying to convert DOC files with macros to DOTM with macros. My code changes the files but after the marco section is totally broken. When I convert it manually my macro code stays.
My code is:
function ReleaseRef ($ref) {
if($ref){
([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
[System.__ComObject]$ref) -gt 0)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
}
function Convert-DOC{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$filepath,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$filefilter
)
try {
$files = Get-ChildItem $filepath -Include "$filefilter" -recurse -ErrorAction SilentlyContinue | Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Extension -like "$filefilter") }
$totalfiles = $files.Count
[int]$currentfile = 0
Write-Host "converting files... [$totalfiles]"
#word object********************************
#load dotnet assembly
Add-Type -AssemblyName Microsoft.Office.Interop.Word
#create word object
$word = New-Object -ComObject Word.Application -Verbose:$false
$word.visible = $true
$word.DisplayAlerts = [Microsoft.Office.InterOp.Word.WdAlertLevel]::wdAlertsNone
foreach ($file in $files) {
#Current file number
[int]$currentfile = [int]$currentfile + 1
#Check for password
$catch = $false
try {
#open file
Write-Host $file
$worddoc = $word.Documents.Open($file.FullName, $null, $null, $null, "")
} catch {
#if error, file has password
Write-Host "$file is protected by Password, skipping..." -ForegroundColor Yellow
$catch = $true
continue
}
if ($catch -eq $false) {
try {
#**********convert file**********
write-host "converting " $file.fullname "file $currentfile of $totalfiles" -ForegroundColor DarkGreen
#check for links
if([IO.Path]::GetExtension($file) -eq ".doc"){
#check for macros in in file
if ($worddoc.HasVBProject) {
$doFixedFormat = [Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatXMLDocumentMacroEnabled
$newfile = ($file.fullname).substring(0, ($file.FullName).lastindexOf("."))
$newfile += ".docm"
} else {
$doFixedFormat = [Microsoft.Office.Interop.Word.XlFileFormat]::wdFormatXMLDocument
$newfile = ($file.fullname).substring(0, ($file.FullName).lastindexOf("."))
$newfile += ".docx"
}
}
#save file
if(Test-Path $newfile){
Write-host "$newfile already exists" -ForegroundColor Yellow
} else {
$worddoc.SaveAs($newfile, $doFixedFormat )
}
#close file
$worddoc.close()
Write-Host "done" -ForegroundColor DarkGreen
#**********Garbage Collector**********
$gc_int++
if([int]$gc_int -gt 5){
Write-Host 'Run Garbage Collector' -ForegroundColor DarkBlue -BackgroundColor White
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
[int]$gc_int = 0
}
} catch {
$formatstring = "{0} : {1}`n{2}`n" +
" + CategoryInfo : {3}`n" +
" + FullyQualifiedErrorId : {4}`n" +
" + Filename : {5}`n"
$fields = $_.InvocationInfo.MyCommand.Name,
$_.ErrorDetails.Message,
$_.InvocationInfo.PositionMessage,
$_.CategoryInfo.ToString(),
$_.FullyQualifiedErrorId,
$file.fullname
Write-Host -Foreground Red -Background Black ($formatstring -f $fields)
"$fields" | Out-File ($scriptpath + '\error_convert.log') -Append
}
}
}
} finally {
#**********clean-up************
Write-Host ""
Write-Host "Cleaning Up" -ForegroundColor DarkMagenta
Write-Host "Quiting Word"
$word.Quit()
Write-Host "Garbage Collector"
[gc]::collect()
[gc]::WaitForPendingFinalizers()
Write-Host "Release Com Object Workbook"
$a = ReleaseRef($worddoc)
Write-Host "Release Com Object Word"
$a = ReleaseRef($word)
Write-Host "Finishing Clean-Up"
}
}
Convert-DOC -filepath "C:\_testmacro\" -filefilter "*.doc"
What I do is, checking if the file has a VB part and is so setting the extension:
[Microsoft.Office.Interop.Word.WdSaveFormat]::wdFormatXMLDocumentMacroEnabled
and then save it:
$worddoc.SaveAs($newfile, $doFixedFormat)
A similar function with XLS and XLAM works fine
Edit:
seems like I was missing a $worddoc.Convert() but now struggling with checkin/checkout
As my edit stated, I missed the convert command:
$worddoc.Convert()
$worddoc.SaveAs($newfile, $doFixedFormat)
before saving

ServiceNamePrincipal to nslookup

# Source / credit:
# https://social.technet.microsoft.com/wiki/contents/articles/18996.active-directory-powershell-script-to-list-all-spns-used.aspx
cls
$search = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$search.filter = "(servicePrincipalName=*)"
## You can use this to filter for OU's:
## $results = $search.Findall() | ?{ $_.path -like '*OU=whatever,DC=whatever,DC=whatever*' }
$results = $search.Findall()
foreach( $result in $results ) {
$userEntry = $result.GetDirectoryEntry()
Write-host "Object Name = " $userEntry.name -backgroundcolor "yellow" -foregroundcolor "black"
Write-host "DN = " $userEntry.distinguishedName
Write-host "Object Cat. = " $userEntry.objectCategory
Write-host "servicePrincipalNames"
$i=1
foreach( $SPN in $userEntry.servicePrincipalName ) {
Write-host "SPN(" $i ") = " $SPN
$i+=1
}
Write-host ""
}
nslookup $SPN
I would like to use nslookup on the service principal names.

Nested If Statement first -notlike condition

I am trying to use nested IF statements to check a AD-Computer Attribute and if it is not either VM or VeraCrypt, use Manage-BDE to check the Bitlocker status.
When I use just Get-Adcomputer <name> -Properties extensionAttribute1 | select extensionAttribute1 it returns the expected result VM.
When I do
$Attribute = Get-Adcomputer <name> -Properties extensionAttribute1 | select extensionAttribute1
Write-Host $Attribute
I get #{extensionAttribute1=VM}
I have tried many using -Notlike "*VM* but this did not work.
Here is my code.
# -----------------------
# Define global variables
# -----------------------
$ScanCount = 0
$UnprotectedCount = 0
$Date = Get-Date -Format yyyyMMdd
$StartDate = Get-Date -Format HH:mm:ss
$ReportFile = "C:\BitLocker_Status\BitLocker_Status.csv"
$BackupFile = "C:\BitLocker_Status\BitLocker_Status_Backup$BackupCopy'_$Date.csv"
$OutputArray = #()
$BackupCopy = 0
$SearchBase = "DC=Merallis,DC=net"
# ----------------------------------------
# Checking backing up output file
# ----------------------------------------
if (Test-Path $ReportFile) {
Rename-Item -Path $ReportFile -newname $BackupFile
$BackupCopy = $BackupCopy + 1
}
Else {
$BackupCopy = 0
}
# ----------------------------------------
# Build array from list of computers in AD
# ----------------------------------------
Write-Host -NoNewline "- Gathering a list of Computers from Active Directory..."
Try
{
$Computers = Get-ADComputer -SearchBase $SearchBase -Filter * -Properties Name,Description | Sort-Object
Write-Host -ForegroundColor Green "Success"
}
Catch
{
Write-Host -ForegroundColor Red "Failed ($_)"
}
# -------------------------------------------------
# Use the Manage-BDE command to query each computer
# -------------------------------------------------
Write-Host "- Querying BitLocker status..."
ForEach ($Computer in $Computers)
{
$Name = $Computer.Name
$Description = $Computer.Description
$BDE = Manage-BDE -ComputerName $Computer.Name -Status C:
# -------------------------------------------------
# Use the Get-ADComputer command to query the current attribute for each computer
# -------------------------------------------------
$Attribute = Get-ADComputer $Name -Properties extensionAttribute1 | select extensionAttribute1
Write-Host -nonewline " - $Name ..."
If ($Attribute -notlike "*VM*" -or $Attribute -notlike "*VeraCrypt*") {
If ($BDE -Like "*An error occurred while connecting*") {Write-Host -ForegroundColor Yellow "Unable to connect"; $Status = "Unable to connect"; Set-ADComputer -identity $Name -Replace #{"ExtensionAttribute1"=$Status}}
ElseIf ($BDE -Like "*Protection On*") {Write-Host -ForegroundColor Green "Protected"; $Status = "Protected"; Set-ADComputer -identity $Name -Replace #{"ExtensionAttribute1"=$Status}}
ElseIf ($BDE -Like "*Protection Off*") {Write-Host -ForegroundColor Red $Status; $Status = "Not protected"; $UnprotectedCount = $UnprotectedCount + 1 ; Set-ADComputer -identity $Name -Replace #{"ExtensionAttribute1"=$Status}}
ElseIf ($BDE -Like "*The term 'manage-bde'*") {Write-Host -ForegroundColor Red "error manage-bd!"; $Status = "Not protected"; $UnprotectedCount = $UnprotectedCount + 1}
Else {Set-ADComputer -identity $Name -Replace #{"ExtensionAttribute1"="Unknown"}}
}
$ScanCount = $ScanCount +1
$OutputArray += New-Object PsObject -Property #{
'Computer name' = $Computer.Name
'Description' = $Computer.Description
'BitLocker status' = $Status
}
}
# -----------------
# Generate a report
# -----------------
Write-Host -NoNewline "- Saving report..."
Try
{
$OutputArray | Export-CSV -NoTypeInformation $ReportFile
Write-Host -ForegroundColor Green "Success"
}
Catch
{
Write-Host -ForegroundColor Red "Failed ($_)"
}
# -----------------------------------------
# Display completion message and statistics
# -----------------------------------------
$EndDate = Get-Date -Format HH:mm:ss
$Duration = New-TimeSpan $StartDate $EndDate
Write-Host ""
Write-Host "-------------------------------------------------------------"
Write-Host "Script complete. Start time: $StartDate, End time: $EndDate"
Write-Host "Scanned $ScanCount computers. $UnprotectedCount are unprotected!"
Write-Host "-------------------------------------------------------------"man
Write-Host ""
If you want to filter objects from list based on some property value then you can use Where-Object
i.e. Website list ( without "default" website Name )
$YOURLIST = Get-Website
$YOURLIST | Where-Object { $_.Name -notlike "*Default*" }

Powershell - How would I return appname from a foreach loop only if status code -ne 200?

The title says it all. I have been returning output from every iteration of both of the below foreach loops (see the Write-Host and Write-Output lines), but the application that is using this script (Nagios) can't handle that much data. Therefore, I would like to only return 1 output at a time. Basically "All apps okay" or "app(s) down: then list the apps not returning 200 response code".
I have no idea how to do this as getting the foreach loops to work in the first place was quite the challenge for me.
$ok = 0
$warning = 1
$critical = 2
$unknown = 3
$appPool = get-webapplication
$errorcode = 0
$time_errorcode = 0
foreach($a in $appPool) {
$app = $a.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
$HTTP_Request = [System.Net.WebRequest]::Create($url)
$HTTP_Response = try{ $HTTP_Request.GetResponse() }catch {$exceptionMessage = $_.Exception.Message
$exceptionItem = $app}
[int]$HTTP_Response.StatusCode -ne 200
$statuscode = [int]$HTTP_Response.StatusCode
Write-Host "$app status code: $statuscode"
if ($HTTP_Response.StatusCode.value__ -ne 200) {
[int]$errorcode = 1
}
}
foreach($t in $appPool){
$app = $t.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date
try {Invoke-WebRequest -Uri $url -OutFile $output} catch {
$exceptionMessage = $_.Exception.Message
$exceptionItem = $app
Write-Output "$app error: $exceptionMessage"}
Write-Output "$app Time taken: $((Get-Date).Subtract($start_time).milliSeconds) millisecond(s)"
$timetaken = $((Get-Date).Subtract($start_time).milliSeconds)
if ($timetaken.StatusCode.value__ -ge 500) {
[int]$time_errorcode = 1
}
}
#Uncomment for testing
#Write-Output $time_errorcode
#Write-Output $errorcode
if (($errorcode -eq 0 -and $time_errorcode -eq 0)){exit $ok}
if (($errorcode -eq 1 -and $time_errorcode -eq 0)){exit $critical}
if (($errorcode -eq 0 -and $time_errorcode -eq 1)){exit $warning}
if (($errorcode -eq 1 -and $time_errorcode -eq 1)){exit $critical}
else {exit $unknown}
Here's my approach. UNTESTED. Just to give you an idea to work with.
$appPool = Get-WebApplication
$errorcode = 0
$time_errorcode = 0
# Using a hashset ensures every app is contained only once
$appsDown = New-Object "System.Collections.Generic.HashSet[string]"
foreach($a in $appPool) {
$app = $a.Attributes[0].Value;
$url = "http://localhost$app/apitest/index"
### Test response code ###
$HTTP_Request = [System.Net.WebRequest]::Create($url)
$HTTP_Response = $null
try {
$HTTP_Response = $HTTP_Request.GetResponse()
} catch {
# for test
Write-Host $_
}
if ($null -eq $HTTP_Response -or [int]$HTTP_Response.StatusCode -ne 200 ) {
[int]$errorcode = 1
[void]$appsDown.Add($app)
}
### Test response time ###
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date
$timetaken = -1
try {
Invoke-WebRequest -Uri $url -OutFile $output
$timetaken = ((Get-Date) - $start_time).TotalMilliSeconds
} catch {
# for test
Write-Host $_
}
if ($timetaken -lt 0 -or $timetaken -ge 500) {
[int]$time_errorcode = 1
[void]$appsDown.Add($app)
}
}
# Output the results here
if ($appsDown.Count -eq 0) {
Write-Output "All apps okay"
}
else {
Write-Output ($appsDown.Count.ToString() + "app(s) down")
$appsDown | sort | foreach {
Write-Output $_
}
}
if (($errorcode -eq 0 -and $time_errorcode -eq 0)){exit $ok}
if (($errorcode -eq 1 -and $time_errorcode -eq 0)){exit $critical}
if (($errorcode -eq 0 -and $time_errorcode -eq 1)){exit $warning}
if (($errorcode -eq 1 -and $time_errorcode -eq 1)){exit $critical}
else {exit $unknown}
Explanations:
$appsDown = New-Object "System.Collections.Generic.HashSet[string]"
Create a new instance of a .NET HashSet to hold the app names. (It's an unordered collection where every value is stored only once.)
[void]$appsDown.Add($app)
Add the app name to the collection. [void] is there to prevent the method's return value to be sent to the pipeline.
This may help you:
$list = #()
Foreach(x in y){
$item = #{}
If(x.error -eq 200){
$item.Name = x.Name
}
$obj = New-Object PSObject -Property $item
$list += $obj
}
Adding these parts will leave you with a list of appsnames in the variable $list

Add or remove text from text file using PowerShell

I'm using PowerShell to add or remove text from file. I'm keep getting funny text in my file.
This only happens when I have removed the line from the text file and when I try to add new line I get funny text.
cls
IMPORT-MODULE ActiveDirectory
$fileLocation = "E:\Script\MatchCadTest\ptc.opt";
function addUser( $username=''){
$user = Get-ADUser -Identity $username -ErrorAction SilentlyContinue;
$userFullName = $user.Name;
$empty = [string]::IsNullOrEmpty($userFullName);
if ( !($empty) ){
$userExisted = Get-Content $fileLocation | Select-String "$username" -quiet
if( ! $userExisted ){
$newLocation = "E:\Script\MatchCadTest\backup\";
if((Test-Path -Path $fileLocation)) {
Copy-Item "$fileLocation" "$newLocation"
}
$date = Get-Date -Format "d-M-y Hms";
$newName = "ptc_$date.opt"
Rename-Item "$newLocation\ptc.opt" $newName
# Add-Content $fileLocation ""
Add-Content -Path $fileLocation -Value "# $userFullName";
Add-Content -Path $fileLocation -Value "INCLUDE MATHCAD USER $username";
Write-Host "User has been added to file. Please restart the service." -BackgroundColor Green -ForegroundColor Black
}
else{
Write-Host "User already existed" -BackgroundColor Red -ForegroundColor White
}
}
}
function removeUser( $username=''){
$user = Get-ADUser -Identity $username -ErrorAction SilentlyContinue;
# $user
$userFullName = $user.Name;
$empty = [string]::IsNullOrEmpty($userFullName);
if ( !($empty) ){
$userExisted = Get-Content $fileLocation | Select-String "$username" -quiet
if( $userExisted ){
$remove="# $userFullName";
$removeUser = (Get-Content $fileLocation);
$removeUser | where {$_ -ne $remove};
$remove="INCLUDE MATHCAD USER $username";
$removeUser | where {$_ -ne $remove}
$removeUser |Out-File $fileLocation;
#$removeUser = (Get-Content $fileLocation) | where {$_ -ne $remove} | Out-File $fileLocation;
#$content = Get-Content $fileLocation
#$content | Foreach {$_.TrimEnd()} | Set-Content $fileLocation
Write-Host "User removed" -BackgroundColor Green -ForegroundColor Black
}
else{
Write-Host "User does not existed" -BackgroundColor Red -ForegroundColor White
}
}
else{
Write-Host "User not found in ad" -BackgroundColor Red -ForegroundColor White
}
}
$option=''
while ( $option -ne 0){
Write-Host "What would you like to do?"
Write-Host "1= Add new user"
Write-Host "2= Remove user"
Write-Host "0= No (Exit)"
$option = Read-Host "Select option"
$username = Read-Host "Please enter Username"
if( $option -eq 0 ){
exit 1
}
elseif( $option -eq 1){
addUser($username);
}
elseif ( $option -eq 22){
removeUser ($username);
}
else{
cls
Write-Host
Write-Host " Invaild Choice " -BackgroundColor Red #-ForegroundColor White
Write-Host
}
#Reset
$option=444;
$username="";
$userFullName="";
$user="";
$empty="";
}
When I remove the line of text from file and add a new user, it's all a funny text string:
See below
‣潍慨浭摡䴠橡摩਍义䱃䑕⁅䅍䡔䅃⁄单剅洠ㅭ㘳㐰ല
I have a text file with following information.
- // Full name 1
- User ID of User 1
- // Full name 2
- User ID of User 2
* // Full name 3
* User ID of User 3
* // Full name 4
* User ID of User 4
* // Full name 5
* User ID of User 5
* // Full name 6
* User ID of User 6
* // Full name 7
* User ID of User 7
* // Full name 8
* User ID of User 8
If you see that user 5 and 6 or 7 and 8 has extra space which i wont to remove and ad just sinlge space.
I think you need to set the encoding for your Add-Content
Try: Add-Content -Encoding UTF8 -Path $fileLocation -Value "# $userFullName";