Some Help Please with ( Function sendEmail ) - powershell

can some body help me to solve this one,
I can't understand where i need to put my mail parameters, smtp server and so.
THIS IS THE SCRIPT:
Function sendEmail
{ param($from,$to,$subject,$smtphost,$htmlFileName)
$body = Get-Content $htmlFileName
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}

Unless you're still using PowerShell v1 (which you shouldn't) use Send-MailMessage instead of System.Net.Mail.SmtpClient and System.Net.Mail.MailMessage:
Send-MailMessage -SmtpServer $smtphost `
-To $to `
-From $from `
-Subject $subject `
-Body (Get-Content $htmlFileName | Out-String) `
-BodyAsHtml

I'm not entirely sure I'm understanding you correctly but, I think you're struggling with actually using your function, because that script is fine.
As already pointed out Send-MailMessage is easier to work with than the .net stuff.
If you want to call your function from the shell, first you have to import it
Import-Module sendemail.ps1
Then you can call it from your shell by filling in the parameters.

Related

Use powershell to send an email in outlook without locking up if Outlook is already running

I have the following program:
Function Email{
param ($to, $Subject, $Body, $Attachment)
if($process=(get-process 'outlook'))
{
kill($process)
Stop-Process $process -Force
#$namespace = $outlook.GetNameSpace("MAPI")
#$namespace.Logon("outlook")
}
$Outlook = New-Object -Com Outlook.Application
$session = $outlook.Session
$session.Logon("Outlook")
$Mail = $Outlook.CreateItem(0)
foreach ($person in $to){
$Mail.Recipients.add($person)
}
$Mail.Subject = $Subject
$Mail.Body = $Body
$Mail.Attachments.Add($Attachment)
$Mail.Send()
}
When tested in ISE and in batch, it functions as expected. However, when used in another powershell script, it randomly causes the script to hang up and I cannot open outlook manually due to an error about multiple instances.
How can I re-write this to properly account for an instance of outlook running (or at least so that it doesn't cause a script that uses it to hang up)?
Update: I have also tried it as:
Function Email{
param ($to, $Subject, $Body, $Attachment)
$Creds = Import-CliXml c:\localdata\cred.clixml
$username= myemail
Send-MailMessage -To $to -subject $Subject -body $Body -Attachment $Attachment -UseSsl -Port 587 -SmtpServer smtp.office365.com -From $username -Credential $creds
}
and I cannot get past the "cannot connect to remote server" error
Running telnet smtp.office365.com 587 or telnet smtp.office365.com 25 doesn't seem to return anything.

How to cc a user in System.Net.Mail.MailMessage using powershell script?

I have a code written to generate a report file in HTML format using a powershell.
Used the below code to send an email with that HTML as an attachment.
But unable to cc the user to the mail.
Code:
$subject = "Subject Line"
$body = Get-Content "D:\temp\ABC\TEST\report.htm"
$smtp= New-Object System.Net.Mail.SmtpClient $smtphost
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
Could someone please suggest me on how to send cc using the above syntax?
I can use the Send-MailMessage to accommodate the cc list.But in that case i wouldn't be able to send the HTML output as a body message.
MailMessage has a property called CC that you can set like you set the To line. $msg.CC = "whatever#wherever.somedomain". Send-MailMessage has a -BodyAsHtml switch. Pick your poison.
you should read the help file and is already have pretty nice examples.
Get-Help Send-MailMessage -Examples
If you are not getting any examples, do Update-Help
Send-MailMessage -To 'to#email.com' -From 'from#email.com' -Cc 'cc#email.com' -body $bodyhtml -BodyAsHtml
Regards
kvprasoon

Run built-in cmdlet with parameters that may or may not be specified

I've got a function in my script that wraps up the send-mailmessage cmdlet and does a bit of logic before sending out each email.
My question is how do I create the argument list to feed into send-mailmessage so that Cc, Bcc, and Attachments are optional.
What I'd done before is just a few if statements. But adding -Cc to the mix, that will be 9 if statements instead of the current 4. I figure I'm over-thinking this and there's got to be a simpler way.
Stripped down Function:
Function Send-Email ($To, $Cc, $Bcc, $Subject, $From, $Body, $Attachments)
{
#Some more code goes here that sometimes modifies the incoming parameters
$EmailServer = my.mail.server
Try
{
#Need to add ability for $Cc to be optional
if ($Attachments -and $Bcc) {send-mailmessage -to $To -Cc $Cc -Bcc $Bcc -subject $Subject -From $From -body $Body -smtpserver $EmailServer -attachments $Attachments -ErrorAction "Stop"}
if ($Attachments -and -not $Bcc) {send-mailmessage -to $To -Cc $Cc -subject $Subject -From $From -body $Body -smtpserver $EmailServer -attachments $Attachments -ErrorAction "Stop"}
if ($Bcc -and -not $Attachments) {send-mailmessage -to $To -Cc $Cc -Bcc $Bcc -subject $Subject -From $From -body $Body -smtpserver $EmailServer -ErrorAction "Stop"}
if (-not $Attachments -and -not $Bcc) {send-mailmessage -to $To -Cc $Cc -subject $Subject -From $From -body $Body -smtpserver $EmailServer -ErrorAction "Stop"}
}
Catch [system.exception]
{
"Failed to send email to $($To) due to: $_" #Logging removed for SO example code
}
Finally
{}
}
I've tried generating the arguments as one long string or also as an array of strings, then using invoke-expression. I've tried the same, but using the '&' sign to execute the cmdlet.
I just get prompted for the parameters by the shell when I try that.
PS E:\script> invoke-expression 'send-mailmessage $a'
cmdlet Send-MailMessage at command pipeline position 1
Supply values for the following parameters:
From:
PS E:\script> & send-mailmessage $a
cmdlet Send-MailMessage at command pipeline position 1
Supply values for the following parameters:
From:
I've tried setting $Cc as $Null, or $False, or a null string "", but send-mailmessage complains of invalid parameters.
I feel like I'm missing something simple here, but in my mind, the function should look something like this invalid example:
Function Send-Email ($To, $Cc, $Bcc, $Subject, $From, $Body, $Attachments)
{
#Some more code goes here that sometimes modifies the incoming parameters
$EmailServer = my.mail.server
if ($Cc) {$CcArg = "-Cc $Cc"}
if ($Bcc) {$BccArg = "-Bcc $Bcc"}
if ($Attachments) {$AttachArg = "-Attachments $Attachments"}
Try
{
send-mailmessage -to $To ($CcArg) ($BccArg) -subject $Subject -From $From -body $Body -smtpserver $EmailServer $AttachArg -ErrorAction "Stop"
}
Catch [system.exception]
{
"Failed to send email to $($To) due to: $_" #Logging removed for SO example code
}
Finally
{}
}
Thanks for any thoughts or suggestions.
Ah hah!
Found this post: Inline expansion of powershell variable as cmdlet parameter?
So function will look something like (Not fully tested, but the principle works):
Function Send-Email ($To, $Cc, $Bcc, $Subject, $From, $Body, $Attachments)
{
#Some more code goes here that sometimes modifies the incoming parameters
$EmailServer = my.mail.server
$MoreArgs = #{}
if ($Cc) {$MoreArgs.Add("Cc",$Cc)}
if ($Bcc) {$MoreArgs.Add("Bcc",$Bcc)}
if ($Attachments) {$MoreArgs.Add("Attachments",$Attachments)}
Try
{
send-mailmessage -to $To -subject $Subject -From $From -body $Body -smtpserver $EmailServer -ErrorAction "Stop" #MoreArgs
}
Catch [system.exception]
{
"Failed to send email to $($To) due to: $_" #Logging removed for SO example code
}
Finally
{}
}
Another option that eliminates all the Ifs.
$EmailParams = #{
To = $To
Cc = $Cc
From = $From
Subject = $Subject
Body = $body
SMTPServer = $MailServer
Attachments = $Attachments
ErrorAction = 'Stop'
}
$EmailParams.keys |
Where {$EmailParams.$_ -eq $null } |
foreach { $EmailParams.remove($_) }
Try { Send-MailMessage #EmailParams }
Catch { "Failed to send email to $($To) due to: $_" }
Finally {}

How to pass credentials to the Send-MailMessage command for sending emails

I'm having difficulty passing my credentials to the Send-MailMessage command
This is what I am running:
Send-MailMessage -smtpServer smtp.gmail.com -from 'myself#gmail.com' `
-to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
it errors with below the message which is obviously because I have not passed my gmail credentials
Send-MailMessage : The SMTP server requires a secure connection or the client was not
authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first.
I googled a bit and also went through the man page of Send-MailMessage and found that the "-credential" parameter needs to be passed.
My issue is: HOW ?
I tried with Get-Credentials as below:
$mycredentials = Get-Credential
Then entered my usrname and password for gmail in the box that pops up.
then I run below command:
Send-MailMessage -smtpServer smtp.gmail.com -credentail $mycredentials `
-from 'myself#gmail.com' -to 'myself#gmail.com' -subject 'Test' -attachment C:\CDF.pdf
and still it fails with the exact same error.
So I need help from you guys on how do I pass my Credentials to the Send-MailMessage command. I learned about PScredentials but not exactly sure what it is and how to use it in this context.
I found this blog site: Adam Kahtava
I also found this question: send-mail-via-gmail-with-powershell-v2s-send-mailmessage
The problem is, neither of them addressed both your needs (Attachment with a password), so I did some combination of the two and came up with this:
$EmailTo = "myself#gmail.com"
$EmailFrom = "me#mydomain.com"
$Subject = "Test"
$Body = "Test Body"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\CDF.pdf"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($SMTPMessage)
Since I love to make functions for things, and I need all the practice I can get, I went ahead and wrote this:
Function Send-EMail {
Param (
[Parameter(`
Mandatory=$true)]
[String]$EmailTo,
[Parameter(`
Mandatory=$true)]
[String]$Subject,
[Parameter(`
Mandatory=$true)]
[String]$Body,
[Parameter(`
Mandatory=$true)]
[String]$EmailFrom="myself#gmail.com", #This gives a default value to the $EmailFrom command
[Parameter(`
mandatory=$false)]
[String]$attachment,
[Parameter(`
mandatory=$true)]
[String]$Password
)
$SMTPServer = "smtp.gmail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
if ($attachment -ne $null) {
$SMTPattachment = New-Object System.Net.Mail.Attachment($attachment)
$SMTPMessage.Attachments.Add($SMTPattachment)
}
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom.Split("#")[0], $Password);
$SMTPClient.Send($SMTPMessage)
Remove-Variable -Name SMTPClient
Remove-Variable -Name Password
} #End Function Send-EMail
To call it, just use this command:
Send-EMail -EmailTo "Myself#gmail.com" -Body "Test Body" -Subject "Test Subject" -attachment "C:\cdf.pdf" -password "Passowrd"
I know it's not secure putting the password in plainly like that. I'll see if I can come up with something more secure and update later, but at least this should get you what you need to get started. Have a great week!
Edit: Added $EmailFrom based on JuanPablo's comment
Edit: SMTP was spelled STMP in the attachments.
And here is a simple Send-MailMessage example with username/password for anyone looking for just that
$secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
Send-MailMessage -SmtpServer mysmptp -Credential $cred -UseSsl -From 'sender#gmail.com' -To 'recipient#gmail.com' -Subject 'TEST'
It took me a while to combine everything, make it a bit secure, and have it work with Gmail. I hope this answer saves someone some time.
Create a file with the encrypted server password:
In Powershell, enter the following command (replace myPassword with your actual password):
"myPassword" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\EmailPassword.txt"
Create a powershell script (Ex. sendEmail.ps1):
$User = "usernameForEmailPassword#gmail.com"
$File = "C:\EmailPassword.txt"
$cred=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, (Get-Content $File | ConvertTo-SecureString)
$EmailTo = "emailTo#yahoo.com"
$EmailFrom = "emailFrom#gmail.com"
$Subject = "Email Subject"
$Body = "Email body text"
$SMTPServer = "smtp.gmail.com"
$filenameAndPath = "C:\fileIwantToSend.csv"
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential($cred.UserName, $cred.Password);
$SMTPClient.Send($SMTPMessage)
Automate with Task Scheduler:
Create a batch file (Ex. emailFile.bat) with the following:
powershell -ExecutionPolicy ByPass -File C:\sendEmail.ps1
Create a task to run the batch file. Note: you must have the task run with the same user account that you used to encrypted the password! (Aka, probably the logged in user)
That's all; you now have a way to automate and schedule sending an email and an attachment with Windows Task Scheduler and Powershell. No 3rd party software and the password is not stored as plain text (though granted, not terribly secure either).
You can also read this article on the level of security this provides for your email password.
PSH> $cred = Get-Credential
PSH> $cred | Export-CliXml c:\temp\cred.clixml
PSH> $cred2 = Import-CliXml c:\temp\cred.clixml
That hashes it against your SID and the machine's SID, so the file is useless on any other machine, or in anyone else's hands.
So..it was SSL problem. Whatever I was doing was absolutely correct. Only that I was not using the ssl option. So I added "-Usessl true" to my original command and it worked.
in addition to UseSsl, you have to include smtp port 587 to make it work.
Send-MailMessage -SmtpServer smtp.gmail.com -Port 587 -Credential $credential -UseSsl -From 'yyy#gmail.com' -To 'xxx#email.com' -Subject 'TEST'
Along with the other answers i would like to point out that if you have two factor authentication, you will need to create an application password on your google account.
For the detailed explanations : https://support.google.com/accounts/answer/185833

Email Subject showing Encoding

I am using send-mail message to send email to our Support System.
But when it send email it shows the subject line like this screen!
=?us-ascii?Q?R899076:Aman:System Summary ?=
In Subject I am using the variable:
$vUserName = (Get-Item env:\username).Value
$vComputerName = (Get-Item env:\Computername).Value
$subject = "$vComputerName : $vUserName : System Summary"
and then
send-MailMessage -SmtpServer Smtp-local -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority High
But when I recieve this email in Outlook it looks fine any Idea?
Actually this a approx 150 lines script and the body of email and smtp server are already specified in the server.
yes I tried the $subject = "$env:ComputerName : $env:UserName : System Summary" variable and the result is same.
yes I have tried the - encoding option and it gives an error
Send-MailMessage : Cannot bind parameter 'Encoding'. Cannot convert the "utf8" value of type "Syste
m.String" to type "System.Text.Encoding".
At D:\PowerShell\MyScripts\SystemInfo\SysInfo-V6-test[notfinal].ps1:151 char:84
+ send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Encoding <<<< utf8 -B
ody $body -Attachments "$filepath\$name.html" -BodyAsHtml -Priority High
+ CategoryInfo : InvalidArgument: (:) [Send-MailMessage], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SendMai
lMessage
Any clue?
You could write a custom function to send using .net instead of using the Send-MailMessage cmdlet. It's a lot clunkier, but gets round the problem.
Something like this:
Function SendEmail ($emailFrom, $emailTo, $subject, $body, $attachment) {
# Create from/to addresses
$from = New-Object System.Net.Mail.MailAddress $emailFrom
$to = New-Object System.Net.Mail.MailAddress $emailTo
# Create Message
$message = new-object System.Net.Mail.MailMessage $from, $to
$message.Subject = $subject
$message.Body = $body
$attachment = new-object System.Net.Mail.Attachment($attachment)
$message.Attachments.Add($attachment)
# Set SMTP Server and create SMTP Client
$server = <your server>
$client = new-object system.net.mail.smtpclient $server
# Send the message
"Sending an e-mail message to {0} by using SMTP host {1} port {2}." -f $to.ToString(), $client.Host, $client.Port
try {
$client.Send($message)
"Message to: {1}, from: {0} has beens successfully sent" -f $from, $to
}
catch {
"Exception caught in CreateTestMessage: {0}" -f $Error.ToString()
}
}
(Thanks to Thomas Lee (tfl#psp.co.uk) - I tweaked this from his code at http://powershell.com/cs/media/p/357.aspx)
The Send-MailMessage cmdlet doesn't have any output after you send emails, I wonder where the output comes from? Can you include the command you use and the output?
As to your subject line, you can reduce it to one line only:
$subject = "$env:ComputerName : $env:UserName : System Summary"
The Send-MailMessage has an Encoding parameter, have you tried it?
This happened to me when I used Send-MailMessage with the default encoding (ASCII) when there were spaces in the subject.
First, to answer the question about the Encoding parameter: You are trying to pass it as a string (ie "-Encoding ASCII"), when you should be using this type of syntax instead: "-Encoding ([System.Text.Encoding]::ASCII)".
This "encoding in the subject" issue happened to me, and I narrowed it down to spaces in the subject. To demonstrate:
This will not contain encoding in the subject:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::ASCII)
But this will:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one two" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::ASCII)
Note that the only material difference is the space in the subject.
If I specify UTF8 as the encoding, there is no encoding in the subject:
Send-MailMessage -To "alice#example.com" -From "bob#example.com" -Smtp "localhost" -Subject "one" -BodyAsHtml "body1" -Encoding ([System.Text.Encoding]::UTF8)
But as you say, it looks fine in Outlook, so I presume that the subject is correct. I'm not an expert on email formats or text-encoding, so I won't speculate as to why.