powershell time loop issue - powershell

Please I need help i have a script which checks folders on servers, if the folders get above a certain number of files, I run a function to send an email to notify us of the issue. Since the script is running permanently, I tried to set a check in the notification function that sends the emails to check when the last email was sent, if it is less than 15 minutes it just exits the if statement, if the time is after 15 minutes it must send another notification, update the last sent time and the process continues. The issue is the last update time the function is seeing is not seeing the updated variable. I have tried setting the $timesent = Get-Date variable initially outside of the function and internally but still the same issue. its almost like its seeing a different variable.
function sendnotification {
$currenttime = Get-Date
$diff = New-Timespan -Start $timesent -End $currenttime
if( $diff.Minutes -ge 15 ) {
send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high -Credential $cred
$timesent = Get-Date
}
}

Related

Powershell Script Assistance

I have a script that will query domain controllers to get the expiry date for passwords which works great. I have an issue where I can't access a domain controller directly to run this same query as the only way I can access this domain is via a VPN and a Jumpbox.
What I would like to do is just create a simple script that could access a textfile. Inside this file I'd like to have just a number to represent days since last password reset. Each day this number would decrease. Once the number inside the file was below a certain point I could have an email sent out. I'm just not sure how I can do the process for having the file and decreasing the number each day inside the file. I'd also need to reset it once it reached zero of course.
Any assistance with this would be greatly appreciated.
Thank you in advance.
Steve
A text file will save values as string. So you would have to type cast it to integer before you can do operations.
$File = "C:\temp\ADpasspolicy.txt"
[int]$PassPolicyVal = Get-Content -Path $File
#check for threshold value
if (!($PassPolicyVal -gt 10))
{
#send mail
Send-MailMessage -Subject "Password expired" -To "jane.doe#gmail.com" -From "John#gmail.com" -SmtpServer "smtpserveraddress" -Body "add body here"
}
if ($PassPolicyVal -le 0)
{
$PassPolicyVal = 90
}
else
{
#Decrement by 1 if greater than 0
$PassPolicyVal--
}
$PassPolicyVal | Out-File -FilePath $File

Using pipeline object to populate mail -to and -attachment

First ever Powershell script so any advice or recommendations are appreciated. I'm parsing a .csv into smaller .csv's to send out information about servers to recipients and i'm running into a problem in my foreach. How do I get this to work?
One interesting thing is that in Send-MailMessage, -to should not accept pipeline objects, It still throws an error, but it still sends the emails. However the attachment will never send.
#had to set this as a variable because # was throwing splatting errors
$Mail = "#Email.com"
#Import csv and split information, exports UID.csv
Import-csv C:\path\info.csv | Group-Object UID |
ForEach-Object {
$_.Group | Export-csv "C:\path\$($_.Name).csv" -NoTypeInformation
}
#Import file again to get unique list of UID and send mail with
#respective UID.csv
Import-csv C:\path\info.csv | Group-Object UID |
ForEach-Object {
$_.UID | Send-MailMessage -From "<Me#email.com>" -To "<$($_.Name)$Mail>" `
-Attachments "C:\path\$($_.Name).csv" `
-Subject "Testing" -Body "Please Ignore This" -Priority High `
-SmtpServer smtp.server.com
}
in Send-MailMessage, -to should not accept pipeline objects
In principle it does, namely if the pipeline objects have a .To property (which is not the case for you).
However, with your current approach, you don't need pipeline input at all, given that you're supplying all input as arguments.
Additionally, your pipeline input is incorrect, because $_.UID sends $null through the pipeline, given that $_ - a group-info object output by Group-Object - doesn't have a .UID property.
Using delay-bind script blocks ({ ... }), you can simplify your command as follows, obviating the need for a ForEach-Object call:
Import-csv C:\path\info.csv | Group-Object UID |
Send-MailMessage -From "<Me#email.com>" -To { "<$($_.Name)#Email.com>" } `
-Attachments { "C:\path\$($_.Name).csv" } `
-Subject "Testing" -Body "Please Ignore This" -Priority High `
-SmtpServer smtp.server.com
In short, the script blocks passed to -To and Attachments are evaluated for each input object, and their output determines the parameter value in each iteration. In the script block, $_ represents the pipeline object at hand, as usual.
Note that such delay-bind script blocks can only be used with parameters that are designed to accept pipeline input (irrespective of whether by value (whole object) or by a specific property's value).

Long delay before email arrives after PowerShell Send-MailMessage command (~2 and a half minutes)

I'm writing a PowerShell script to check multiple PCs for specific files and send an email if it finds them. It works, but the email takes a very long time to arrive (roughly two and a half minutes). I've tried running just the Send-MailMessage command and gotten the same results, so it isn't a different part of the script slowing it down. And it's not crunching for all that time - the command succeeds immediately. Outlook sends and receives other emails in this building much faster, and I've checked which SMTP server it's using and used the same one. I searched for anyone else having this problem, but only found examples of Send-MailMessage timing out or not working at all.
This is the command I've been using (to/from/smtp server replaced with placeholders):
Send-MailMessage -To "Example Person <ex#example.com>" -From "Example Person <ex#example.com>" -Subject "Test mail" -SmtpServer "XXXXX.XXXXXXXXX.com" -dno onFailure, onSuccess, Delay
I should note that when I run this, -dno Delay doesn't notify me that the email was delayed (and isn't the source of the problem itself, since when I take out the dno parameters I get the same results). Instead I get a success notification two and a half minutes later, when it arrives.
Since this was the first google result I wanted to provide an answer - As this post implies Powershell doesn't close the TCP connection immediately after sending, which can leave the SMTP session open or something.
However, if you end the PS Session then it closes the connection. Running as a script block closes immediately, like below:
$job = Start-Job -ScriptBlock {
# specify arguments to send-mailmessage as argument hash below, then splat
$mailArgs = $args[0];
Send-MailMessage #mailArgs;
} -ArgumentList #(#{
To = "Example Person <ex#example.com>";
From = "Example Person <ex#example.com>";
Subject = "Test mail";
SmtpServer = "XXXXX.XXXXXXXXX.com";
dno = #('onFailure', 'onSuccess', 'Delay');
});
# wait for job to complete (timeout after 30 seconds)
wait-job $job -Timeout 30;
# get result of job (if any)
receive-job $job;

