Using multiple attachments through comObject Outlook.Application - email

I have a script that goes into SCSM, gets the relevant files from the IR and downloads them properly onto the user's computer.
Next, I need the script to create an email from the client's outlook application and display it on their screen before sending the email..
Here is the part of the script that does that:
$GetFiles = Get-ChildItem "$ArchiveRootPath\$IRID\"
$ol = New-Object -comObject Outlook.Application #| New-Object Net.Mail.MailMessage
$mail = $ol.CreateItem(0)
$mail.To = "johndoe#contoso.com"
$mail.Subject = "This is a test [$IRID]"
Foreach($GetFile in $GetFiles)
{
Write-Host “Attaching File :- ” $GetFile
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList C:\Temp\SCSM_Archive\$IRID\$GetFile
$mail.Attachments.Add($attachment)
}
$inspector = $mail.GetInspector
$inspector.Display()
However, when I run the script, I get this error:
Attaching File :- email.eml
Exception calling "Add" with "1" argument(s): "Value does not fall within the expected range."
At C:\Temp\SSWireless Script.ps1:99 char:2
+ $mail.Attachments.Add($attachment)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
All the variables are checked from the previous part of the script that downloads the files. PS is able to see the files, but cannot attach them to the email.
I don't want to use the send-message function due to the fact that we will be moving to a cross domain email account and would rather use outlook to create the email itself.

Here is a reference for Microsoft.Office.Interop.Outlook Attachments.Add method . This confirms that the first parameter (and the only parameter in your case) needs to be a full path to file.
There is no point passing [System.Net.Mail.Attachment] .NET objects to COM interface.
Your code should look something like this:
$GetFiles = Get-ChildItem "$ArchiveRootPath\$IRID\"
$ol = New-Object -comObject Outlook.Application
$mail = $ol.CreateItem(0)
$mail.To = "johndoe#contoso.com"
$mail.Subject = "This is a test [$IRID]"
Foreach($GetFile in $GetFiles)
{
Write-Host “Attaching File :- $GetFile.Name"
$mail.Attachments.Add($GetFile.FullName)
}

Related

Reply to an outlook mail using powershell

