Change Powershell script to send the email with embedded text - powershell

I would like to modify the script below, to send the email with embedded text, without removing the html attachments.
The data it should embed into the email is found at: "C:\Users\Users\Summary\SummaryCSV.txt"
Here is the Powershell Script which needs to be modified:
# Check to see we have all the arguments
If (Test-Path -Path "C:\Users\Users\Summary\SummaryCSV.txt") {
#Send Email with HTML as attachment and no text embedded
$FullPath=$args[0]
#Get an Outlook application object
$o = New-Object -com Outlook.Application
$mail = $o.CreateItem(0)
#2 = High importance message
$mail.importance = 1
$mail.subject = "Ready to be retrieved: $(get-date)"
$mail.body = "Summary $(get-date)"
#separate multiple recipients with a ";"
$mail.To = "email#email1.com"
# Iterate over all files and only add the ones that have an .html extension
$files = Get-ChildItem $FullPath
for ($i=0; $i -lt $files.Count; $i++) {
$outfileName = $files[$i].FullName
$outfileNameExtension = $files[$i].Extension
# if the extension is the one we want, add to attachments
if($outfileNameExtension -eq ".html")
{
$mail.Attachments.Add($outfileName);
}
}
$mail.Send()
# give time to send the email
Start-Sleep 5
# quit Outlook
$o.Quit()
#end the script
#exit
}
Thanks in advance for your assistance.

Based on your specifications:
# Check to see we have all the arguments
If ((Test-Path -Path C:\Users\Users\Summary\SummaryCSV.txt) -and (Test-Path -Path C:\Users\Users\Summary\SummaryCSV.txt)) {
#Send Email with HTML as attachment and no text embedded
$FullPath=$args[0]
$embeddedText = Get-Content -Path C:\Users\Users\Summary\SummaryCSV.txt -Raw
#Get an Outlook application object
$o = New-Object -com Outlook.Application
$mail = $o.CreateItem(0)
#2 = High importance message
$mail.importance = 1
$mail.subject = "Ready to be retrieved: $(get-date)"
$mail.body = "Summary $(get-date)`r`n$embeddedText"
#separate multiple recipients with a ";"
$mail.To = "email#email1.com"
# Iterate over all files and only add the ones that have an .html extension
$files = Get-ChildItem $FullPath
for ($i=0; $i -lt $files.Count; $i++) {
$outfileName = $files[$i].FullName
$outfileNameExtension = $files[$i].Extension
# if the extension is the one we want, add to attachments
if($outfileNameExtension -eq ".html") {
$mail.Attachments.Add($outfileName);
}
}
$mail.Send()
# give time to send the email
Start-Sleep 5
# quit Outlook
$o.Quit()
#end the script
#exit
}

Related

How to find path for outlook so I can send emails with scripts

I have created a powershell script to send csv files automatically using Task Scheduler. I feel as if I am making a silly mistake with my pathing as nothing is sending.
I have testing the script below.
if($args.Count -lt 1)
{
Write-Host "Use: SendMail.ps1 <"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office\Microsoft Outlook 2010.lnk">"
Write-Host
Write-Host "<"C:\CSV">"
Write-Host
exit
}
$FullPath=$args[0]
#Get an Outlook application object
$o = New-Object -com Outlook.Application
$mail = $o.CreateItem(0)
#2 = High importance message
$mail.importance = 2
$mail.subject = "CSV File"
$mail.body = "Here is the CSV file."
#separate multiple recipients with a ";"
$mail.To = <---->
#$mail.CC = <OTHER RECIPIENT 1>;<OTHER RECIPIENT 2>
# Iterate over all files and only add the ones that have an .csv extension
$files = Get-ChildItem $FullPath
for ($i=0; $i -lt $files.Count; $i++) {
$outfileName = $files[$i].FullName
$outfileNameExtension = $files[$i].Extension
# if the extension is the one we want, add to attachments
if($outfileNameExtension -eq ".csv")
{
$mail.Attachments.Add($outfileName);
}
}
$mail.Send()
# give time to send the email
Start-Sleep 20
# quit Outlook
$o.Quit()
#end the script
exit
I believe that the following is incorrect:
Write-Host "Use: SendMail.ps1 <"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft Office\Microsoft Outlook 2010.lnk">"
But I am unsure as to what the path should be.
The path should be something like:
C:\Program Files (x86)\Microsoft Office\root\Office16\Outlook.exe
This link has a few methods of finding the path to the executable of a running process:
http://www.softwareok.com/?seite=faq-Windows-10&faq=152

