Iam looking for a Powershell script to attach the html file in the body of email.Please help me by providing a sample script .My current script is not working .Iam not able to get the html file content in the body of email.Name of the html file changes every time.
i used 2 scripts but i suppose you could use one
Make the html file
$FILENAME = HTMLfilename
$head = #'
<title>page title</title>
<style> maybe some css</style>
'#
$title01 = #'
<h1>some text above html file</h1>
'#
$body = #"
<a href='$FILENAME.html'>filename</a>
'#
$x = some code
$x | Select-object Name | ConvertTo-HTML -head $head -PreContent $title01 -PostContent "some text" -body $body | Out-File "PATH\TO\HTML\FILE\$FILENAME.html"
Send the email
$Credential = New-Object System.Management.Automation.PsCredential($EmailUsername, $Emailpassword)
$EmailFrom = "from#domain.com"
$EmailTo = #("<to#domain.com>")
#$EmailCc = #("<EMAIL>")
$EmailSubject = "email subject"
$EmailBody = "a link to html file"
#OR maybe Attach it
#$EmailAttachments = "PATH\TO\HTML\FILE\$FILENAME.html"
$SMTPServer = "smtp.#domain.com"
$SMTPPort = ####
$SMTPSsl = $True
$param = #{
SmtpServer = $SMTPServer
Port = $SMTPPort
UseSsl = $SMTPSsl
Credential = $Credential
From = $EmailFrom
To = $EmailTo
#Cc = $EmailCc
Subject = $EmailSubject
Body = $EmailBody
#Attachments = $EmailAttachments
}
Send-MailMessage #param
Related
I have one HTML file which contains css and HTML code as shown below.
I want this content to be embedded in email body using Powershell script.
Below is my Powershell script for Email.
$toUsers = #('xxxx#microsoft.com','xxxx#microsoft.com')
$fromUser = "xxxx#microsoft.com"
$smtpServer = "xxx.XXX.corp.xxxx.com"
#$ccUsers = "xxxx#microsoft.com"
$msg = New-Object Net.Mail.MailMessage
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.UseDefaultCredentials = $true
#$msg.Body = $html
$msg.Subject="c360 UX test run report" -f (Get-Date -format "yyyy-MM-dd")
foreach($toUser in $toUsers)
{
$msg.To.Add($toUser)
write-host $toUser
}
$body = "<b>Build Number:- $(Build.BuildNumber)<br>"
$body += "Branch Name:- $(Build.SourceBranch) </b> <br>"
$body += "Product Name:- $env:PRODUCT_NAME <br>"
$body +='Click here'
$msg.From = $fromUser
#$msg.CC.Add($ccUsers)
$msg.IsBodyHTML = $true
$msg.Body = $body
$attachmentObject = new-object Net.Mail.Attachment($(Get-ChildItem -Recurse -Path $(System.ArtifactsDirectory) -Filter 'Report.zip').FullName)
$msg.Attachments.Add($attachmentObject)
$msg.Priority="High"
$smtp.Send($msg)
$smtp.Dispose()
$msg.Dispose()
#Wait for a sec to let dispose complete.
sleep 2`enter code here`
I am editing one of my old scripts to send an email to a user with images embedded into the text. I am trying to use the Send-MailMessage function to send the email as opposed to the older method of $smtp.send($msg). However, when trying to update the script, the images are no longer being embedded.
I know how to attach them to the email as actual attachments, but I am not sure what I am doing wrong to have them show as actual embedded images.
NOTE: for brevity, I removed some of the full email since it is large and as long as I can get an image or two working, it will all work.
# force powershell to run as an x86 process
Set-ExecutionPolicy -Scope CurrentUser Unrestricted
if ($env:Processor_Architecture -ne "x86") {
&"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" -file $myinvocation.Mycommand.path
exit
}
# initialize the script
if ($startupvariables) { try {Remove-Variable -Name startupvariables -Scope Global -ErrorAction SilentlyContinue } catch { } }
New-Variable -force -name startupVariables -value ( Get-Variable | ForEach-Object { $_.Name } )
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$Separator = ".", "#"
# advise what the script does
Add-Type -AssemblyName PresentationCore,PresentationFramework
$ButtonType = [System.Windows.MessageBoxButton]::OKCancel
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Shared Drive Access Assistance"
$MessageBody = "This script asks the user to provide more information regarding a network drive that they would like access to.`n`nTo use it, enter the below information:`n`n`n`tTicket Number`n`n`tUser's Email Address`n`n`tRequestor's Email Address`n`n`nIf this is the script you want to use, click OK.`nIf not, click Cancel."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
if ($Result -eq "Cancel")
{
Exit-PSSession
}
else
{
# get the ticket number
$Ticket = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the SCTask ticket number" , "Ticket Number")
# get the user id via the email address
$UserID = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the user's email address" , "User Email Address")
$User = $UserID.split($Separator)
$Firstname = $User[0].substring(0,1).toupper()+$User[0].substring(1).tolower()
$Lastname = $User[1].substring(0,1).toupper()+$User[1].substring(1).tolower()
$User = $Firstname, $Lastname
# get local username
$Username = [System.Environment]::UserName
# create email
$subject = "Ticket $Ticket on Hold for User Response - Shared Drive Access for $User - Awaiting Additional Information"
$body = #"
<html>
<body style="font-family:calibri">
To $Requestor, $User,<br>
<br>
<br>
In order to proceed with your request for shared drive access, we require the server name and full path to the folder you need access to. If you do not already know this information, you will need to provide these instructions to someone that already has access to the folder that you need access to.<br>
<br>
1) Click the Start menu<br>
<br>
<img src="cid:image1.png"><br>
<img src="cid:image2.png"><br>
<img src="cid:image3.png"><br>
<br>
<br>
2) Navigate to "Computer"<br>
<br>
<img src="cid:image4.png"><br>
<br>
<br>
<br>
If you have any questions or need assistance with this process, please contact the Service Desk via one of the methods listed below.
<br>
<br>
Thank You,<br>
<br>
IT Service Desk<br>
</body>
</html>
"#
$att1 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive1.png")
$att2 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive2.png")
$att3 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive3.png")
$att4 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive4.png")
$att1.ContentId = "image1.png"
$att2.ContentId = "image2.png"
$att3.ContentId = "image3.png"
$att4.ContentId = "image4.png"
# $msg.Attachments.Add($att1)
# $msg.Attachments.Add($att2)
# $msg.Attachments.Add($att3)
# $msg.Attachments.Add($att4)
# create confirmation message
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageIcon = [System.Windows.MessageBoxImage]::Warning
$MessageTitle = "Shared Drive Access Assistance"
$MessageBody = "The information you have entered is show below:`n`n`nTicket Number: $Ticket`n`nUser's Email Address: $UserID`n`nRequstor's Email Address: $RequestorID`n`n`nIf you would like to send the email, click Yes.`nOtherwise, click No."
$Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
if ($Result -eq "No")
{
Exit-PSSession
}
else
# send email
{
Send-MailMessage -To "<$UserID>" -bcc "<$Username#dana.com>" -from "<itservicedesk#x.com>" -Subject $global:subject -SmtpServer "mailrelay.x.com" -BodyAsHtml -body $global:body
}
}
Function Clean-Memory {
Get-Variable |
Where-Object { $startupVariables -notcontains $_.Name } |
ForEach-Object {
try { Remove-Variable -Name "$($_.Name)" -Force -Scope "global" -ErrorAction SilentlyContinue -WarningAction SilentlyContinue}
catch { }
}
}
So the real question is how to embed a image into the HTML document from a attachment
CID aka Content ID will allow you to attach a image and then use that attached image in the document. Avoid using spaces in the Content ID name.
Send-MailMessage -To "Test#Test.com" -from "Test2#Test.com" -SmtpServer SMTP.TEST.NET -Subject "Hello" -BodyAsHtml -Body "<img src='cid:Test.png'>" -Port 25 -Attachments "C:\Users\Test\Test.png"
You are using
$att1 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive1.png")
$att2 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive2.png")
$att3 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive3.png")
$att4 = new-object Net.Mail.Attachment ("T:\PS Scripts\Images\shareddrive4.png")
$att1.ContentId = "image1.png"
$att2.ContentId = "image2.png"
$att3.ContentId = "image3.png"
$att4.ContentId = "image4.png"
but when you send the mail you are not attaching those attachments
Send-MailMessage -To "<$UserID>" -bcc "<$Username#dana.com>" -from "<itservicedesk#x.com>" -Subject $global:subject -SmtpServer "mailrelay.x.com" -BodyAsHtml -body $global:body
You could stop using the Net.Mail.Attachment and instead do something like
$Body = #"
<html>
<body style="font-family:calibri">
<b>This is image 1</b>
<img src='cid:TEST1.png'>
<b>This is image 2</b>
<img src='cid:Test2.png'>
</body>
</html>
"#
Send-MailMessage -To "Test#Test.com" `
-from "Test2#Test.com" `
-SmtpServer Test.smtp.com `
-Subject "Hello" `
-BodyAsHtml -body $body `
-Attachments "C:\Test\TEST1.png", "C:\Test\TEST2.png"
You can embed the image into the HTML, therefore there are no extra files.
It is replacing
{img=file}
with data URL
{src="data:image/png;base64,[base64 encoded long string representing the image]}
There are many online converters that can convert your image file into the required code.
Just google for Image to Data URI converter.
Here is a simple example using MailKit. I had do download the packages from https://www.nuget.org/packages/MimeKit and https://www.nuget.org/packages/MailKit and unpack with 7Zip as PowerShell was struggling to install from the CLI. I got some ideas from here but wanted to add an example of an embedded image, https://adamtheautomator.com/powershell-email.
You can do all sorts with MimeKit and MailKit including modern Auth which is great. It's also supper fast and the Client and even a Connection can be used in a loop to send lots of messages. There is probably an upper bound on how long to use a connection without refreshing?
$mailServer = "domain-com.mail.protection.outlook.com"
$SMTP = New-Object MailKit.Net.Smtp.SmtpClient
Add-Type -Path ".\mailkit.3.3.0\netstandard2.0\MailKit.dll"
Add-Type -Path ".\mimekit.3.3.0\netstandard2.0\MimeKit.dll"
$SMTP.Connect($mailServer, 25, [MailKit.Security.SecureSocketOptions]::StartTls, $False)
$Message = New-Object MimeKit.MimeMessage
$message.From.Add("a.person#domain.com");
$message.To.Add("b.person#domain.com");
$message.Subject = "Some Subject";
$builder = [MimeKit.BodyBuilder]::new();
$image = $builder.LinkedResources.Add($path);
$image.ContentId = [MimeKit.Utils.MimeUtils]::GenerateMessageId();
$body = #"
<html>
<body style="font-family:calibri">
<b>This is image 1</b>
<img src='cid:$($image.ContentId)'>
</body>
</html>
"#
$builder.HtmlBody = $body
#Now we just need to set the message body and we're done
$message.Body = $builder.ToMessageBody();
$SMTP.Send($Message)
$SMTP.Disconnect($true)
$SMTP.Dispose()
I have this below script to calculate the age of snapshots (snapshots older than one day to be precise) in our environment. My code and current output are as below:
Add-PSsnapin VMware.VimAutomation.Core
# HTML formatting
$a = "<style>"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: LightBlue}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: white}"
$a = $a + "</style>"
Connect-VIServer -Server ******-User *****-Password *****
# Main section of check
Write-Host "Checking VMs for for snapshots"
$date = Get-Date
$datefile = Get-Date -UFormat '%m-%d-%Y-%H%M%S'
$filename = "C:\Temp\snaps_older_than_3\" + $datefile + ".htm"
$ss = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object vm, name, SizeGB, SizeMB, Created, powerstate,
#{Name='Age';Expression={(New-TimeSpan -Start $_.Created -End $date).Days}} |
ConvertTo-Html -Head $a -Body "<H2>VM Snapshot Report </H2>" |
Out-File $filename
Write-Host " Complete " -ForegroundColor Green
Write-Host "Your snapshot report has been saved to:" $filename
$SMTPServer = "******"
$SMTPPort = 25
$username = "******"
#Define the receiver of the report
$to = "******"
$subject = "VM Snapshot Report"
$body = "VM Snapshot Report"
$attachment = New-Object Net.Mail.Attachment($filename)
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.Body = $body
$message.To.Add($to)
$message.From = $username
$message.Attachments.Add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
#$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($message)
Write-Host "Mail Sent"
What I want to do is, in the below piece of code I want to determine the color of my age cell according to the age value. For example, if age is less than 3 I want that cell to be colored in green, if it is 3 should be in blue, if it crosses it should be red.
$ss = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object vm, name, SizeGB, SizeMB, Created, powerstate,
#{Name='Age';Expression={(New-TimeSpan -Start $_.Created -End $date).Days}} |
ConvertTo-Html -Head $a -Body "<H2>VM Snapshot Report </H2>" |
Out-File $filename
I have googled a lot and found below piece of code by someone, but I seriously cannot make this work.
$servers = "mccoyb02", "foo", "mccoyb01", "reisrv1"
$path = "c:\ephemeral\uptime.html"
$header = #"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>System Status Report</title>
<style type="text/css">
<!--
body {
background-color: #E0E0E0;
font-family: sans-serif
}
table, th, td {
background-color: white;
border-collapse:collapse;
border: 1px solid black;
padding: 5px
}
-->
</style>
"#
$body = #"
<h1>Server Status</h1>
<p>The following report was run on $(get-date).</p>
"#
$results = foreach ($server in $servers) {
if (Test-Connection $server -Count 1 -EA 0 -Quiet) {
$status = "Up"
} else {
$status = "Down"
}
[PSCustomObject]#{
ServerName = $server
Reuslts = $status
}
}
$results | ConvertTo-Html -Head $header -Body $body | foreach {
$PSItem -replace "<td>Down</td>", "<td style='background-color:#FF8080'>Down</td>"
} | Out-File C:\Ephemeral\uptime.html
& .\uptime.html
Output:
the video from Jeffrey Hicks (https://www.youtube.com/watch?v=QdK3qM5jnYw) pointed me in the right direction. And the article at Petri got the solution to style cells (and not only rows). I recommend you also watch/read those.
I've edited also the $head variable to a Here-String for easier reading and editing.
The styling of cells requires it to first convert the object to a XML object (mind the -Fragment switch!). This XML object can then be parsed, edited and finally converted to HTML. Hope the comments are clear.
Add-PSsnapin VMware.VimAutomation.Core
# HTML formatting
$head = #"
<style>
BODY{background-color:white;}
TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: LightBlue}
TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: white}
.green{background-color:#d5f2d5}
.blue{background-color:#e0eaf1}
.red{background-color:#ffd7de}
</style>
"#
Connect-VIServer -Server ****** -User ***** -Password *****
# Main section of check
Write-Host "Checking VMs for for snapshots"
$date = Get-Date
$datefile = Get-Date -UFormat '%m-%d-%Y-%H%M%S'
$filename = "C:\Temp\snaps_older_than_3\" + $datefile + ".htm"
# Convert the selection to an XML object
[xml]$xmlObject = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object vm, name, SizeGB, SizeMB, Created, powerstate,
#{Name='Age';Expression={(New-TimeSpan -Start $_.Created -End $date).Days}} |
ConvertTo-Html -Fragment
# Parse XML object and set colour class according to value in last column ("Age")
for($i=1;$i -le $xmlObject.table.tr.count-1;$i++) {
if(($xmlObject.table.tr[$i].td[-1] -as [int]) -lt 3) {
$xmlObject.table.tr[$i].ChildNodes[($xmlObject.table.tr[$i].ChildNodes.Count-1)].SetAttribute('class','green')
} elseif (($xmlObject.table.tr[$i].td[-1] -as [int]) -eq 3) {
$xmlObject.table.tr[$i].ChildNodes[($xmlObject.table.tr[$i].ChildNodes.Count-1)].SetAttribute('class','blue')
} else {
$xmlObject.table.tr[$i].ChildNodes[($xmlObject.table.tr[$i].ChildNodes.Count-1)].SetAttribute('class','red')
}
}
# Define body and append the modified XML object
$body = #"
<H2>VM Snapshot Report </H2>
$($xmlObject.innerxml)
"#
# Convert to HTML and save the file
ConvertTo-Html -Head $head -Body $body |
Out-File $filename
Write-Host " Complete " -ForegroundColor Green
Write-Host "Your snapshot report has been saved to:" $filename
$SMTPServer = "******"
$SMTPPort = 25
$username = "******"
#Define the receiver of the report
$to = "******"
$subject = "VM Snapshot Report"
$body = "VM Snapshot Report"
$attachment = New-Object Net.Mail.Attachment($filename)
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.Body = $body
$message.To.Add($to)
$message.From = $username
$message.Attachments.Add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
#$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($message)
Write-Host "Mail Sent"
I'm looking for a method to import a template HTML file in PowerShell and being able to populate it with variables, which in turn sends an e-mail in HTML format containing user data.
I already know how to send the HTML e-mail. And, currently have HTML in a 'here' string embedded in the code. I want to take it a step further, by being able to grab an HTML template based on country code. So, if the user is in the US, it'll get a English HTML data filled e-mail, if they're dutch, they'll get it in Dutch, etc.
function SendMessage {
Param(
[Parameter(Position=0,Mandatory=$true)]
[string]$Identity,
[Parameter(Position=1,Mandatory=$true)]
[string]$Body
)
$Subject = "Important information - Do not delete this email. Welcome to Voicemail"
$SmtpClient = New-object system.net.mail.smtpClient
$MailMessage = New-Object system.net.mail.mailmessage
$CredentialFile = ".\UMcloud-creds.txt"
$password = Get-Content $CredentialFile| ConvertTo-SecureString -Force
$UMCloudAdmin = ""
$SmtpClient.Credentials = New-Object System.Net.NetworkCredential($UMCloudAdmin, $Password)
$smtpclient.Host = "smtp-in.net"
$MailMessage.From = "Voicemail <P#domain.net>"
$MailMessage.To.clear()
$MailMessage.To.Add($Identity)
$MailMessage.Subject = $Subject
$Mailmessage.Body = $body
$MailMessage.IsBodyHtml = 1
$Logofilepath = ((Resolve-Path .\).Path) + "\logo.jpg"
$attachment = New-Object System.Net.Mail.Attachment -ArgumentList $LogoFilePath
$attachment.ContentDisposition.Inline = $True
$attachment.ContentDisposition.DispositionType = "Inline"
$attachment.ContentType.MediaType = "image/jpg"
$attachment.ContentId = "logo.jpg"
$MailMessage.Attachments.Add($attachment)
do {
$Continue = $false
try {
$smtpclient.Send($MailMessage)
Write-LogFile $OutputLogFile ("[SUCCESS] {0} {1}" -f $identity, $UMExtension)
Write-LogFile $customemaillog ("[SUCCESS] {0} {1}" -f $identity, $UMExtension) | out-null
$Continue = $true
} catch {
sleep -s 10
Write-LogFile $OutputLogFile "[ERROR] $Identity $_.Exception.Message"
Write-LogFile $CustomEmailLog "[ERROR] $Identity $UMExtension"
Write-Error $_.Exception.Message
}
} until($Continue -eq $true)
} # End send message
$WelcomeText = Get-Content -Path ".\$CountryID.txt"
$Body = #"
<html>
...
</html>
"#
The here string is part of the script, I'd like to be able to import it from TXT file as not to clutter the script.
Instead of using a text file, create a powershell file (ps1) for each html language format you want. Within those files, you can set a single variable as the html text (file EN_US.ps1):
$bodyENUS = #"Dear <b><font color=red>user</b></font> <br>
This is a test <b>HTML</b> email for your language preference<br>
Sincerely,<br> PdeRover<br>"
You can then pass the variable into the main ps file using two ways: Dot Sourcing or using a Global Variable.
Dot Sourcing: calling the variable by providing the file name.
In the main file:
..\EN_US.ps1
..\PT_PT.ps1
$smtp = "Exchange-Server"
$to = $Identity
$from = "Voicemail <P#domain.net>"
$subject = "This is a Test of HTML Email"
if (user is English speaking){
$bodyByLang = $bodyENUS}
elseif (user is Portuguese speaking) {
$bodyByLang = $bodyPTPT}
send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $bodyByLang -BodyAsHtml -Priority high
Global Variable: prefixing a variable with $Global:and calling the file during runtime. $Global: bodyENUS Then calling it using $bodyENUS
I asked my own SO question about the difference/best practice of using them. May be worth a read.
This should be enough to point you in the right direction.
i use the script below to send emails from a powershell script.
$smtpServer = "mail.company.com"
$smtpFrom = "Check <check#company.com>"
$smtpTo = "user1#company.com"
$messageSubject = "Daily Check from $thedate"
$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
$message.Subject = $messageSubject
$message.IsBodyHTML = $true
$message.Body = $Body | ConvertTo-HTML -head $style -body $Body
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($message)
It works fine untill i add more reciepients like this...
$smtpTo = "user1#company.com", "user2#company.com"
I also tried putting it inside an array like this....
$smtpTo = #("user1#company.com", "user2#company.com")
None of them work for me. Hope someone can help
The .To property of System.Mail.MailMessage is a collection that you can add emails to.
$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
$Message.to.add('myotheremail#mydomain.net')
$message.Subject = $messageSubject
$message.IsBodyHTML = $true