I am trying to automate some replies to email that I get on my outlook. I have tried sending mail from my outlook (normal mail) using powershell and it worked successfully. Now I am trying to reply on mail using powershell. This is my current code as of now:
$o = New-Object -com Outlook.Application
$all_mail = $o.Session.Folders.Item($myEmailId).Folders.Item("Inbox").Items
foreach ($mail in $all_mail) {
if ($mail.subject -match "Re: Testing") {
$reply = $mail.reply()
$reply.body = $reply.body + "Adding this extra info in mail."
$reply.send()
}
}
#myEmailId is my emailId, if trying this script, replace it with yours.
When I run this, I am getting the following error
Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
At line:7 char:13
+ $reply.send()
+ ~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
I have printed the logs in between while debugging and found that it is successfully picking up all the emails in my outlook. The if condition where it matches the mail subject is also working fine. I tried going through various resource on internet but could not find any resolution for this. Any help or direction will be really helpful.
Helping myself with the Microsoft Dev Blog :
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
Add-type -assembly "System.Runtime.Interopservices"
try
{
$outlook = [Runtime.Interopservices.Marshal]::GetActiveObject('Outlook.Application')
$outlookWasAlreadyRunning = $true
}
catch
{
try
{
$Outlook = New-Object -comobject Outlook.Application
$outlookWasAlreadyRunning = $false
}
catch
{
write-host "You must exit Outlook first."
exit
}
}
$namespace = $Outlook.GetNameSpace("MAPI")
$inbox = $namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderInbox)
$mails = $inbox.Items | Where-Object {$_.Subject -like "ABC TEST*"}
foreach($mail in $mails) {
$reply = $mail.reply()
$reply.body = "TEST BODY"
$reply.send()
while(($namespace.GetDefaultFolder([Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderOutbox)).Items.Count -ne 0) {
Start-Sleep 1
}
}
# Kill Process Outlook (close COM)
Get-Process "*outlook*" | Stop-Process –force
The while loop on the Items.Count is used to check if the OutBox is empty or not. If you close the Outlook Process before it's done, your mail won't be sent.

Powershell Send .csv files in a folder using Gmail

I realize this question has been asked before, but I have not been able to find a solution using the related questions.
I am trying to send two .csv files using Powershell to a gmail account (externalexample#gmail.com), using credentials from another gmail account(senderexample#gmail.com). I have turned on the Less Secure Apps feature for both accounts, but am getting the following error when trying to run my script:
> Exception calling "Send" with "1" argument(s): "The SMTP server
> requires a secure connection or the client was not authenticated. The
> server response was: 5.7.0 Authentication Required. Learn more at" At
> C:\users\luke\downloads\EmailTest.ps1:37 char:1
> + $smtp.Send($msg)
> + CategoryInfo: NotSpecified: (:) [], MethodInvocationException
> + FullyQualifiedErrorId : SmtpException
My script:
#Connection Details
$username="senderexample#gmail.com"
$password="senderpassword"
$smtpServer = “smtp.gmail.com”
$msg = new-object Net.Mail.MailMessage
#Change port number for SSL to 587
$smtp = New-Object Net.Mail.SmtpClient($smtpServer, 587)
#Uncomment Next line for SSL
$smtp.EnableSsl = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($username, $password)
#From Address
$msg.From = "senderexample#gmail.com"
#To Address, Copy the below line for multiple recipients
$msg.To.Add(“externalexample#gmail.com”)
#Message Body
$msg.Body=”Please See Attached Files”
#Message Subject
$msg.Subject = “Email with Multiple Attachments”
#your file location
$files=Get-ChildItem “C:\Users\luke\Daily Stats\”
Foreach($file in $files)
{
Write-Host “Attaching File :- ” $file
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList $file.FullName
$msg.Attachments.Add($attachment)
}
$smtp.Send($msg)
$attachment.Dispose();
$msg.Dispose();
All help is greatly appreciated!

Powershell Grab 2 files and email them to a group of people

I am trying to figure out how I can schedule a task to run once a week with task scheduler to copy two files and attach them to an email and email them to a group of people. Is this possible to do? To have a script that will run using power shell grab two files from certain locations and then email them? Would it be similar to what I have below or am I going in the wrong direction?
$ol = New-Object -comObject Outlook.Application
$message = $ol.CreateItem(0)
$message.Recipients.Add("Deployment")
$message.Subject = "Website deployment"
$message.Body = "See attached file"
$file = "K:\Deploy-log.csv, K:\Deploy-log2.csv"
$message.Attachments.Add($file)
Error
Exception calling "Add" with "1" argument(s): "File name or directory
name is not valid." At C:\Users\davidb\Desktop\email.ps1:8 char:1
+ $message.Attachments.Add($file)
FullyQualifiedErrorId : ComMethodTargetInvocation
If I take , K:\Deploy-log2.csv off it will not error but I still do not receive the email either
In your code, $file is one string which when interpreted as just one path isn't valid. What you are intending is an array of strings, each element of the array is a string with one path. You could loop over the array with either a foreach or a ForEach-Object loop, using the Add() once on each separate path. Would look like this:
$ol = New-Object -comObject Outlook.Application
$message = $ol.CreateItem(0)
$message.Recipients.Add("Deployment")
$message.Subject = "Website deployment"
$message.Body = "See attached file"
$files = "K:\Deploy-log.csv","K:\Deploy-log2.csv"
foreach ($file in $files) {
$message.Attachments.Add($file)
}
$message.Send()
Alternatively, you could use the Send-MailMessage cmdlet
Send-MailMessage -From 'Sender <Sender#example.com>' -To "Recipient <Recipient#example.com>" -Subject "Website deployment" -Body "See attached file" -Attachments #("K:\Deploy-log.csv", "K:\Deploy-log2.csv") -SmtpServer smtp.example.com

Unable to Send Outlook Email via Powershell

I can create an email and display it with my script, but for some reason it doesn't send and I receive the following error. Am I missing something, maybe there's a permissions issue?
Exception calling "Send" with "0" argument(s): "Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))"At C:\TEMP\Scripts\PowerShell\Outlook EMail Creation\TestEMailSend.ps1:27 char:5
+ $mail.Send()
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
My code:
$global:UserReportsToEmail = "my.email#domain.com"
$ol = New-Object -comObject Outlook.Application
$mail = $ol.CreateItem(0)
$mail.To = "$global:UserReportsToEmail"
$mail.cc = "EMAIL#domain.com"
$mail.Subject = "mySubject"
$mail.HTMLBody =
"<font color ='blue'><b>TESTING STUFFFF!</b></font><br>
Text on a new line $UserID"
$mail.Send()
$inspector = $mail.GetInspector
$inspector.Display()
According to a few of the Microsoft sites (e.g. https://social.msdn.microsoft.com/Forums/en-US/80c66a08-66ee-4ab6-b629-6b1e70143eb0/operation-aborted-exception-from-hresult-0x80004004-eabort-outlook-appointment?forum=outlookdev ) this is due to 'object model guard'. A security feature to prevent automated programs from doing stuff like auto-emailing out viruses and stuff from the background.
You probably already worked this out. Posting this here so that others like myself can more quickly and easily understand why its not working.
you can use the Send-MailMessage CmdLets : https://technet.microsoft.com/en-us/library/hh849925.aspx
then when i need more controls and dispose functionnality i use System.Net.Mail.SmtpClient
try
{
$emailCredentials = Import-Clixml "C:\testMail\credentials.clixml"
$recipients = #("user#mail.com", "user2#mail.com", "user3#mail.com")
$attachments = #("C:\testMail\file.txt", ""C:\testMail\file2.txt", "C:\testMail\file3.txt")
# create mail and server objects
$message = New-Object -TypeName System.Net.Mail.MailMessage
$smtp = New-Object -TypeName System.Net.Mail.SmtpClient($buildInfoData.BuildReports.Mail.Server)
# build message
$recipients | % { $message.To.Add($_) }
$message.Subject = $subject
$message.From = New-Object System.Net.Mail.MailAddress($emailCredentials.UserName)
$message.Body = $mailHtml
$message.IsBodyHtml = $true
$attachments | % { $message.Attachments.Add($(New-Object System.Net.Mail.Attachment $_)) }
# build SMTP server
$smtp = New-Object -TypeName System.Net.Mail.SmtpClient(smtp.googlemail.com)
$smtp.Port = 572
$smtp.Credentials = [System.Net.ICredentialsByHost]$emailCredentials
$smtp.EnableSsl = $true
# send message
$smtp.Send($message)
Write-Host "Email message sent"
}
catch
{
Write-Warning "$($_.Exception | Select Message, Source, ErrorCode, InnerException, StackTrace | Format-List | Out-String)"
}
finally
{
Write-Verbose "Disposing Smtp Object"
$message.Dispose()
$smtp.Dispose()
}

powershell outlook automation namespace

I'm working with automating the opening of a public folder by EntryID from IE with javascript and activex and ran across some errors. To debug I've re-wrote it as a power shell script.
$eid = "HEX EntryID FOR PUBLIC FOLDER";
$o = new-object -com outlook.application;
$ns = $o.GetNamespace("MAPI");
#$ns #if this line is commented, error
$f = $ns.GetFolderFromID($eid)
$f.Display();
If I shut outlook down completely, and then run the script I get the following error
Exception calling "GetFolderFromID" with "2" argument(s): "The messaging interface has returned an unknown error. If the problem persists, restart Outlook."
At G:\scripts\outlook.ps1:5 char:25
+ $f = $ns.GetFolderFromID <<<< ($eid)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
If I uncomment the $ns line, everything works fine, even if its removed again. That is, until I close out of Outlook completely, almost as if the $ns com object isn't being truly initialized until I output it to the console.
I'd like to know:
why calling $ns fixes the problem
why powershell thinks I'm passing 2 arguments
is there a way to implement this workaround
in javascript
The GetFolderFromID() requires two arguments: EntryID and StoreID of folder wanted.
This code gives no error and show outlook with PublicFolder selected:
$o = new-object -com outlook.application;
$ns = $o.GetNamespace("MAPI");
$cp = $ns.Folders # FolderClass ComObject containing all Outlook folders, usually first is the PublicFolder
$f = $ns.GetFolderFromID( $cp.GetFirst().EntryID ,$cp.GetFirst().StoreID )
$f.Display();
Using your code I can't do it, $ns line commented or not.
You can get the public folders store programatically:
$ol = New-Object -ComObject Outlook.Application
$pf = $ol.GetNamespace("MAPI").Folders | Where-Object {$_.FolderPath -like "\\Public Folders*"}
$pf.Display()