Save all attachments from mail

I have a script that is supposed to download all attachments from "Inbox" then move them to another folder named "Processed". I filter mails by subject. If exist then download all attachments and move the mails.
For example I have 5 mails with attachments (xls) the subject are named like:
BB_asd_green_dsa
AD_acv_blue_sf
FD__c_d_red_sa
CV_saas_white_sdsd
as_dc_asa_purple
When I start the script it saves 3 attachments, the mails with attachments are moved too. And then it stops.
Second start. It saves 1 attachment & moves 1 mail
And one last manual start script saves the last attachment and moves the mail.
For what reason doesn't the script save and move all attachments with their mails?
Here is the script:
$olFolderInbox = 6
$outlook = New-Object -Com Outlook.Application;
$ns = $outlook.GetNameSpace("MAPI");
#$ns.Logon("Outlook")
#$ns.SendAndReceive($true)
#Start-Sleep -s 0
$inbox = $ns.GetDefaultFolder($olFolderInbox)
$messages = $inbox.Items
Write-Host $messages.Count
foreach ($message in $messages) {
$msubject = $message.Subject
$b = $msubject.Filename
$filepath = "D:\Users\h.yordanov\Desktop\convertexltohtm\xls\"
$message.Attachments | foreach{
Write-Host $message.Filename
$a = $_.Filename
$msubject = $message.Subject
$msubjectW = $msubject -replace '[^0-9]', ''
$b = $msubjectW + ".xls"
if ($msubject.Contains("green") -or $msubject.Contains("blue") -or $msubject.Contains("green") -or $msubject.Contains("white") -or $msubject.Contains("purple")) {
$_.SaveAsFile((Join-Path $filepath $b))
}
}
$MoveTarget = $inbox.Folders.Item("Processed")
[void]$message.Move($MoveTarget)
}
I used this script to move the mails, but still not all 5 mails are moved at once:
$Date = [DateTime]::Now.AddDays(-180)
$Last6Months = $Date.tostring("MM/dd/yyyy")
$o = New-Object -comobject outlook.application
$n = $o.GetNamespace(“MAPI”)
$Account = $n.Folders | ? { $_.Name -eq 'h.yordanov#sample.com' };
$Inbox = $Account.Folders | ? { $_.Name -match 'Inbox' };
$TargetFolder = $Inbox.Folders.Item('Processed')
$Inbox.Items |
Where-Object -FilterScript {
$_.senton -ge "$Last6Months"
} |
ForEach-Object -Process {
[void]$psitem.Move($TargetFolder)
}
Btw i am using MS office Pro plus 2010 64-bit

Download emails from outlook using powershell?

