Send mail when Outlook is not already open - vba

My situation:
I'm trying to send e-mails while Outlook is not open. This code will work if Outlook is running. If Outlook is closed the code will create a non-visible process that you can see running in Task Manager.
The code encounters an error during the .Send. It returns runtime error 287.
From my experience that are certain VBA methods that will only work when the object is either visible or active.
My work around is to use .Display(False) before calling .Send.
After calling .Send it immediately terminates the Outlook process. (Please point me to the right direction why.) Then the e-mail gets stuck in the Outbox.
I have to apply another work around by calling another CreateObject("Outlook.Application") and either looping through the Outbox While Outbox.Items.Count > 0
or
Looping through SyncObjects and manually calling .Start to run Send/Receive on the Outbox.
My question:
Is there a way to directly use the .Send method instead of using work arounds while also not having to open Outlook.
My code:
Sub emailer()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = "f#r.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = "Hi there"
.Send 'or use .Display
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

A workaround for the .send issue with Outlook closing can possibly be resolved by changing the settings for Send/Receive. Go to File -> Options -> Advanced -> find Send/Receive... and press it. Under "Setting for group "All Accounts" is a checkbox for Perform an automatic send/receive when exiting. Check this, and it may resolve the "stuck in the outbox issue you are having".
Here is a screenshot:
Give this a try, hopefully it helps.

Use Namespace.SendAndReceive. Keep in mind that Send/Receive is asynchronous and you need to wait to the sync to finish. You can use Namespace.SyncObjects collection, start a sync using SyncObject.Start, then wait for the SyncObject.SyncEnd event.
To prevent Outlook from closing, you need to keep a live reference to an Outlook Explorer or Inspector object. You can retrieve the Inbox folder using Namespace.GetDefaultFolder, then use MAPIFolder.GetExplorer method to get a pointer to an Explorer object.
UPDATE:
You might also want to make sure that you log to a MAPI profile before you create and send a message. After the CreateObject line, try to add the following
set NS = OutApp.GetNamespace("MAPI")
NS.Logon

Related

Reprocessing Outlook Undelivered Mail

I have an Exchange mailbox with a bunch of Outlook ReportItem Undelivered messages. I am attempting to reprocess the undelivered messages via an Outlook VBA script by invoking the "SendAgain" operation on the ReportItem messages. My issue is that the ReportItem does not have a send method, so I have no way of actually sending the reprocessed messages. I am using the following code to go through the messages:
Dim objApp As Outlook.Application
Dim objNameSpace As NameSpace
Dim journalAlertInbox As Folder
Dim objInspector As Inspector
Dim resendItem As ReportItem
Set objApp = CreateObject("Outlook.Application")
Set objNameSpace = objApp.GetNamespace("MAPI")
Set journalAlertInbox = objNameSpace.Stores.Item("thestore").GetDefaultFolder(olFolderInbox)
For Each folderItem In journalAlertInbox.Items
If TypeOf folderItem Is ReportItem Then
folderItem.Display
Set objInspector = folderItem.GetInspector
objInspector.CommandBars.ExecuteMso "SendAgain"
Set resendItem = Application.ActiveInspector.CurrentItem
Set objInspector = resendItem.GetInspector
''how do I send the item that is now displayed?
''resendItem.Close olSave
folderItem.Close olDiscard
End If
Next folderItem
I thought I might be able to save the displayed message as a draft, however If I uncomment the resendItem.close olSave line this results in a message in my Outlook Drafts folder of type ReportItem. I can open up the saved draft message it the Outlook GUI and click the send button, but I do not see a way to actually invoke the send operation programmatically. Examining the message in drafts shows it to be of type ReportItem, which does not have a .Send method.
How can I invoke the "Send" operation on the Report Item? I can clearly see the "Send" button, but there seems to be no programmatic way of actually clicking it.
OOM does not expose any functionality that allows to link a ReportItem object to the original MailItem, and, generally, there might not be any kind of link between the two. The best you can do is to retrieve PR_ORIGINAL_SEARCH_KEY MAPI property (or PR_REPORT_TAG, which includes both the search key and the store/Sent Items folder entry id) using ReportItem.PropertyAccess.GetProperty and try to find a matching message in the Sent Items folder. You can see these properties in OutlookSpy (I am its author).
Keep in mind that OOM does not allow to search on the binary (PT_BINARY) properties in Items.Find/Restrict.
If using Redemption is an option (I am also its author), it exposes RDOReportItem.FindOriginalItem method.
Once you have the original item, you can make a copy and try to send it again.
The ReportItem doesn't represent the original item which is failed to be sent. Also it doesn't contain any relationship with the original mail item, so you will not find any property or method available in the Outlook object model. Your existing solution looks good.
You may also try using the ReportItem.GetConversation method which obtains a Conversation object that represents the conversation to which this item belongs. So, you may try getting the previous item from the conversation, it could be the original item which has been submitted.

Send email reminder when task occurs

