Send mail from result (should be easy) - email

I have built a script to check for local machine certificates from a certain issuer expiring within 400.000 days (to get a hit when testing it) on remote server, but i cant just figure out how to get the result to send the actual email as experimenting with pipes after (and in) the IF statements doesnt seem to work.
I have been googling quiet alot (ofcourse) but as I'm new to Powershell and some code is difficult at times to interpret.
I am looking for something like; if $OutputFromtheIFStatement | Measure-Object -gt 0 { Send email using $SendReportNow.}
My code:
$Servers = 'testserver1,'testserver2'
$Threshold = 400000
$Deadline = (Get-Date).AddDays($Threshold)
$MailSMTP = '-SmtpServer smtpserver.domain.com -Port 25'
$MailTo = "receiversmailaddress#company.com"
$MailFrom = "sendersmailaddress#company.com"
$MailSubject = '-Subject Certifikat expiring within 90 days'
$MailBody = '-Body ?'
$SendReportNow = 'Send-MailMessage $MailSMTP $MailFrom $MailTo $MailSubject'
Invoke-Command -ComputerName $Servers { Get-ChildItem Cert:\LocalMachine\My } | ForEach {
If ($_.NotAfter -le $Deadline -and $_.Issuer -like '*CertainCompanyName*') { $_ | Select #{Label="Servername";Expression={($_.PSComputerName)}}, Issuer, Subject, #{Label="Expiry Date & Time";Expression={($_.NotAfter)}}, #{Label="Expires In (Days)";Expression={($_.NotAfter - (Get-Date)).Days}}
}
}

I cleaned your code up, hopefully this is easier to digest.
$Servers = 'testserver1','testserver2'
$Threshold = 400000
$Deadline = (Get-Date).AddDays($Threshold)
$certs = Invoke-Command -ComputerName $Servers { Get-ChildItem Cert:\LocalMachine\My }
ForEach ($cert in $certs){
If ($cert.NotAfter -le $Deadline -and $cert.Issuer -like '*CertainCompanyName*') {
$body = $cert | Select #{Label="Servername";Expression={($cert.PSComputerName)}}, Issuer, Subject, #{Label="Expiry Date & Time";Expression={($cert.NotAfter)}}, #{Label="Expires In (Days)";Expression={($cert.NotAfter - (Get-Date)).Days}}
$MailSubject = "[$($cert.PsComputerName)] Certifikat expiring within 90 days"
Send-MailMessage -SmtpServer smtpserver.domain.com -Port 25 -From sendersmailaddress#company.com -To receiversmailaddress#company.com -Subject $MailSubject -Body $body
}
}
This will result in e-mails being sent like this:
Title: [ServerA] Certifikat expiring within 90 days
----- Body-------
Servername : ServerA
Issuer : CN=localhost
Subject : CN=localhost
Expiry Date & Time : 4/5/2020 8:00:00 PM
Expires In (Days) : 1627

Related

Powershell - search for old files and email alert

