I'm wrote this script to look for NDR messages in Outlook. I want to find these messages and parse the body of the message to extract the email address the message bounced back from. Finding the messages with the subject is working fine. The issue I'm having is the body of the NDR emails are garbled with strange characters so I cannot parse them.
Anyone know how I can get around this?
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$ns = $outlook.GetNameSpace("MAPI");
$inbox = $ns.GetDefaultFolder($olFolderInbox)
$targetfolder = $inbox.Folders | ? { $_.name -eq "Dump" }
$targetfolder.items | % {
if($_.subject -match "Undeliverable"){
write-output $_.subject
write-output $_.SentOnBehalfOfName
write-output $_.body
}
}
sample from
$_.body
格浴㹬格慥㹤洼瑥瑨灴攭畱癩∽潃瑮湥祔数•潣瑮湥㵴琢硥⽴瑨汭※档牡敳㵴獵愭捳楩㸢⼼敨摡㰾潢祤ാ㰊㹰戼㰾潦瑮挠汯牯∽〣〰㘰∶猠穩㵥㌢•慦散∽牁慩≬䐾汥癩牥⁹慨慦汩摥琠桴獥敲楣楰湥獴漠牧畯獰㰺是湯㹴⼼㹢⼼㹰昼湯⁴潣潬㵲⌢〰〰〰•楳敺∽∲映捡㵥吢桡浯≡㰾㹰愼栠敲㵦洢楡瑬㩯湁牵条
䴮瑩慲牀换浣挮浯㸢湁牵条䴮瑩慲牀换浣挮浯⼼㹡戼㹲桔ⵥ慭汩愠摤敲獳礠畯攠瑮牥摥挠畯摬❮⁴敢映畯摮汐慥敳挠敨正琠敨爠捥灩敩瑮猧攠洭楡摡牤獥œں牴⁹潴爠獥湥桴”®«Aجُ䤠桴 ¶³¶¾´潣瑮湩敵ⱳ瀠敬獡ک¬—¼ٌ⁴¨ا£–ك›D“µھ—戼㹲⼼㹰瀼㰾牨晥∽
慭汩潴䄺“³اأطرں¨کO䁮’Rµ·潣≭䄾摮敲匮煥極䁮’Rµ·潣㱭گè㰾ہخാ吊敨攠洭楡摡牤獥¨⁵œ£صûاأ潣汵湤琧戠ءتœ±倠敬獡µµ’ج桴اأé¹کKœ£❴ⵥ慭汩愠摤敲獳愠摮琠祲琠敲敳摮琠敨洠獥慳敧晉琠敨瀠潲汢浥挠湯楴畮獥汰慥敳挠湯慴瑣礠畯”«ى
ل”¨ڑr㰮ہخാ㰊瀯ാ㰊㹰愼栠敲㵦›¥ک#¬–㩯±âکE‘]獁橩䁡’Rµ·潣≭䄾桢湩癡䄮کM‘Y —»»ن½’«ن´⼼㹡‘ù㹲桔ⵥ慭汩愠摤敲獳礠畯攠瑮牥摥挠畯摬❮⁴敢映畯摮汐慥敳挠敨正琠敨爠捥灩敩瑮猧攠洭楡摡牤獥œں牴⁹潴爠獥湥桴”®«Aجُ䤠桴
¶³¶¾´潣瑮湩敵ⱳ瀠敬獡ک¬—¼ٌ⁴¨ا£–ك›D“µھ—戼㹲⼼㹰⼼潦瑮ാ㰊牢㰾ہخ㰾ہخ㰾ہخ㰾ہخ㰾ہخാ㰊潦瑮挠汯牯∽㠣㠰㠰∰猠穩㵥¢ç•‘Wة¢∽慔潨慭㸢ڈ㰾㹢—èجُ³±¬›قوèئصêô‘\کNœ«س³êôم³›ؤœ§ھ›
¹¬‹êô㩳⼼㹢⼼㹰瀼䜾œ£ °¬‹œ§”²°d °›’R潣㱭„ാ㰊㹰湁牵条䴮¬“‘` —»»ن½’«ن´‘ù㹲⌠氦㭴⌠⸵⸱‱浳灴㔻〵㔠ㄮㄮ删卅䱏䕖⹒䑁⹒敒楣买瑯潆湵㭤ا¬کس³®ڈ“³ëü㭴⌠䵓偔㰣„ാ㰊㹰湁牤敓畱湩牀换浣挮浯戼㹲⌠氦㭴⌠⸵⸱‱浳灴㔻〵㔠ㄮㄮ删卅䱏䕖
⹒䑁⹒敒楣买瑯潆湵㭤ا¬کس³®ڈ“³ëü㭴⌠䵓偔㰣„ാ㰊㹰扁楨慮獁橩䁡’Rµ·潣㱭ہخാ ☣瑬※㔣ㄮㄮ猠瑭㭰㔵،ë⸵⸱‱䕒体噌剅䄮„q¹خ’ج¹‡䙴®ڈ“³،ù³±⁴ءتœ±♤瑧※匣呍⍐⼼㹰瀼伾楲楧慮敭獳条”«“©
°㩳⼼㹰瀼敲刾捥楥敶㩤س³نû硭⸳扲潣ㄨ⸰〲⸸㌱⸶⤵戠⁹塓䍓㑍昮扲潣൭ ㄨ⸰〲⸸㤱⸲ㄴ
楷桴䴠قونû¤¬گ½³…ش⁐敓癲牥椠㐱㌮ㄮ㐷ㄮ※敗Ɽ㐠䨠湵㈠ഴ 㜱㐺㨳㤲ⴠ㐰〰ⵘ牉湯潐瑲䄭¬—灓浡䘭مéصûاأ㩤¬_î´堊䤭نû‚آêô湁楴匭慰敒畳瑬›ڑM䉙䑁⌦㌴医ㅪ䕎䤶癥䝮獤㉢桊䅢䩄±’䈴شت䉅¶ç䩷ⵘ牉湯潐瑲䄭㩖䔠…]µئœ㭳㵩½¹¥㭴⸴㠹㤬㔷ㄬ㤳ㄲㄸ〲
☰畱瑯㬻ഠ †㵤焦潵㭴“µ❦猿慣❮〲ⰸㄲ☷畱瑯㬻㵡焦潵㭴㠱〳㐲㠹☳畱瑯഻堊匭剂㩓㔠㘮敒散癩摥›êَن´®_ڑm³±œ³⠠䕈佌攠慳⸲慭歲瑥硡獥灩浨潣⥭⠠㙛⸸㌲⸲㌱⸵㜱崵ഩ 戠⁹浶㍸爮换挮浯眠瑩ط¦…ش⽐䱔⽓䍒ⴴ䡓㭁〠‴畊〲㐱ㄠ㨷㌴ㄺ‵〭〴ര堊䤭نû‚آêô噁›㵅Œ—Iâ´—
â☽畱瑯㐻㤮ⰸ㜹ⰵ㌱㈹㐱㈵〰焦潵㭴،ù†搠☽畱瑯瀻晤㼧’صœں¢ى㠰㈬㜱½¹¥㭴گô☽畱瑯ㄻ〶¤¨㠷焦潵㭴敒散癩摥›êَن´®_ڑm³±œ³⠠䕈佌挠灲敳浣楡桬ぴ⸲佃偒剏呁⹅佌䅃⥌⠠㉛㐰ㄮ㠲㔮⸲崰ഩ 戠⁹獥㉡洮ظہ敫慴數獳椮桰硭挮浯眠瑩ط¦…ش⽐䱔⽓䕁ㅓ㠲匭䅈،°㔰䨠湵㈠ഴ ㈰
㐺㨱㠵☠㐣㬳㔰〰敒散癩摥›êَن´u“·”²ن½ھ›·َぢ‱ㄨ⸰〴㈮㌵㌮⤰戠⁹剃卐䍅䅍䱉呈㈰䌮„y×ô䅒䕔䰮䍏䱁⠠〱㐮⸰ㄱ⸲㔱⤴眠瑩—ٌ ®â´¾°⁴䵓‚½³ °”´ؤ¦ㄠ⸴⸳㜱⸴㬱圠摥‴畊〲㐱ㄠ㨷ㄴ㔺،ا〭〴ര琊牨慥ⵤ湩敤㩸䄠♣㐣㬳偁䙡つ䵨䭏䕋半焹丹䍃‹C䜲…و㵑ഽ吊
牨慥ⵤ潔楰㩣䴠⁁䝈吠慲敤删捥灡〠⼶㐰㈯ഴ䘊潲㩭☠瑬䴻ؤµë¸䅴”µ«A›µؤµë¸‘b”µ«A’«ن´ëü㭴潔ഺ䌊㩃☠瑬吻慲敤敒慣䑰ک#µ…›µؤµë¸‘b”µ«A’«ن´ëü㭴畓橢捥㩴䴠⁁䝈吠慲敤删捥灡〠⼶㐰㈯ഴ䐊瑡㩥ˆL“‴畊〲㐱ㄠ㨷〴㐺‰〭〴ര䴊獥慳敧䤭㩄☠瑬䔻㘶㌹ぃ
㌸㌲㐳㜲䈴䘸䕃㈲㥃䐶㉂䄳䀸牐摯捵楴湯䰮’زخغëü㭴䥍䕍嘭牥楳湯›⸱ര䌊湯整瑮吭灹㩥›£›NکNخ؟¬ڑ›³چ“഻ऊ潢湵慤祲☽畱瑯ⴻⴭ㴭也硥側牡彴〰弰〰㔰た䌱㡆⹃䄱〵㑂〵焦潵㭴ⵘ慍汩牥›—ٌ ®â´¾°⁴䑃⁏潦饓³²J〲〰潃瑮湥汃獡㩳®_œ®ح¦œ«صû¬—’ھ‘[«
Aھ—›³ھ—‘a”ھ浉潰瑲湡散›³±›حخغ牐潩楲祴›³±›حخغⵘ楍敭䱏㩅‚‹نû®‡ة¢祂䴠قونû¤¬گ䴠浩佥䕌嘠⸶〰㌮㤷⸰㤴㌱敒畴湲倭瑡㩨䴠牡敫䅴”µ«A›µؤµë¸‘b”µ«A’«ن´⼼牰㹥⼼潦瑮ാ㰊戯摯㹹⼼瑨汭
It's likely a bug in Outlook 2013. See:
http://answers.microsoft.com/en-us/office/forum/office_2013_release-outlook/when-forwarding-or-replying-to-emails-the-text/61280c0d-0fd6-48cf-9318-184ee3e83da9
In my case I got the strange gibberish when trying to view the body of a non delivery report from an Outlook 2013 addin (not such which version of Exchange we're using). But when the addin is disabled, the body of the non-delivery report shows up just fine.
Related
I'm trying to write a PowerShell script that automates the way to retrieve all my emails with sender information in outlook and importing it on a text file.
I monitored this script that I created returns incomplete results.
Below here is my code for:
$namespace = $Outlook.GetNameSpace("MAPI")
$inbox = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
$emails = $inbox.items
ForEach ($email in $emails){
write-host $email.Subject
}
If "incomplete results" means that it's not returning all the emails you're expecting, there are a couple of things that I ran into when working with emails in Powershell:
It won't grab emails that are in folders under the Inbox. You have to call each folder separately. I had to setup a recusive loop to compile a list of them
Not all of your emails are actually stored in Outlook. By default, Outlook only pulls the last year of email form an email server. Sometimes it can show messages that exist on the server but they aren't actually downloaded.
EDIT: Here's the recursive function I built to get all the folders and subfolders within the Inbox.
# Create an ArrayList and immediately add the Inbox as the first folder in the list
[System.Collections.ArrayList] $folderList = #([PSCustomObject]#{
FolderPath = $inbox.FolderPath
EntryID = $inbox.EntryID
})
# Call the function to get all the folders and subfolders in the Inbox folder
Get-MailFolders $inbox.Folders
# Recusive function that will get all the folders and subfolders in the parent folder
function Get-MailFolders ($parent) {
foreach ($child in $parent) {
Write-Host "." -NoNewLine
$folderList.Add([PSCustomObject]#{
FolderPath = $child.FolderPath
EntryID = $child.EntryID
}) | Out-Null
Get-MailFolders ($child.Folders)
}
}
Continuing form my comment
Search for:
'PowerShell read outlook email name and subject'
hit(s)
https://devblogs.microsoft.com/scripting/use-powershell-to-data-mine-your-outlook-inbox
Read most recent e-mail from outlook using PowerShell
http://jon.glass/blog/reads-e-mail-with-powershell
olFolderInbox = 6
$outlook = new-object -com outlook.application;
$mapi = $outlook.GetNameSpace("MAPI");
$inbox = $mapi.GetDefaultFolder($olFolderInbox)
# Grab the specific properties from the messages in the Inbox:
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$mapi = $outlook.GetNameSpace("MAPI");
$inbox = $mapi.GetDefaultFolder($olFolderInbox)
$inbox.items|Select SenderEmailAddress,to,subject|Format-Table -AutoSize
# Results
<#
SenderEmailAddress To Subject
------------------ -- -------
notify#twitter.com Jonathan Glass Thomas Garnier (#mxatone) retweeted one...
mailing-list#rifftrax.com Riff Rediscover Puppets in our latest short!
notify#twitter.com Jonathan Glass [ Gunther ] (#Gunther_AR) retweeted one...
#>
I am trying to select multiple emails from on outlook inbox folder via mapi addressing and want to move a copy of these emails to another folder in the same inbox.
Unfortunately my script seems to do whatever it wants, sometimes copying 6 emails before stopping with following failure, sometimes stopping right with the first email.
Failure:
... "veeam")} | ForEach-Object {$_.Copy().Move($Namespace.Folders.Item("$ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [ForEach-Object], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.ForEachObjectCommand
I could not find any solution for this and I am sitting here confused since in another mailbox the code works just fine.
Of course I am setting the variables $Mailbox and $TempWorkPath beforehand.
Thanks in advance for your help.
Trying to run the code in a foreach-loop is less performant and ends with the same issue.
About 3 hours of google search did not help me at all.
Just moving the object causes the code to break, probably because of indexiation?
Add-Type -Assembly "Microsoft.Office.Interop.Outlook"
$OutlookSession = New-Object -ComObject Outlook.Application
$Namespace = $OutlookSession.GetNameSpace("MAPI")
$Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Items.Restrict('[UnRead] = True') | Where-Object {($_.Subject -match "ackup") -or ($_.SenderEmailAddress -match "veeam")} | ForEach-Object {$_.Copy().Move($Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Folders.Item("$TempWorkPath"))} | Out-Null
<# Do things with the selected/coppied emails #>
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($OutlookSession) | Out-Null
$OutlookSession = $null | Out-Null
In Theory an based on my tests in another folder this should work perfectly fine, create a copy of the email, move it to my folder and afterwards I can do things with it.
Well, I think I found my way around the issue. Running the command in a while loop instead of an foreach loop seems to work better.
$Inbox = $Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Items.Restrict('[UnRead] = True') | Where-Object {($_.Subject -match "ackup") -or ($_.SenderEmailAddress -match "veeam")}
$MailCounter = $Inbox.Count
$HelperForCounting = 0
while ($MailCounter -gt $HelperForCounting)
{
$Inbox[$MailCounter].Copy().Move($Namespace.Folders.Item("$Mailbox").Folders.Item("Posteingang").Folders.Item("$TempWorkPath"))
$MailCounter = $MailCounter - 1
}
Greetings
I also had this issue with processing emails on Outlook. My overall scheme is to process emails folder by folder. I traced the issue to the Emails.getNext() function. My completely uneducated guess is it has something to do with parallel processing of Emails and how it grabs them in ForEach() and getNext(). The problem went away by using the getLast().
Note in the following code it will just move all read emails to archive folder and then some unread emails to corporate dump folder and most unread emails to the unread folder. This is itself just a mutation on the .p0r email script. There is a > $null at the end of the function block is where I originally had it on the ForEach loop and it worked as one would expect, but it does not work on the While loop blocking function. Instead that had to be moved to the location in the move unread section. Still a lot of room for improvement, getting some strange com errors but it will process through an inbox so long as GetLast() email is moved out of the folder.
As for my rationale on the root cause, I noticed that the failure to read a whole inbox is dependent on the size of the inbox. So each run my go through 2/3 of the remaining emails in the inbox.
# OUTLOOK RULES #
#################
# OUTLOOK RULES #
#################
#Import Object Library?
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
# VARIABLES
$index=0;
$pstPath = "C:\YOURPATHHERE"
# DISPLAY INFO
function display( [string]$subject, [string]$color , [string]$out) {
# REQUIRED LENGTH OF STRING
$len = 20
# STRINGS THAT ARE LONGER WILL BE CUT DOWN,
# STRINGS THAT ARE TO SHORT WILL BE MADE LONGER
if ( $subject.length -lt 20 ){
$toadd=20-$subject.length;
for ( $i=0; $i -lt $toadd; $i++ ){
$subject=$subject+" ";
}
$len = $subject.length
}
else { $len = 20 }
$index=$index+1
Write-host -ForegroundColor $color -nonewline " |" ((($subject).ToString()).Substring(0,$len)).ToUpper()
}
# CREATING OUTLOOK OBJECT
$outlook = New-Object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
# GETTING PST FILE THAT WAS SPECIFIED BY THE PSTPATH VARIABLE
$pst = $namespace.Stores | ?{$_.FilePath -eq $pstPath}
# ROOT FOLDER
$pstRoot = $pst.GetRootFolder()
# SUBFOLDERS
$pstFolders = $pstRoot.Folders
$fArchive = $pstFolders.Item("Archive")
# PERSONAL SUBFOLDER
$personal = $pstFolders.Item("Personal")
# INBOX FOLDER
$DefaultFolder = $namespace.GetDefaultFolder(6)
# INBOX SUBFOLDERS
$InboxFolders = $DefaultFolder.Folders
# DELETED ITEMS
$DeletedItems = $namespace.GetDefaultFolder(3)
# EMAIL ITEMS
$Emails = $DefaultFolder.Items
$workingFile = [IO.Path]::GetTempFileName()
# PROCESSING EMAILS
$currentWriteFolder = $pstFolders.Item("Archive")
While ($Emails.count -gt 0) {
$Email = $Emails.GetLast()
#Move all reads into Archive
if (!$Email.Unread) {
$email.move($fArchive) > $null
continue
}
#Filter unread items by sender
$WriteString = $Email.SenderEmailAddress.ToString()
[IO.File]::WriteAllLines($workingFile, $WriteString)
if (Select-String -Path $workingFile -Pattern "company") {
$email.move($currentWriteFolder.Folders.Item("globalcorp"))
continue
}
$email.move($pstFolders.Item("Unread"))
} # > $null
[IO.File]::Delete($workingFile)
Write-host ""
I'm attempting to create a Send-Email function in a script which can change the email address each time the script is used. However, I'm currently suck being forced to use a static email:
function Send-Email (
$recipientEmail = "EMAIL",
$subject = "Ticket" + $type,
$body
) {
$outlook = New-Object -ComObject Outlook.Application
$mail = $outlook.CreateItem(0)
$mail.Recipients.Add("EMAIL")
$mail.Subject = ("Ticket - " + $type)
$mail.Body = $body # For HTML encoded emails
$mail.Send()
Write-Host "Email sent!"
}
I'd like to set it up so that I can define $recipientEmail and then later use this input with $mail.Recipients.Add("EMAIL") - I've beend doing $mail.Recipients.Add("$receipientemail") and the like without any luck and wondering if I'm approaching this completely wrong?
I'd like it to be set up in a way that it could use
[void] $listBox.Items.Add("Email1")
[void] $listBox.Items.Add("Email2")
[void] $listBox.Items.Add("Email3")
And accept that as the email to send to instead of only working with one email.
This whole thing rang a bell with me, and I went "code dumpster diving". I wrote this same function (more or less) a year ago. I'm not using $mail.recipients.add(); I'm using $Mail.To = $RecipientEmail; if I want multiple recipients, I simply -join ";" them and assign to $mail.To. The members $mail.CC and $mail.BCC work the same way:
Function Send-Email {
<#
.Synopsis
Sends Email using Microsoft Outlook
.DESCRIPTION
This cmdlet sends Email using the Outlook component of a locally-installed
Microsoft Office. It is not expected to work with the "Click-to-run" versions.
This version requires that Outlook be running before using the cmdlet.
.PARAMETER To
Must be a quoted string or string array, may not be omitted.
Specifies the address to send the message to. If an array, it will
be converted to a semicolon-delimited string. May contain contact
groups.
.PARAMETER Subject
Must be a quoted string, may not be omitted.
Specifies the subject of the message to be sent.
.PARAMETER Body
Must be a string or a string array, may not be omitted.
Contains the text of the message to be sent. If supplied as a string in double
quotes, any PowerShell variables will be expanded unless the leading $ is
escaped. If supplied in a script via a variable containing a here-doc, will
reproduce the here-doc. If supplied as an array, either by variable or by the
Get-Content cmdlet, the array elements will be joined with `r`n as "separators".
A body supplied via Get-Content will not have expanded variables; arrays created
in scripts using double quotes or via here-docs willl have expanded variables.
.PARAMETER CC
Must be a quoted string or string array, may be omitted.
Specifies an address to send a copy of the message to. If an array, it will be
converted to a semicolon-delimited string. All recipients can see that a copy
of the message was sent to the addresses here.
.PARAMETER BCC
Must be a quoted string or string array, may be omitted.
Specifies an address to send a copy of the message to. If an array, it will be
converted to a semicolon-delimited string. The recipients named here are not
displayed as a recipient of the message, even though they do receive the message.
.PARAMETER Attachments
Must be a quoted string or string array, may be omitted.
Specifies one or more files to be included with the message as attachments.
.INPUTS
This version of the cmdlet does not accept input from the pipeline
.OUTPUTS
No output to the pipeline is generated. The cmdlet does return an error code.
.EXAMPLE
Send-Email -To "boss#example.com" -Subject "Personnel Issue - John M. Ployee" -Body "I need a raise."
Sends an email with the indicated subject and body to the stated address.
.EXAMPLE
$messagebody = #"
Roses are red
Violets are blue
I need a raise
And so do you
"#
$others = "boss-of-boss#example.com","hr#example.com"
Send-Email -To "boss#example.com" -Subject "Personnel Issue - John M. Ployee" -cc $others -Body $messagebody
Sends an email with the indicated subject to the stated address. The body
will be composed of the lines in the variable $messagebody as shown; the
line breaks are preserved. A copy of the message is sent to the two addresses
listed in $others.
.EXAMPLE
Send-Email -To "boss#example.com" -Subject "Personnel Issue - John M. Ployee" -Body (Get-Content -Path "C:\Request-for-raise.txt")
Sends an email with the indicated subject and body to the stated address.
The body is drawn from the indicated file, and line breaks are preserved.
.EXAMPLE
Send-Email -To "boss#example.com" -Subject "Personnel Issue - John M. Ployee" -Body "Please see attached for rationale for raise" -Attachments (Get-Content -Path "C:\Request-for-raise.txt")
Sends an email with the indicated subject and body to the stated address.
The indicated file is included as an attachment.
.NOTES
Planned Future Enhancements:
1. Allow the cmdlet to accept input (message body text) from the pipe.
2. Allow the cmdlet to accept the body from a file (parameter -BodyFromFile)
3. Allow the cmdlet to start up Outlook if it is not already running.
This includes shutting it down afterward.
4. Allow the body to be formatted as HTML or RTF, and properly handle this.
Initially, switches (e.g., -BodyAsHTML or -BodyAsRTF); better would be to
use file name (e.g., -BodyFromFile "C:\Test.html" would still set the message
format to HTML even in the absence of -BodyAsHTML); best would be to inspect
content of file.
Based on a script from http://www.computerperformance.co.uk/powershell/powershell_function_send_email.htm
#>
[cmdletbinding()]
Param (
[Parameter(Mandatory=$True)]
[String[]]$To,
[String[]]$CC,
[String[]]$BCC,
[Parameter(Mandatory=$True)]
[String]$Subject,
[Parameter(Mandatory=$True)]
[String[]]$Body,
[String[]]$Attachments
)
Begin {
# Future Enhancement: Start Outlook if it's not already running
} # End of initialization
Process {
# Create an instance Microsoft Outlook
$Outlook = New-Object -ComObject Outlook.Application
# Create a new mail message
$Mail = $Outlook.CreateItem(0)
# Set up the email
$Mail.To = $To -join ";"
if ($CC -ne $null) {
$Mail.CC = $CC -join ";"
}
if ($bcc -ne $null) {
$Mail.BCC = $BCC -join ";"
}
$Mail.Subject = "$Subject"
$Mail.Body = $Body -join "`r`n"
if ($attachments -ne $null) {
foreach ($Attachment in $Attachments) {
$silencer = $Mail.Attachments.Add($Attachment)
}
}
# I need to investigate scripting Outlook more.
# The next three comments may be all that's needed
# to handle HTML and/or attachments.
# $Mail.HTMLBody = "When is swimming?"
# $File = "D:\CP\timetable.pdf"
# $Mail.Attachments.Add($File)
# Place message in outbox.
$Mail.Send()
} # End of Process section
End {
# Clean up after ourselves. This prevents Outlook from reporting
# an error on exit.
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook)
$Outlook = $null
# If Outlook settings are to Send/Receive only on command rather
# than as-needed, force the send at this time.
# NOTE TO SELF: CHECK THIS!
# $Outlook.GetNameSpace("MAPI").SendAndReceive(1)
# If we launched Outlook at the beginning, close it here.
# $Outlook.Quit()
} # End of End section!
} # End of function
<#
Note 2: Look in Outlook's outbox for a newly-created message.
Note 3: If you really want to send the email then append this command:
$Outlook.GetNameSpace("MAPI").SendAndReceive(1)
#>
How to accept confirmation Automatically in PowerShell for Outlook
I have script for Export attachments from email from Outlook - see next
It works correctly on one PC, but on another PC is there a problem:
Outlook gives message and wants answer:
Permit Denny Help
If I manually click on Permit or Denny it works correctly. I want to automate it.
Can you give me some suggestion how to do it in PowerShell?
I have tried to set Outlook to not give this message but I didn’t success.
My script:
# <-- Script --------->
# script works with outlook Inbox folder
# check if email have attachments with ".txt" and save those attachments to $filepath
# path for exported files - attachments
$filepath = "d:\Exported_files\"
# create object outlook
$o = New-Object -comobject outlook.application
$n = $o.GetNamespace("MAPI")
# $f - folder „dorucena posta“ 6 - Inbox
$f = $n.GetDefaultFolder(6) # 6 - Inbox
# select newest 10 emails, from it olny this one with attachments
$f.Items| select -last 10| Where {$_.Attachments}| foreach {
# process only unreaded mail
if($_.unread -eq $True) {
# processed mail set as read, not to process this mail again next day
$_.unread = $False
$SenderName = $_.SenderName
Write-Host "Email from: ", $SenderName
# process all attachments
$_.attachments|foreach {
$a = $_.filename
If ($a.Contains(".txt")) {
Write-Host $SenderName," ", $a
# copy *.txt attachments to folder $filepath
$_.saveasfile((Join-Path $filepath "$a"))
}
}
}
}
Write-Host "Finish"
# <------ End Script ---------------------------------->
I found that security prompt is generate on line
" $SenderName = $_.SenderName "
Realy I dont need to use SenderName and I deleted this line.
Now script works OK without any message.
I'm new at writing in powershell but this is what I'm trying to accomplish.
I want to compare the dates of the two excel files to determine if one is newer than the other.
I want to convert a file from csv to xls on a computer that doesn't have excel. Only if the statement above is true, the initial xls file was copied already.
I want to copy the newly converted xls file to another location
If the file is already open it will fail to copy so I want to send out an email alert on success or failure of this operation.
Here is the script that I'm having issues with. The error is "Expressions are only allowed as the first element of a pipeline." I know it's to do with the email operation but I'm at a loss as to how to write this out manually with all those variables included. There are probably more errors but I'm not seeing them now. Thanks for any help, I appreciate it!
$CSV = "C:filename.csv"
$LocalXLS = "C:\filename.xls"
$RemoteXLS = "D:\filename.xls"
$LocalDate = (Get-Item $LocalXLS).LASTWRITETIME
$RemoteDate = (Get-Item $RemoteXLS).LASTWRITETIME
$convert = "D:\CSV Converter\csvcnv.exe"
if ($LocalDate -eq $RemoteDate) {break}
else {
& $convert $CSV $LocalXLS
$FromAddress = "email#address.com"
$ToAddress = "email#address.com"
$MessageSubject = "vague subject"
$SendingServer = "mail.mail.com"
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, $MessageSubject, $MessageBody
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SendEmailSuccess = $MessageBody = "The copy completed successfully!" | New-Object System.Net.Mail.SMTPClient mail.mail.com $SMTPMessage
$RenamedXLS = {$_.BaseName+(Get-Date -f yyyy-MM-dd)+$_.Extension}
Rename-Item -path $RemoteXLS -newname $RenamedXLS -force -erroraction silentlycontinue
If (!$error)
{ $SendEmailSuccess | copy-item $LocalXLS -destination $RemoteXLS -force }
Else
{$MessageBody = "The copy failed, please make sure the file is closed." | $SMTPClient.Send($SMTPMessage)}
}
You get this error when you are trying to execute an independent block of code from within a pipeline chain.
Just as a different example, imagine this code using jQuery:
$("div").not(".main").console.log(this)
Each dot (.) will chain the array into the next function. In the above function this breaks with console because it's not meant to have any values piped in. If we want to break from our chaining to execute some code (perhaps on objects in the chain - we can do so with each like this:
$("div").not(".main").each(function() {console.log(this)})
The solution is powershell is identical. If you want to run a script against each item in your chain individually, you can use ForEach-Object or it's alias (%).
Imagine you have the following function in Powershell:
$settings | ?{$_.Key -eq 'Environment' } | $_.Value = "Prod"
The last line cannot be executed because it is a script, but we can fix that with ForEach like this:
$settings | ?{$_.Key -eq 'Environment' } | %{ $_.Value = "Prod" }
This error basically happens when you use an expression on the receiving side of the pipeline when it cannot receive the objects from the pipeline.
You would get the error if you do something like this:
$a="test" | $a
or even this:
"test" | $a
I don't know why are trying to pipe everywhere. I would recommend you to learn basics about Powershell pipelining. You are approaching it wrong. Also, I think you can refer to the link below to see how to send mail, should be straight forward without the complications that you have added with the pipes : http://www.searchmarked.com/windows/how-to-send-an-email-using-a-windows-powershell-script.php