This code works with Outlook's Task system. I created a task that reoccurs every week on Wednesday. When the task occurs the code is suppose to send an email to "test#work.com" (not the real test email).
I have written the code in the Outlook VBA developer window.
Am I missing a step to get the code to run? The code logic is posted below.
Sub Application_Reminder(ByVal Item As Object)
Dim objPeriodicalMail As MailItem
If Item.Class = olTask Then
If InStr(LCase(Item.Subject), "Send PM Work Order Request Reminder Email") Then
Set objPeriodicalMail = Outlook.Application.CreateItem(olMailItem)
With objPeriodicalMail
.Subject = "REMINDER-Get Work Order Request Submitted"
.To = "Test#work.com"
.HTMLBody = "<HTML><BODY>Hello All Pm's, Please Submit your Work order request by 9:00A.M.</HTML></BODY>"
.Attachments.Add
.Importance = olImportanceHigh
.ReadReceiptRequested = True
.Send
End With
End If
End If
End Sub
To control Outlook objects from outside Outlook, you must establish a reference to the Outlook object library from the project in which you are writing code. To do this, use the References dialog box in the Visual Basic Editor in the primary application. You can then write code that returns a reference to the Outlook Application object. Through this reference, your code has access to all the objects, properties, methods, and constants defined in the Outlook type library.
Read more about that in the Automating Outlook from a Visual Basic Application article.
To set up events you need to define the source object withevents or select in the drop-down list on VBA editor and select the required event. See Using Outlook Visual Basic for Applications to Respond to Outlook Events.

Draft email created by VBA code returns undeliverable error

I create an email draft using the following VBA Code in Excel (2014):
Sub Send_email()
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
Dim OutMail As Object
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = "myself#hotmail.com"
.Subject = "test email"
.HTMLBody = "Sample test body"
.Save
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
If I open the saved email and send it manually, I receive an Undeliverable error message from System Administrator:
"Your message did not reach some or all of the intended recipients."
If I use:
.Send
instead of
.Save
The email is sent (with no Undeliverable error).
Hopefully this will help. I was able to resolve the issue for myself by adding a call to OutMail.Recipients.ResolveAll().
VB.NET
Call OutMail.Recipients.ResolveAll
This solved the issue for me. However, if you have a version of Outlook that does not support antivirus detection, you may get a message box prompting you that an external app is trying to access email addresses or something similar to this:
a program is trying to access e-mail address information ...
If you get this, Google the phrase above to find many articles on how to resolve. It has to do with trust settings in Outlook.
i run you code AS IS from within excel, and it's working well.
When i open outlook i found the draft , flagged "the message has not been sent".
The email is saved in Drafts Folder of my Outlook, and i can view it in outlook.
I opened the draft email and sent it by pressing the sent button , and it is sent successfully.
i can't guess the problem , for i didn't find it :).
Review the setting of your email in outlook, you may find something.

Outlook code is working when manually called but giving trouble from Application_ItemSend

I have a code that checks the recipient of the mail, looks what organization is set in the address book for the recipient and dependent on that sets the "SentOnBehalfOfName"-property of the item. If the recipient is working for client2, he will get the mail from "we_love_to_serve_client2#domain.com".
I call the code either before sending the mail via a button in my ribbon, that calls this Sub:
Sub Signatur()
Dim olApp As Outlook.Application
Dim objMail As Outlook.MailItem
Set olApp = Outlook.Application
Set objMail = Application.ActiveInspector.CurrentItem
Call Signatur_auto(objMail)
End Sub
I do this if I want to know which mail-adress is going to be chosen.
In the itemSend-section of thisOutlookSession I also call the same sub
Call Signatur_auto(Item)
Part of the Signatur_auto (i do not copy that in, the question is too long already...) is dealing with the SentOnBehalfOfName-property, the other part is putting the item into the right folder. The Folder is chosen depending on the SentOnBehalfOfName-property.
Now comes the interesting part: Although the folder-part is always working (which can only be when the SentOnBehalfOfName has worked before), the SentOnBehalfOfName only works "half". In the preview-line the mail sent is shown as from "we_serve_client2#domain.com", but when I open the mail it says it was sent by me. The Client always only sees my address, and also answers to my address - which I do not want....
How cant be, that the same code is having different results dependent on where it is called? Is it a Problem to change the sendonbehalf-field in the item send-section?
Thanks for any Inputs!
Max
Why it does not work?
Try this in ItemSend.
Dim copiedItem As mailItem
Set copiedItem = Item.Copy
copiedItem.SentOnBehalfOfName = "we_love_to_serve_client2#domain.com"
copiedItem.Send
Item.delete
Cancel = True ' In case your setup generates an error message as described in the comments
Why it works? Appears "copiedItem.Send" bypasses ItemSend.

VB.net 2005 Sending Emails With Outlook 2003

We currently use the following code to create an email in Outlook so that the user can type what they want in Outlook, then when the email is sent, the system prompts them to see if they would like to save the email.
Dim objOutlook As Object
Dim objMessage As Object
Dim objInspector As Object
If strEMail <> "" Then
objOutlook = CreateObject("Outlook.Application")
objMessage = objOutlook.CreateItem(0)
objMessage.To = strEMail
objInspector = objMessage.GetInspector
objInspector.Display()
While Not objInspector.CurrentItem Is Nothing
End While
frmSaveSentEmail.BringToFront()
frmSaveSentEmail.ShowDialog()
The code works fine on Outlook 2003 as long as they are not using Word as their email editor. However, with Word set up as the email editor, the while loop that tests to see if the email object is closed never ends.
Is there a way to handle this differently so that it will work even with Word as the editor?
I am not terribly experienced with programming Outlook via VB.NET, but that loop certainly looks suspicious. Perhaps you should try taking advantage of the inspector's Close event instead of repeatedly checking its CurrentItem property. If I am not mistaken, you should be able to present your dialog within the event handler.
Ended up changing the loop to:
While Not objOutlook.ActiveInspector Is Nothing
End While
This resolved the issue.