# encoding: ascii # api: powershell # title: Set Outlook Signatures # description: This is a script I wrote to automatically update email signatures. Reference this script in group policy. # version: 1.80.4 # type: script # author: darkscrypt # license: CC0 # function: Check-LocalLogging # x-poshcode-id: 6275 # x-archived: 2016-11-18T01:01:36 # x-published: 2016-03-31T17:35:00 # # param ([Switch]$force = $false) $SignatureEnforcing = $true $AppData=(Get-Item env:appdata).value $SigPath = '\Microsoft\Signatures' $SignatureName = 'Siggy Standard' $DomainName = 'siggy.com' $SigSource = "\\siggy1\Signatures\$SignatureName" $LocalLogFile = "C:\Siggy\Siggy\siggy_" + $ENV:Username + ".txt" $LocalSignaturePath = $AppData+$SigPath $RemoteSignaturePathFull = $SigSource+'\'+$SignatureName+'.docx' $CompanyRegPath = "HKCU:\Siggy\" $SignatureRegPath = $CompanyRegPath+'\'+$SignatureName $SiggyVersion = "1.80.4" $SiggySystemLog = [System.Collections.ArrayList]@() $UserName = $env:username $Filter = "(&(objectCategory=User)(samAccountName=$UserName))" $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.Filter = $Filter $ADUserPath = $Searcher.FindOne() $ADUser = $ADUserPath.GetDirectoryEntry() $ADDisplayName = $ADUser.DisplayName $ADEmailAddress = $ADUser.mail $ADTitle = $ADUser.title $ADDescription = $ADUser.description $ADTelePhoneNumber = $ADUser.TelephoneNumber $ADFax = $ADUser.facsimileTelephoneNumber $ADMobile = $ADUser.mobile $ADStreetAddress = $ADUser.streetaddress $ADCity = $ADUser.l $ADPOBox = $ADUser.postofficebox $ADCustomAttribute1 = $ADUser.extensionAttribute1 $ADModify = $ADUser.whenChanged $ADFirst = $ADUser.givenName $ADLast = $ADUser.sn $ADInitials = $ADUser.Initials $ADPostal = $ADUser.postalcode $ADDepartment = $ADUser.physicalDeliveryOfficeName $ADState = $ADUser.st $ADSignatureQuote = $ADUser.signatureQuote $ADProfessionalCredentials = $ADUser.professionalCredentials function Check-LocalLogging{ if (!(Test-Path -path "C:\Siggy\Siggy")) { New-Item "C:\Siggy\Siggy" -Type Directory } } function Local-Log($message){ Check-LocalLogging $stream = New-Object System.IO.StreamWriter $LocalLogFile, "Append" $output = "[" + (Get-Date).toString() + "]: " + $message $stream.WriteLine($output) $stream.close() } function Write-Log($message){ Local-Log($message) if($SiggySystemLog.count -eq 0){ $LocalScopedUser = $ENV:username $SiggySystemLog.Add("---------------------------") | Out-Null Local-Log("---------------------------") $SiggySystemLog.Add("Starting Siggy $SiggyVersion ") | Out-Null Local-Log("Starting Siggy $SiggyVersion ") $SiggySystemLog.Add,("Siggy Evaluating $LocalScopedUser for signature") | Out-Null Local-Log("Siggy Evaluating $LocalScopedUser for signature") } $output = "[" + (Get-Date).toString() + "]: " + $message Write-Host($output) $SiggySystemLog.Add($output) | Out-Null } function Finalize-Log{ $LogFile = "\\SC1\Reporting\Siggy\$ENV:COMPUTERNAME.txt" $stream = New-Object System.IO.StreamWriter $LogFile, "Append" foreach($message in $SiggySystemLog){ Write-Output $message $stream.WriteLine($message) } $stream.close() } function Check-ValidMAPIAddress{ $UserName = $env:username $Filter = "(&(objectCategory=User)(samAccountName=$UserName))" $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.Filter = $Filter $ADUserPath = $Searcher.FindOne() $ADUser = $ADUserPath.GetDirectoryEntry() if(!$ADUser.mail -or $ADuser.mail -notmatch "yourdomain.com"){ return $false }else{ return $true } } function Check-ValidCompanyRegistry{ #Return True if Valid, False if Invalid $Validations = $true if (Test-Path $SignatureRegPath) { Write-Log('Company Registry Valid') }else{ New-Item -path "HKCU:\" -name "Siggy" New-Item -path $CompanyRegPath -name $SignatureName Write-Log('Company Registry Not Found.') $Validations = $false } if (Test-Path $SignatureRegPath'\Outlook Signature Settings') { Write-Log('Outlook Registry Settings Exist') }else{ New-Item -path $SignatureRegPath -name "Outlook Signature Settings" Write-Log('Outlook Signature Settings Not Found.') $Validations = $false } return $Validations } function Synchronize-AD{ Write-Log("Synchronizing Active Directory.") $ValidateProperties = [System.Collections.ArrayList]@() $ValidateProperties.Add("ADDisplayName") | Out-Null $ValidateProperties.Add("ADTitle") | Out-Null $ValidateProperties.Add("ADEmailAddress") | Out-Null $ValidateProperties.Add("ADFirst") | Out-Null $ValidateProperties.Add("ADLast") | Out-Null $ValidateProperties.Add("ADInitials") | Out-Null $ValidateProperties.Add("ADPostal") | Out-Null $ValidateProperties.Add("ADState") | Out-Null $ValidateProperties.Add("ADDepartment") | Out-Null $ValidateProperties.Add("ADStreetAddress") | Out-Null $ValidateProperties.Add("ADCity") | Out-Null $ValidateProperties.Add("ADTelephoneNumber") | Out-Null $ValidateProperties.Add("ADMobile") | Out-Null $ValidateProperties.Add("ADFax") | Out-Null $ValidateProperties.Add("SiggyVersion") | Out-Null $ValidateProperties.Add("ADSignatureQuote") | Out-Null $ValidateProperties.Add("ADProfessionalCredentials") | Out-Null $key = Get-Item -Path $SignatureRegPath'\Outlook Signature Settings' foreach ($prop in $ValidateProperties){ $CurrentValue = (Get-Variable $prop).Value if($key.GetValue($prop) -ne (Get-Variable $prop).Value){ Write-Log("Updating Registry Item: $prop to $CurrentValue") Set-ItemProperty $SignatureRegPath'\Outlook Signature Settings' -Name $prop -Value $CurrentValue } } } function Check-ADSync{ #Returns False if Desynchronized, and True if Synchronized Write-Log("Checking AD Properties against Registry") $synchronized = $true if((Check-ValidCompanyRegistry) -eq $false){ $synchronized = $false } $ValidateProperties = [System.Collections.ArrayList]@() $ValidateProperties.Add("ADDisplayName") | Out-Null $ValidateProperties.Add("ADTitle") | Out-Null $ValidateProperties.Add("ADEmailAddress") | Out-Null $ValidateProperties.Add("ADFirst") | Out-Null $ValidateProperties.Add("ADLast") | Out-Null $ValidateProperties.Add("ADInitials") | Out-Null $ValidateProperties.Add("ADPostal") | Out-Null $ValidateProperties.Add("ADState") | Out-Null $ValidateProperties.Add("ADDepartment") | Out-Null $ValidateProperties.Add("ADStreetAddress") | Out-Null $ValidateProperties.Add("ADCity") | Out-Null $ValidateProperties.Add("ADTelephoneNumber") | Out-Null $ValidateProperties.Add("ADMobile") | Out-Null $ValidateProperties.Add("ADFax") | Out-Null $ValidateProperties.Add("SiggyVersion") | Out-Null $ValidateProperties.Add("ADSignatureQuote") | Out-Null $ValidateProperties.Add("ADProfessionalCredentials") | Out-Null $key = Get-Item -Path $SignatureRegPath'\Outlook Signature Settings' foreach ($prop in $ValidateProperties){ $CurrentValue = (Get-Variable $prop).Value if($key.GetValue($prop) -ne (Get-Variable $prop).Value){ $synchronized = $false Write-Log("$prop is ne to $CurrentValue, setting synchronization status to false") } } if($synchronized){ Write-Log "Active Directory information is Synchronized to local cache" } return $synchronized } function Check-SignatureSync{ $LocalSignatureVersion = (Get-ItemProperty $SignatureRegPath'\Outlook Signature Settings').SignatureVersion $MasterSignatureVersion = (gci $RemoteSignaturePathFull).LastWriteTime.toString() if (!(Test-Path -path $LocalSignaturePath)) { New-Item $LocalSignaturePath -Type Directory } Copy-Item "$SigSource\*" $LocalSignaturePath -Recurse -Force if ($MasterSignatureVersion -eq $LocalSignatureVersion){ Write-Log("Local Signature Version Matches Master Signature") return $true }else{ Write-Log("Local Signature Mismatch.") Set-ItemProperty $SignatureRegPath'\Outlook Signature Settings' -name SignatureVersion -Value $MasterSignatureVersion return $false } } Function Get-OutlookProcess(){ $process = Get-Process "Outlook" -ErrorAction SilentlyContinue if ($process -ne $null){ $Application = [Runtime.InteropServices.Marshal]::GetActiveObject('Outlook.Application') return $Application }else{ Return $null } } Function WaitFor-Outlook(){ $Application = $null while($true){ if($force){ Write-Log("Bypassing Outlook-Wait: Force Mode detected.") break } $Application = Get-OutlookProcess if($Application -ne $null){ $profname = $Application.Application.DefaultProfileName Write-Log("Outlook Process Detected") if($profname -ne $null){ Write-Log("Default Outlook Profile Detected") break } } Write-Log("No Outlook Profile Detected") start-sleep -s 120 } Write-Log("Outlook Profile Detected") } function EndProgram{ param([string]$Reason) Write-Log("Gracefully Ending Program: $Reason") Finalize-Log } function Set-OutlookDefaults{ WaitFor-Outlook $MSWord = New-Object -com word.application $EmailOptions = $MSWord.EmailOptions $EmailSignature = $EmailOptions.EmailSignature $EmailSignatureEntries = $EmailSignature.EmailSignatureEntries if ($SignatureEnforcing -eq $false) { if ($EmailSignature.NewMessageSignature -eq "(none)") { Write-Log("New Message Signature Not Detected. Setting $SignatureName as Default.") $EmailSignature.NewMessageSignature = $SignatureName } if ($EmailSignature.ReplyMessageSignature -eq "(none)") { Write-Log("Reply Signature Not Detected. Setting $SignatureName as Default Reply.") $EmailSignature.ReplyMessageSignature = $SignatureName } } else { Write-Log ("SignatureEnforcing is `$true") Write-Log("Forcing $SignatureName as Default.") $EmailSignature.NewMessageSignature = $SignatureName Write-Log("Forcing $SignatureName as Default Reply.") $EmailSignature.ReplyMessageSignature = $SignatureName } $MSWord.Quit() } function Launch-Payload{ Write-Log('Payload Triggered.') $Doctor = $false $ReplaceAll = 2 $FindContinue = 1 $MatchCase = $False $MatchWholeWord = $True $MatchWildcards = $False $MatchSoundsLike = $False $MatchAllWordForms = $False $Forward = $True $Wrap = $FindContinue $Format = $False #Insert variables from Active Directory to rtf signature-file $MSWord = New-Object -com word.application $fullPath = $LocalSignaturePath+'\'+$SignatureName+'.docx' $MSWord.Documents.Open($fullPath) #Begin Find and Replace #Check if Doctor if($ADDisplayName.ToString().substring(0,3) -match "Dr."){ Write-Log "Display Name contains DR. In the first three characters. Switching to Doctor Mode." $Doctor = $true } #User Name $FindText = "DisplayName" $ReplaceText = $ADDisplayName.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Title $FindText = "Title" $ReplaceText = $ADTitle.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Email $FindText = "harbmail" $ReplaceText = $ADEmailAddress.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #FirstName $FindText = "FirstName" $ReplaceText = $ADFirst.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #LastName $FindText = "LastName" $Unclean = $ADLast.ToString() $ReplaceText = $Unclean -replace "Dr. ", "" $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Middle Initials If ($ADInitials -ne '') { $FindText = "MiddleInitial" $ReplaceText = $ADInitials.ToString() } Else { $FindText = "MiddleInitial. " $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Postal $FindText = "Postal" $ReplaceText = $ADPostal.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #State $FindText = "State" $ReplaceText = $ADState.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Department $FindText = "Department" $ReplaceText = $ADDepartment.ToString() $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Description If ($ADDescription -ne '') { $FindText = "Description" $ReplaceText = $ADDescription.ToString() } Else { $FindText = " | Description " $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Professional Credentials (Job titles) If ($ADProfessionalCredentials -ne '') { $FindText = "ProfessionalCredentials" $ReplaceText = $ADProfessionalCredentials.ToString() } Else { $FindText = ", ProfessionalCredentials" $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Street Address If ($ADStreetAddress -ne '') { $FindText = "StreetAddress" $ReplaceText = $ADStreetAddress.ToString() } Else { $FindText = "StreetAddress" $ReplaceText = $DefaultAddress } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #PostofficeBox If ($ADPOBox -ne '') { $FindText = "PostofficeBox" $ReplaceText = $ADPOBox.ToString() } Else { $FindText = "PostofficeBox" $ReplaceText = $DefaultPOBox } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #City If ($ADCity -ne '') { $FindText = "City" $ReplaceText = $ADCity.ToString() } Else { $FindText = "City" $ReplaceText = $DefaultCity } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Telephone If ($ADTelephoneNumber -ne "") { $FindText = "TelephoneNumber" $Number = $ADTelephoneNumber.ToString() -replace "-", "." $ReplaceText = $Number } Else { $FindText = "Office TelephoneNumber" $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Mobile If ($ADMobile -ne "") { $FindText = "MobileNumber" $Number = $ADMobile.ToString() -replace "-", "." $ReplaceText = $Number } Else { $FindText = "| Cell MobileNumber" $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #Fax If ($ADFax -ne '') { $FindText = "FaxNumber" $Number = $ADFax.ToString() -replace "-", "." $ReplaceText = $Number } Else { $FindText = "| Fax FaxNumber" $ReplaceText = "".ToString() } $MSWord.Selection.Find.Execute($FindText, $MatchCase, $MatchWholeWord, $MatchWildcards, $MatchSoundsLike, $MatchAllWordForms, $Forward, $Wrap, $Format, $ReplaceText, $ReplaceAll ) #END: Find And Replace #Save new message signature Write-Log('Saving Signatures') #Save HTML $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatHTML"); $path = $LocalSignaturePath+'\'+$SignatureName+".htm" $MSWord.ActiveDocument.saveas([ref]$path, [ref]$saveFormat) #Save RTF $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatRTF"); $path = $LocalSignaturePath+'\'+$SignatureName+".rtf" $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$saveFormat) #Save TXT $saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatText"); $path = $LocalSignaturePath+'\'+$SignatureName+".txt" $MSWord.ActiveDocument.SaveAs([ref] $path, [ref]$SaveFormat) $MSWord.ActiveDocument.Close() $MSWord.Quit() Write-Log('Signature Saved...') } #End Payload function Launch-Missile{ WaitFor-Outlook Launch-Payload } Function Main{ $payload = $false if($force){ Write-Log("Force Mode!") $payload = $true }else{ Write-Log("Initiating 3 Minute Sleep before continuing.") Start-Sleep -s 180 } if((Check-ValidMapiAddress) -eq $false){ EndProgram -Reason "Invalid MAPI Address for " + $ENV:Username } if((Check-ADSync) -eq $false){ Write-Log("Active Directory is Not Synchronized. Missile Armed.") $payload = $true } if((Check-SignatureSync) -eq $false){ Write-Log("Local Signature is Not Synchronized. Missile Armed.") $payload = $true } if($payload -eq $true){ Write-Host "Launching Missile." Launch-Missile Set-OutlookDefaults Synchronize-AD EndProgram -Reason "Missile Launched" }else{ EndProgram -Reason "Signature modification not needed. All Settings are Clear" } } Main