Define To: field from from various values

In a CSV file I have various columns and two of those are for emails. Each row within these email columns have a group of emails.
I want to be able to send to these email addresses from a script.
I have everything setup and working, except for the TO:.
The idea of the script is that it loops each line of the csv and generates an email grabbing values from the cells of that row into various parts of the body. Then it sends of an email and loops back to the next line of the CSV to do the same, and so on until it reaches the end of the CSV file.
I'm having issues to plug a variable for the email columns, I'm guessing because the emails don't have "quotations".
How do I bring these in?
In a nutshell for the code
data is imported CSV
a loop is created foreach line of imported data
smtp, from, to, subject, attachments, body variables are defined
then the sendmail-message command is provided.
close the loop
##For the purpose of this, the emaildata.csv looks like this sample:
"NameGroup","emailGroupA","emailGroupB"
"Groupabc","a.b#b.com;c.a#b.com","xyv#b.com;xxd#b,com"
"Grouptrd","ca.r#b.com;as.b#b.com","aaa#a.com;bbb#b.com"
"Groupghd","dd.r#b.com;dd.b#b.com","dddaa#a.com;ddddddb#b.com"
$DataDir = "C:\Users\acastrellon\Documents"
$Data= import-csv $DataDir\emaildata.csv
foreach ($i in $Data) {
$NameGroup = $i.NameGroup
$TeamA = $i.emailGroupA.replace(';',"`n")
$TeamB = $i.emailGroupB.replace(';',"`n")
function send-email {
$smtpserver = " server.smtp"
$from = "myemail.com"
$to = $TeamA,$TeamB
send-MailMessage -From $from -To $to -Subject $subject -Body $body -SmtpServer $smtpServer
}
[string] $subject = "some text here: $NameGroup"
#[string] $attachment = "not here yet"
[string] $body = "
Text here that calls out $NameGroup
This also lists: $TeamA
This here lists $TeamB
Done"
send-email -subject $subject -attachment $attachment -body $body
}
#this should loop to get data from next line of csv and generate a new email with data.
Unlike a batch file where environment variables have a global impact to the current session, PowerShell isolates variables in different scopes.
You're referencing the two $TeamA & $TeamB variables inside a function but you set their values outside the function. Because the function scope (where they are read) is different to the script scope (where you set them) those variables will be empty inside the send-email function in your script.
Have a read on PowerShell scopes as you'll need to make some changes to your script functions; to either read the variables from the script scope ($script:TeamA) or to pass them into the function as a parameter

How to attach files to a Powershell function and send it through MS Outlook?

I've got this code:
Function Mailer ($MSubject, $MBody, $File){
$Outlook = New-Object -ComObject Outlook.Application
$Mail = $Outlook.CreateItem(0)
$Mail.To = "abc#contoso.com"
$Mail.Subject = $MSubject
$Mail.Body = $MBody
$Mail.Attachments.Add($File)
$Mail.Send()
}
I will work if I provide the exact path in the function by assigning it to the $File variable. However, I wish to make this universal for different subjects, bodies and paths. Shall I set the file path as global? What are your thoughts?
Thanks in advance :)
Piotr
This is the code I use to send emails out,
$from="ServerAdmin#Contoso.com"
$to="worker#contoso.com"
$cc=#("John.Doe#Contoso.com", "Jane.Doe#Contoso.com")
$subject="Weekly reports"
$attach="c:\SchTsk\Reports\Server_Inventory_$((Get-Date).ToString('MM-dd-yyyy')).csv","C:\SchTsk\Reports\VMPlatform_$((Get-Date).ToString('MM-dd-yyyy')).csv"
$body="This email contains weekly reports ran on the domain.<br>In an effort to reduce inbox spam, reports that generate separate files are now being attached to one weekly email."
Send-MailMessage -from $from -To $to -cc $cc -subject $subject -SmtpServer snmp.relay.contoso.com -Body $body -BodyAsHtml -Attachments $attach
Actually the function works fine. The problem was with the variable for the file path I was calling to.