How do I reference a specific email address in this code it always directs to
the default email account. I have multiple email accounts in my outlook and I want to download emails from a different account which I want to reference by that email address . I have a feeling
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
has to be changed please give suggestions.
`[CmdletBinding(DefaultParameterSetName="All")] `
`Param(
[Parameter(Mandatory=$true,
Position=0,
HelpMessage='Folder path to store emails. Do not use quotation marks even if the path has spaces.',
ValueFromPipelineByPropertyName=$true
)]
[Alias("Destination", "Dest", "FullName")]
[String]$DestinationPath, `
[Parameter(ParameterSetName="All")]
[Parameter(Mandatory=$true,ParameterSetName="Unread")]
[Switch]$UnreadOnly,
[Parameter(ParameterSetName="Unread")]
[Switch]$MarkRead
)
#Removes invalid Characters for file names from a string input and outputs
the clean string
` #Similar to VBA CleanString() Method
#Currently set to replace all illegal characters with a hyphen (-)
Function Remove-InvalidFileNameChars {`
param(
[Parameter(Mandatory=$true, Position=0)]
[String]$Name
)
return [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '-')
}
#Test for destination folder nonexistence
if (!(Test-Path $DestinationPath)) {
#Set values for prompt and menu
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Confirmation Choice"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Negative Response"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$title = "Invalid Destination"
$message = "The folder you entered does not exist. Would you like to create the folder?"
#Prompt for folder creation and store answer
$result = $host.UI.PromptForChoice($title, $message, $options, 0)
#If yes, create.
if ($result -eq 0) {
New-Item $DestinationPath -ItemType Directory | Out-Null
Write-Host "Directory created."
}
#If no, exit
else {exit}
}
#Add a trailing "\" to the destination path if it doesn't already
if ($DestinationPath[-1] -ne "\") {
$DestinationPath += "\"
}
#Add Interop Assembly
Add-type -AssemblyName "Microsoft.Office.Interop.Outlook" | Out-Null
#Type declaration for Outlook Enumerations, Thank you Hey, Scripting Guy! blog for this demonstration
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$olSaveType = "Microsoft.Office.Interop.Outlook.OlSaveAsType" -as [type]
$olClass = "Microsoft.Office.Interop.Outlook.OlObjectClass" -as [type]
#Add Outlook Com Object, MAPI namespace, and set folder to the Inbox
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNameSpace("MAPI")
#Future Functionality to Receive Email before saving - Still Needs Testing
#$outlook.Session | Out-Null
#$outlook.Session.SendAndReceive($false) | Out-Null
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
#Iterate through each object in the chosen folder
foreach ($email in $folder.Items) {
#Get email's subject and date
[string]$subject = $email.Subject
[string]$sentOn = $email.SentOn
#Strip subject and date of illegal characters, add .msg extension, and combine
$fileName = Remove-InvalidFileNameChars -Name ($sentOn + "-" + $subject + ".msg")
#Combine destination path with stripped file name
$dest = $DestinationPath + $fileName
#Test if object is a MailItem
if ($email.Class -eq $olClass::olMail) {
#Test if UnreadOnly switch was used
if ($UnreadOnly) {
#Test if email is unread and save if true
if ($email.Unread) {
#Test if MarkRead switch was used and mark read
if ($MarkRead) {
$email.Unread = $false
}
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
#UnreadOnly switch not used, save all
else {
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
}
Think You can do something like this:
$outlook = New-Object -ComObject Outlook.Application
$namespace =$outlook.GetNameSpace("MAPI")
$namespace.Logon("Profilename","profilepassword",$false,$false)
Also you can use Assembly - Microsoft.Exchange.WebServices.dll and do something like this:
[Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll") > $nul
$getref = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
$getref.Credentials = New-Object Net.NetworkCredential('Account', 'Password', 'domain.local')
$getref.AutodiscoverUrl("Account#domain.com")
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($getref,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
#Write-Host "Total Messages:" $inbox.TotalCount
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($inbox.TotalCount)
$fiItems = $getref.FindItems($Inbox.Id,$ivItemView)
[Void]$getref.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
if ($Item.From -EQ "Somemail#domain.com") {
New-Object -TypeName PSObject -Property #{
Emails = $Item.From
} | select Emails
}
}
Hello! You can load a body text (to html) something like this:
foreach($Item in $fiItems.Items){
if ($Item.Subject -match "Something special") {
$Item.Load()
$Save = ((Get-Date -Format "yyMMdd") + "-" + $Item.Subject[0] + ".html")
New-Item -Path "C:\file\exch\" -name $Save -ItemType file -value $Item.Body.Text
}
}

Powershell - Email does not have same format as text despite Out-string

Folks,
Googling shows me lots of folks have this problem, however the answers I'm getting do not seem to work for me. Either that, or I don't understand.
Situation: I have a script that polls and gives a file count. It works great and I pipe it to a text file
Foreach ($Directory in $Directories) {
Write-Output "You have $Results files in that folder" | Out-File "C:\Filecheck.txt" -Append
}
Filecheck looks great. It does the above loop 6 times (as I have 6 directories) and it does the carriage returns.
In email, its all jumbled up. On here, someone suggested I use the out-string, so Ive done this:
$body = GC "C:\Filecheck.txt" | Out-string
I've also seen
$body = GC "C:\Filecheck.txt" -Raw
I get the email fine, but again, its still all one line, with no carriage returns.
Anyone have any idea? I know Im so close.
You could try using the [Environment] newline. I tested with the code below and the e-mail looked good and with the correct line breaks:
$DirectoriesFiles = 2,3,4,5
$newline = [Environment]::NewLine
$body = "List of number of files" + $newline
Foreach ($numOfFiles in $DirectoriesFiles) {
$body += "You have $numOfFiles files in that folder" + $newline
}
$ol = New-Object -comObject Outlook.Application
$Mail = $ol.CreateItem(0)
$Mail.To = "someone"
$Mail.Subject = "some test e-mail"
$Mail.Body = $body
$Mail.save() #or send
For the example's sake I just assumed you have an array with the number of files in the folder, but I think you can understand how to adapt to your context from here. My resulting e-mail looked like this:
List of number of files
You have 2 files in that folder
You have 3 files in that folder
You have 4 files in that folder
You have 5 files in that folder
Thanks for your help. My company email didn't like the format, but I format in html (using ) and utilize IsBodyHTML tag, it works like a charm!
Del "D:\Filecheck.txt"
$Directories = GC "D:\Directory.txt"
Foreach ($Directory in $Directories) {
$Results = (Get-ChildItem $Directory).count
If ($Results -gt 0) {
Write-Output "...You have $Results files stuck in $Directory...<br><br> " | Out-File "D:\Filecheck.txt" -Append
} else {
Write-Output "Phew! We're good, <br><br>" | Out-File "D:\Filecheck.txt" -Append
}
$Results = $null
}
$body = GC "D:\Filecheck.txt"
Add-PSSnapin Microsoft.Exchange.Management.Powershell.Admin -erroraction silentlyContinue
$SmtpClient = new-object system.net.mail.smtpClient
$SmtpServer = "localhost"
$SmtpClient.host = "relay.me.local"
$msg = new-object Net.Mail.MailMessage
$msg.IsBodyHTML = $true
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "TelluRyesFileCheck#me.you"
$msg.To.Add("me#you.org")
$msg.Subject = "Checking if files exist on 9901/2"
$msg.Body = $body
$SmtpClient.Send($msg)

How to get PowerShell to send email with file paths

I have the following script where I'm trying to get the path location of some files emailed to me but I am having a problem passing a variable to a function. I get the email but the body is empty.
Can someone help me out here?
Thanks,
Lamar Thomas
function sendMail($VirusLoc){
Write-Host "Sending Email"
#SMTP server name
$smtpServer = "mailhost.maxor.com"
#Creating a Mail object
$msg = new-object Net.Mail.MailMessage
#Creating SMTP server object
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
#Email structure
$msg.From = "me#xxxxxx.com"
$msg.ReplyTo = "me#xxxxx.com"
$msg.To.Add("me#xxxxx.com")
$msg.subject = "CryptoLocker Virus Found On pcname"
$msg.body = $VirusLoc
#Sending email
$smtp.Send($msg)
}
Clear-Host
$arg = ("\\mxfsa01\Supsys\Red River Wholesale-old")
Set-Location $arg
$Files = Get-ChildItem -Recurse |Where-Object {$_.name -Like "Decrypt_Instruction.txt"} | % {
# Write-Host $_.FullName
$VirusLoc = $_.FullName
Write-Host $VirusLoc
}
sendMail
You need to provide an argument for the VirusLoc parameter of your function e.g.:
sendMain -VirusLoc $VirusLoc
BTW that variable is only holding a single filename. Is there are multiple files you may want to change this line:
$VirusLoc = $_.FullName
to
$VirusLoc += "`n" + $_.FullName