I am writing a powershell script for a monthly maintenance process. In order to track it I am using a try catch block that will send an email when it succeeds or fails. To do this I am using smtp. I am wondering how to write the console output to the email. Please let me know if you have any suggestions. Having trouble getting started.
Thank you in advance.
This is what I recently tried but it didn't work:
catch {
$smtpServer = "example"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "example"
$msg.To.Add("example")
$msg.Subject = "MONTHLY MAINTENANCE FAILED!"
$msg.Body= Write-Error ("Monthly maintenance failed! Please investigate." + $_)
$smtp.Send($msg)
$msg.Dispose();
}
Q: What "Didn't work"?
SUGGESTION:
1) Write a sample script that deliberately triggers the error
2) Make sure you're successfully capturing the error text you want (you should be able to get it from $_, like you're doing)
3) Make sure your e-mail parameters are correct
4) Divide and conquer: Powershell syntax first, E-Mail connectivity after.
My hunch is you'll need to debug your e-mail connectivity.
For example:
Try {
1/0 # throw "divide by zero"
}
Catch {
$errmsg = "Monthly maintenance failed! Please investigate." + $_
Write-Console $errmsg
$smtpServer = "example"
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "example"
$msg.To.Add("example")
$msg.Subject = "MONTHLY MAINTENANCE FAILED!"
$msg.Body= $errmsg
$smtp.Send($msg)
$msg.Dispose();
}
Related
Can someone please help me figure this part out.
#Mail Configuration
$smtpUser = "email#domain.com"
$smtppass = ConvertTo-SecureString "PasswordAsPlainText" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList ($smtpuser, $smtppass)
$ToAddress = "toaddress#domain.com"
$FromAddress = "send#domain.com"
$SMTPSERVER = "smtp.office365.com"
$SMTPPORT = "587"
$MailParam = #{
To = $ToAddress
From = $FromAddress
Subject = $subject
Body = $Mail
SMTPServer = $SMTPServer
Port = $SMTPPORT
Credential = $pscred
}
#Send Email
$GetChildItem = Get-ChildItem -Path C:\Temp
if ($GetChildItem -ne $Null)
{
Write-Host "Backup Success"
$subject = "$env:COMPUTERNAME SQL Backup Success"
$Mail = "SQL Backup Succeded on the server, please see the attached report for more details"
$attachment = $reportfile
Send-MailMessage #MailParam -BodyAsHtml -usessl
#Exit
}
if ($GetChildItem -eq $Null)
{
Write-Host "Backup Failed"
$subject = "$env:COMPUTERNAME SQL Backup Failed"
$Mail = "SQL Backup Failed on the server, please see the attached report for more details"
$attachment = $reportfile, $debuglog
Send-MailMessage #MailParam -usessl -BodyAsHtml
#Exit
}
Now I don't think anything is wrong with the code above, I am no expert coder but I can pretty much copy and paste :) and take stuff from there to get it working for me.
The issue with the above code is that when run it, it doesn't work for the 1st time but when you run it again it works fine. The error you get the first time is
Send-MailMessage : Cannot validate argument on parameter 'Body'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\Aasim\Desktop\Untitled1.ps1:29 char:26
+ Send-MailMessage #MailParam -BodyAsHtml -usessl
+ ~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage
I am not sure what the issue is and why it doesn't work only the first time but works every other subsequent time until you close and reopen the script.
Basically I am creating a SQL backup script that backs up databases to our Network Share and then emails me whether it was successful or not. so far the rest of the script works just fine.
In your If and Else blocks, instead of creating a variable $subject, or $Mail, update the hashtable, $MailParam. Also, you seem to be missing the Attachment variable in your Send-MailMessage
if ($GetChildItem -eq $Null)
{
Write-Host "Backup Failed"
$MailParam.Subject = "$env:COMPUTERNAME SQL Backup Failed"
$MailParam.Body = "SQL Backup Failed on the server, please see the attached report for more details"
$attachment = $reportfile, $debuglog
Send-MailMessage #MailParam -usessl -BodyAsHtml -Attachments $attachment
#Exit
}
Good afternoon -
I have a "trigger file" that calls several scripts to run some morning reports. Each called script contains code that attaches a file to an email and sends (via ComObject). If I run each script individually then there all emails send correctly. However, when i run the "trigger file", only a couple of the emails send and I am not receiving any error messages. Any ideas what is happening? I purposely made the trigger file run the scripts concurrently to save time. But is that overloading Outlook?
EDIT: Updated code to include Try/Catch block. There are 8 scripts that run using this template. All 8 successfully complete the excel open/run/save. However, only some of the emails send. And even with this Try/Catch block, no error message is being sent.
#Establish script file locale
$FullPath = “//fullpath/”
$SavePath = “//savepath/”
#Open Excel file
& {
$Excel = New-Object -ComObject excel.application
$Excel.Visible=$False
$Workbook = $Excel.Workbooks.Open($FullPath)
#Run Macro
$app=$Excel.Application
$app.Run("Macro1")
#Save and close Excel
$Excel.Application.DisplayAlerts=$False
$Workbook.SaveAs($SavePath,51)
$Workbook.Close()
$Excel.Quit()
}
#Send email with attachment
Try
{
$EmailSettings=#{
SMTPServer = "smtp"
From = "me#email.com"
To =
#(
"you#email.com"
)
Subject = "Subject"
Attachments = $SavePath
BodyAsHtml = $true
Body =
"<body><p>
Attached is the thing.
</b></p></body>"
}
Send-MailMessage #EmailSettings
}
Catch
{
$Subject = 'ERROR: '+$EmailSettings.Subject
$ErrorMessage = $_.Exception.Message+' '+$_.Exception.ItemName
Send-MailMessage -From me#email.com -To me#email.com -Subject $Subject -SmtpServer smtp -Body $ErrorMessage
}
I did turn on my less secure app in Gmail, I think the problem is SSL.
$time = get-date
$smtpServer = “smtp.gmail.com”
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential(“user”, “password”)
$smtp = new-object Net.Mail.SmtpClient($smtpServer,587) **587 to 465**
$msg = new-object Net.Mail.MailMessage
$msg.From = (“myemail#gmail.com”)
$msg.To.Add(“myemail#gmail.com”)
$body=”Your message Body”
$msg.Subject = “Mail From Gmail ” + $time
#your file location
$files=Get-ChildItem “C:\Users\Public\Pictures\LINE”
Foreach($file in $files)
{
Write-Host “Attaching File :- ” $file
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList
C:\Users\Public\Pictures\LINE\$file
$msg.Attachments.Add($attachment)
}
$smtp.Send($msg)
$attachment.Dispose()
$msg.Dispose()
Have you tried to change the port?
It looks to me that you're still using 587 which is expecting TLS/SSL or STARTTLS.
Is there a reason you're not authenticating and using SSL/TLS ?
I've read that Google does not fall back to plaintext SMTP if STARTTLS is not supported. If you've explicitly selected the "Unsecured" option when configuring the server I believe you need to use a different port. 25(maybe).
Edit: It looks like you're missing arguments on the send method. Try this code.
Alternatively try changing for the much easier looking Send-MailMessage cmdlet
https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/Send-MailMessage?view=powershell-5.1
$EmailFrom = "notifications#somedomain.com"
$EmailTo = "me#earth.com"
$Subject = "Notification from XYZ"
$Body = "this is a notification from XYZ Notifications.."
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
I had a similar problem at one point with a script of mine. On mobile right now, but if I remember right, I ended up making an app password for the use and turned off the Less secure app option.
https://support.google.com/accounts/answer/185833?hl=en
I was using nant to send mail and it is working fine - something like
<mail
from="Test#b.c"
tolist="A#b.c"
subject="Test"
mailhost="myhost.mydomain.com"
isbodyhtml="true"
message= "${Test}">
</mail>
I didn't have to use any kind of authentication.
Now when using powershell it seems I am forced to use authentication - something like this would fail:
Send-MailMessage -To $to -From $from -Subject "Test" –Body “Test (body) -SmtpServer "myhost.mydomain.com"
I would get the following message:
Send-MailMessage : No credentials are available in the security package
Am I missing some way to send mails without specifying credentials if the server supports that?
Edit:
I've also tried the answer here to send anonymous mails but it just times out:
send anonymous mails using powershell
Sending mails using Powershell v1 method works fine without authentication as shown here
My Powershell version is 5 yet this is apparently the way to go, unless someone has another idea.
$smtpServer = "ho-ex2010-caht1.exchangeserverpro.net"
$smtpFrom = "reports#exchangeserverpro.net"
$smtpTo = $to
$messageSubject = $subject
$messageBody = $body
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($smtpFrom,$smtpTo,$messagesubject,$messagebody)
I was looking for another issue and found this question here...
As #AngelicCore already explained one approach,
Here is another one if someone using Outlook dektop app...
The mail sent will appear in your outbox.
using outlook object
Try
{
#Email structure
$Outlook = New-Object -ComObject Outlook.Application
$Mail = $Outlook.CreateItem(0)
#Email Recipients
$Mail.To = "abc#domain.com;xyz#domain.com"
$Mail.Cc = "tuv#domain.com; pqr#domain.com"
#Email Subject
$date = Get-Date -Format g
$Mail.Subject = "Subject here $date"
#Email Body
$Mail.Body = "Body Here"
#Html Body
$Mail.HTMLBody == "<html> HTML Body Here </html>"
#Email Attachment
$file = "C:\path\xyz.txt"
$Mail.Attachments.Add($file)
$Mail.Send()
Write-Host -foreground green "Mail Sent Successfully"
}
Catch
{
write-host -foreground red $error[0].Exception.Message
}
pause
exit
Need to send email via private smtp server with credential and starttls. I read many tutorials and still cannot establish starttls communication.
My code:
$smtpServer = "smtp.xserver.cz"
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer, 25)#587 works
$smtp.EnableSsl = $false
$smtp.Credentials = New-Object System.Net.NetworkCredential("myuser#xserver.cz","mypassword"); #yes, correct login, tried via Thunderbird
#Email structure
$msg.From = "info#xserver.cz"
$msg.To.Add("testtest#gmail.com")
$msg.subject = "subject"
$msg.IsBodyHTML = $true
$msg.body = "AAA"+"<br /><br />"
$ok=$true
try{
$smtp.Send($msg)
Write-Host "SENT"
}
catch {
Write-Host "`tNOT WORK !!!!!"
$error[0]
$_.Exception.Response
$ok=$false
}
finally{
$msg.Dispose()
}
if($ok){
Write-Host "`tEVERYTHING OK"
}
Need to use .Net objects and class, not third party library, or Send-MailMessage in Powershell, because Send-MailMessage doesn't have atachment sending options.
You're not getting your TLS connect because you've set EnableSsl to $false.
Not sure where you got the idea that Send-MailMessage doesn't have attachment sending options. Sending attachments with Send-MailMailMessage is ridiculously easy. It accepts one or more file names to use as attachments from the pipeline, or through the -Attachments parameter.