Outputting CSV to String/Table - powershell

I have a CSV with data that is to be emailed to me at the end of a powershell script. I know that I can attach the CSV file to the email itself, but I'd like to know how to output the data from the CSV straight into the body, formatted properly. I assume that this would involve converting the CSV to a String or something.
I've tried things like ConvertTo-Csv along with Format-Table, but this comes up without formatting. I've thought of looping through the csv line-by-line but I'm not sure where to go from there.

You need to use ConvertTo-Html
$body = $YOUR_CSV_DATA | ConvertTo-Html -Fragment
Send-MailMessage -To 'abc#example.com' -From 'admin#example.com' -Subject 'Your report' -BodyAsHtml -Body $body -SmtpServer 'smtp.example.com'

Related

Who to email based on attachment file

Without using a ton of ElseIf statements is it possible to select the the recipient of an email based on the file that will be attached to the email while iterating over all files in a folder?
I have started building this without the foreach get-ChildItem running over the folder where I create the email object, assign specific recipients, and choose a specific file out of the folder, but this is quite tedious and repetitive. I feel like there has to be a way to use an array of arrays or something where based on the file that the loop is on it pulls through the recipients and maybe a custom subject line.
There's tons of powershell email code out there so I won't repost that. Just not sure how to even attack this.
One option would be to have an accompanying CSV file, with rows for the filename, the recipient and the subject name etc. You could then import the CSV file using Import-Csv.
For example:
$emailList = Import-csv c:\users.csv
foreach ($line in $emailList) {
Write-Host "Sending message to $($line.emailAddress)"
Send-MailMessage -To $line.emailAddress `
-Subject $line.subject `
-Attachments $line.attachmentPath `
-Body $line.bodyText
}
and if you wanted to define the contents of the CSV in the PowerShell script, rather than using an external file, you could do something like:
$emailList = "emailAddress,subject,attachmentPath,bodyText
joe#bloggs.com,Attachment for Joe,c:\attachmentsToSend\joe.pdf,Attached is your file
Mary#bloggs.com,Mary's attachment,c:\attachmentsToSend\mary.pdf,Hello, Mary. Attached is your file
" | ConvertFrom-Csv
Put that above the foreach loop in the script

How to fix encoding with send-MailMessage in powerShell?

I'm trying to send email message from a powershell script but in the email all accented characters (ó, é etc) get scrambled.
What I'm doing is the following:
I use Import-CSV to import an ANSI encoded file.
foreach($item in $inputfile) send-MailMessage -Body $item.body -bodyAsHTML
I'm not a PC-user and the whole encoding thingy gives me headache.
I tried all the different encoding options of send-MailMessage without getting the expected result.

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).

Powershell using string and file content in email message body without breaking formatting

I have a Powershell script that has a part which needs to email some information. I have a requirement to include 2 pieces of information inside the message body, but I am having issues with formatting. The first part will be a line of text which I would like to simply store inside the powershell script as a variable, and the second part will be information from a text file. Below is a simplified version of what I want to do:
$INFO1="The following fruits are ready to eat:
"
$INFO2=get-content "info2.txt"
$BODY=$INFO1 + $INFO2
$BODY=$BODY | out-string
send-mailmessage -To myname#mydomain.com -Subject "Fruit Status" -From
fruit#mydomain.com -Body $BODY -Smtpserver smtp.mydomain.org -UseSsl
The file info2.txt contains the following info. 3 columns with a list of fruits with tab separators:
Col1 Col2 Col3
Apple Orange Pear
Banana Grape Strawbery
Kiwi Peach Apricot
The above code works but I get an email which looks like this:
The following fruits are ready to eat:
Col1 Col2 Col3 Apple Orange Pear Banana Grape
Strawbery Kiwi Peach Apricot
It keeps the line spaces in the $INFO1 stored variable string, but then places the content of the info2.txt file all in one continuous line, with no line breaks or tabbed formatting.
I tested this with the below changes whereby the line of text from the $INFO1 variable, is instead obtained by doing a get-content on the same piece of text from inside a file named "info1.txt". When I then append both pieces of information into the message body, the formatting is maintained and the email looks ok.
$INFO1=get-content "info1.txt"
$INFO2=get-content "info2.txt"
$BODY=$INFO1 + $INFO2
$BODY=$BODY | out-string
send-mailmessage -To myname#mydomain.com -Subject "Fruit Status" -From
fruit#mydomain.com -Body $BODY -Smtpserver smtp.mydomain.org -UseSsl
The following fruits are ready to eat:
Col1 Col2 Col3
Apple Orange Pear
Banana Grape Strawbery
Kiwi Peach Apricot*
I also notice that if I do the below using the first method, grabbing the file content first and THEN the string from variable, the formatting is also kept fine:
$BODY=$INFO2 + $INFO1
It is only when I start with the string from variable first, that it mucks up the formatting in the email for the file content part.
I would prefer to keep the script more compact and minimize writing out to files on disk and used stored variables. Is there a way I can use method 1 appending a string or multiple strings, followed by file content where formatting is kept? I do not wish to use HTML for this as it will overly complicate matters with the text file content I am working with so the body is just -body rather than -bodyashtml unless this is the only way to sort this.
I believe I have found the answer. I played with the get-content -RAW argument before but I think I was having trouble using it to get content stored in the pipeline. When I use it as below directly on a file with no other where clauses, it fixes the issue:
$INFO1="The following fruits are ready to eat:
"
$INFO2=get-content "info2.txt" -raw
$BODY=$INFO1 + $INFO2
$BODY=$BODY | out-string
send-mailmessage -To myname#mydomain.com -Subject "Fruit Status" -From
fruit#mydomain.com -Body $BODY -Smtpserver smtp.mydomain.org -UseSsl
Get-Content gets the content of the item at the location specified,
such as the text in a file. By default PowerShell will read the
content one line at a time and return a collection of System.String
objects. Carriage returns (CR/LF) are stripped from the original file
but when PowerShell displays a collection of strings, it will
re-insert carriage returns so that the display will look just like the
original file.
If you specify -raw, this behaviour is reversed and the entire file
will be read at once.

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