Having some trouble with a powershell script which Im completely new too
What Im trying to do is basically monitor a specific folder for XML files only. If the files are older than say a 30mins then to email myself to alert me there is a problem
This is what I have so far:
$Path = "‪D:\Temp"
$SMTPServer = "10.1.1.12"
$From = "Email <email#aol.com>"
$To = "emailme#whatever.com"
$Subject = "Alert: Potential issue with service"
$SMTPMessage = #{
To = $To
From = $From
Subject = "$Subject"
Smtpserver = $SMTPServer
}
$File = Get-ChildItem -path $path -Filter ".XML" | Where-Object {$_.LastWriteTime -lt (Get-
Date).AddMinutes(-30)}
If ($File)
{ $SMTPBody = "Batches older than 30 minutes located in D:\Temp while service is actively running.
Service may require a restart."
$File | ForEach { $SMTPBody += "$($_.FullName)`n" }
Send-MailMessage #SMTPMessage -Body $SMTPBody
It doesnt work at all at the moment its failing at the first stage in trying to find the path
Any help would be great
Thanks

Powershell - Scan DC for new servers + if specific service is running on them

I have script that is scanning my DC for new servers that has been added to my domain + sending an email with the Name, IP and OS of the new server.
What I am looking, is how can i add a line to this script that will check if those new servers has specific Service running on them?
The output that I'm receiving to the email now is:
Dear IT Team,
Weekly AD scan for new servers:
Name IPv4Address OperatingSystem
test x.x.x.x Windows Server 2016 Standard
So i want somehow to add here a "Service" tab that will say "Servicename" running or no, in those servers.
The script:
#>
"Start: "+ (Get-Date)
try
{
$domain=""
if ($domain -eq"")
{
$domain = Get-ADDomain
}
else
{
$domain = Get-ADDomain -Identity $domain
}
$domain_name=$domain.name
$distinguished_name = $domain.DistinguishedName
$domain_controller = (Get-ADDomainController -server $domain_name).HostName
$logging_level=1
$search_base = "OU=my-ous," + $distinguished_name
$days_to_search =-300 # this value needs to be negative integer
if ($days_to_search -ge 0) {throw "Value for variable $days_to_search must be a negative integer in days."}
$date_filter = (get-date).adddays($days_to_search)
$computers=get-adcomputer -SearchBase $search_base -Properties * -Filter {Created -gt $date_filter -and operatingsystem -like "*windows*"} -server $domain_controller
$computers | Select-Object Name, Created,DistinguishedName,IPv4Address,OperatingSystem | ft -AutoSize
}
Catch
{
"Error occurred: " + (Get-Date)
throw
}
$Body = #"
<html>
<body>
<p>Dear Team,
<br/>
<p>Weekly scan for new servers:</p>
$($computers | ConvertTo-Html -Property Name,IPv4Address,OperatingSystem)
<br/>
</body>
</html>
"#
Send-MailMessage -To "myemail#test.com" -From 'do_not_reply#test.com' -Subject 'New Servers' -Body $Body -SmtpServer 'mysmtp server' -BodyAsHtml -Priority High

Writing a powershell script to monitor a log file

I am trying to write a script that will monitor a log file for time modified. If the file has been monitored on the last minute send me an email saying it is all good. IF the log file is older then a minute and the time is between 6am and 9pm send me an email. IF between 9pm and 6am reboot the server. except it is rebooting the server no matter what
# Set perameters here
$uncPath = 'Unc path to log file'
$Server = 'ServerName'
$min = Get-Date 06:00
$max = Get-Date 21:00
$now = Get-Date -Format hh:mm:ss
# Look at the Printstream Log Files and check last modified time
$files = (Get-ChildItem -Path $uncPath -Filter '*PrintstreamBroker*' -File |
Where-Object { $_.LastWriteTime -Gt (Get-Date).AddMinutes(-1) }).FullName
#If there file is good do nothing, and send email
if ($files) {
$Subject = 'Printstream Broker Is Running'
$message = 'The Printstream Broker Is Running There Is Nothing To Do'
$emailTo = '1#1.com'
}
Else ($min.TimeOfDay -lt $now -and $max.TimeOfDay -gt $now){
{
$Subject = 'Printstream Broker Is Not Running'
$message = 'Printstream Broker Is Not Running Please Log Into $servername and start the Printstream Monarch Broker'
$emailTo = '1#1.com'
}
}
Else {
Restart-Computer –ComputerName $server -Force
$Subject = 'Monarch Server Rebooted'
$message = 'The Monarch Server Has Been Rebooted'
$emailTo = '1#1.com'
}
}
# create a email
$mailParams = #{
From = 'PrintstreamBrokerDEV#visionps.com'
To = $emailTo
Subject = $Subject
Body = $message
SmtpServer = 'smtpserver'
# any other parameters you might want to use
}
# send the email
Send-MailMessage #mailParams
You have if else else.
It should be if elseif else.

How can I concatenate a string with a link that has spaces in powershell

Here is my code that checks when users passwords will expire and emails them if it will expire in less than 14 days. Since the link in the body of the email has spaces in it, the link does not encompass the whole file name.
#Add the Quest PowerShell snapin
Add-PsSnapIn Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
#Clear the placeholder log file
Clear-Content O:\logs\network\passwordchangeemails.txt
#Set Email Variables
$today = Get-Date
$logdate = Get-Date -format yyyyMMdd
$emailFrom = "my.name#mycompany.com"
$body = "Good Morning, `n`n"
$body += "As a courtesy reminder, your Company password will be expiring soon. `n`n"
$body += "If you allow your password to expire, you will be unable to access our network, mail or QAD until you recieve assistance from the Helpdesk. `n`n"
**$body += "To avoid this, please change your network password as soon as possible. (Remote users, please follow the password change procedure for remote users. Click Here -> " + "\\mydfsshare.net\share\helpdesk\guides\Passwords - Change procedure for remote users.pdf ) `n`n"**
$body += "Feel free to contact the Help Desk by phone at 555-555-5555 or by email at Helpdesk#mycompany.com `n"
$body += "Thanks!"
#Get Active Directory Information
Get-QADUser -SizeLimit 0 | Select-Object samAccountName,mail,PasswordStatus |
Where-Object {$_.PasswordStatus -ne "Password never expires" -and $_.PasswordStatus -ne "Expired" -and $_.PasswordStatus -ne "User must change password at next logon." -and $_.mail -ne $null} |
#For each user, get variables
ForEach-Object {
$samaccountname = $_.samAccountName
$mail = $_.mail
$passwordstatus = $_.PasswordStatus
$passwordexpiry = $passwordstatus.Replace("Expires at: ","")
$passwordexpirydate = Get-Date $passwordexpiry
$daystoexpiry = ($passwordexpirydate - $today).Days
#If days to expire is lessthan 14 days, send email to user
if ($daystoexpiry -lt 14) {
$emailTo = "$mail"
$subject = "Company IT Notification: Your Network password will expire in $daystoexpiry day(s). "
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191
Write-Host "Email was sent to $mail on $today"
Add-Content O:\logs\network\passwordchangeemails.txt "Email was sent to $mail on $today"
}
}
$recipients = "my.name#mycompany.com"
#Copy contents of log file to email and send to IT Department
$content = [IO.File]::ReadAllText("O:\logs\network\passwordchangeemails.txt")
Send-MailMessage -To $recipients -From "my.name#mycompany.com" -Subject "Password change log for $today" -Body "This is the log from $today, $content" -SmtpServer 111.111.111.111
Sorry I can't test this right now but if HTML is OK to use, try wrapping the link as follows...
"Text you want the users to see goes here<br>`n
Then set -BodyAsHtml on Send-Mailmessage:
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191 -BodyAsHtml

Powershell script for Soon-to-expire AD users

So basically, what I have here is a script that will scan a CSV that it imports, and for every entry in the spreadsheet, except for people in the RANDOM.DOMAIN, it will find the managers email address and send an automated email to the manager telling them user XYZ is about to expire soon, and they need to do something about it.
If the managers email is unavailable for some reason, then it defaults to sending the email to me.
This script works well.
The problem I am running into is, I want to make it so only one email is sent to each manager, despite multiple users (or entries) from the spreadsheet, list them as the manager.
I.e. if Joe Bloggs has a manager Aaron T and Jane Doe has the manager Aaron T, then Aaron T will get two emails, one email for each user.
MY QUESTION:
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
$datai = Import-Csv "Soon-to-expire User Accounts22.csv" | select 'Display Name',Manager,'Domain Name','Account Expiry Time'
Connect-QADService -Service another.DC | Out-Null
$expiringUsers = #{}
foreach ($i in $datai) {
$dn = $i.'Display Name'
$dn1 = $i.'Domain Name'
$man = $i.'Manager'
$aet = $i.'Account Expiry Time'
$subject = "Account about to expire: $dn"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
if ($man -eq "-" -or $man -like 'CN=*' -or $getmail -eq $null -or $man -eq "") {
$man = "Aaron T"
$getmail = get-qaduser "$man" -LdapFilter '(mail=*)' | select mail
$emailAD = $getmail.mail
}
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn += "`n"
$expiringUsers[$emailAD]["aet"] += $aet += "`n"
$expiringUsers[$emailAD]["man"] += $man += "`n"
} else {
$expiringUsers[$emailAD] = #{
#"dn1" = $dn1
#"aet" = $aet
#"man" = $man
# "dn" = #( $dn )
}
}
}
$expiringUsers | fc #as suggested
foreach ($emailAD in $expiringUsers.Keys) {
$dn = $expiringUsers[$emailAD]["dn"]
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account/s About to Expire!"
$content = #"
Hi,
$dn `n
$dn1 `n
$man `n
$aet `n
$emailAD `n
Technology Services
"#
Send-MailMessage -from "aaron#website.com" `
-To $emailAD `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer "relay.server"
#using this as a test instead of sending mass emais all the time
Write-Host $content
}
UPDATED with the new script as requested.... still having issues.
Is there an easy way to only get it to send one email per manager, even if that manager has multiple users reporting to them that are about to expire?
For this you need to defer e-mail processing. Collect the users in a hashtable, e.g. by manager e-mail address:
...
$expiringUsers = #{}
foreach ($i in $datai) {
If ($i.'Domain Name' -notmatch "RANDOM.DOMAIN") {
...
if ($expiringUsers.Contains($emailAD)) {
$expiringUsers[$emailAD]["dn"] += $dn
} else {
$expiringUsers[$emailAD] = #{
"dn1" = $dn1
"aet" = $aet
"man" = $man
"dn" = #( $dn )
}
}
}
}
and move the actual e-mail processing outside the loop:
foreach ($emailAD in $expiringUsers.Keys) {
$dn1 = $expiringUsers[$emailAD]["dn1"]
$man = $expiringUsers[$emailAD]["man"]
$aet = $expiringUsers[$emailAD]["aet"]
$subject = "Account about to expire: $($expiringUsers[$emailAD]["dn"])"
$content = #"
Hi,
...
Technology Services
"#
Send-MailMessage -from "Test Script - Powershell <email#test.com>" `
-To "$emailAD" `
-Subject $subject `
-Body $content `
-Priority high `
-smtpServer servername
Write-Host "Mail Sent to $man"
}
Note that for simplicity reasons the above code only records the expiry date of the first user. If you want the expiry date of each user recorded separately, you'll have to take additonal steps, e.g.
$expiringUsers[$emailAD]["expiry"] += #{
"name" = $dn;
"date" = $aet;
}
instead of
$expiringUsers[$emailAD]["dn"] += $dn
So I finally decided to revisit this script, after many, many months.
I'm get a little better at PowerShell and while I'm sure this isn't the most effective way to do it, this is something that works for me.
I've also changed the input method; it pulls the information directly from AD, instead of using a CSV file that used to be generated from an application called 'AD Manager Plus' (Hate it).
Remember, using Quest CMDlets here because we don't have a 2008 environment. (so using Get-QADUser instead of Get-ADuser)
FYI, I have only posted the code here which sorts out the data into separate tables - you can decide how you want to utilize those results. For our environment, I have it build an nice HTML table and body, then send it to the appropriate manager to deal with.
#user data input
$data = get-qaduser -SizeLimit 0 -includedproperties accountexpires | where {$_.AccountExpires -ne $null -and $_.AccountExpires -le ((Get-Date).AddDays(45)) }
#get a list of managers, unique.
$uniqueMan = $data | select Manager -Unique
#foreach manager from $uniqueman
Foreach ($manager in $uniqueman) {
#create the array variable / clear it out for the next manager.
$myarray = #()
#foreach User found in in $data query
Foreach ($user in $data) {
#Search the $user's query for people with the same manager as that of the $uniqueman list.
If ($user.Manager -eq $manager.Manager) {
#do what with the result.
#add the person to an array
$myarray += New-Object psobject -Property #{
Name = $user.'Name'
UserName = $user.'SAMAccountName'
AccountExpires = $user.'AccountExpires'
Manager = $user.Manager
}
}
#for testing, to output the results to an HTML file.
#$myarray | ConvertTo-Html | Out-File ("C:\test\" + $manager.Manager + ".html")
}
}