The problem
For the application I'm creating, the goal is to programmatically create an email (with the recipient, subject and body written), attach a file, send the email; then, finally, delete the file from the hard drive.
The problem I have is that I need the program to wait for the email to finish sending before it deletes the temporary attached file.
Sending the email isn't a problem, and I've read in my research into this problem that I should use the Items.AddItem event on the Sent Mail folder. This makes sense to me. Having the program delete the temp file when the AddItem event fires so it's waiting for the Sent Mail folder to have the mail item added to it sounds wonderful, but I can't get it to fire.
I used this MS Docs site as a reference: https://docs.microsoft.com/en-us/office/vba/api/outlook.items.itemadd
I added the following references:
- Microsoft Scripting Runtime
- Microsoft Outlook 16.0 Object Library
Here's my code:
Imports Microsoft.Office.Interop
Imports Scripting
Imports System.Environment
Public Class Form
Public WithEvents myOlItems As Outlook.Items
Public olApp As Outlook.Application
Public testfso As FileSystemObject
Public testfilepath As String
Public Sub Initialize_handler()
olApp = New Outlook.Application 'initialise outlook app
myOlItems = olApp.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail).Items 'set sent folder variable for itemsadd event.
End Sub
Private Sub myOlItems_ItemAdd() Handles myOlItems.ItemAdd
'This event should fire when the Sent Mail folder has an item added to it.
MsgBox("Email sent.", vbOKOnly vbApplicationModal vbMsgBoxSetForeground, "Success")
olApp.Quit() 'close outlook app.
testfso.DeleteFile(testfilepath) 'delete temp test file.
Application.Exit()
End Sub
Public Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
testfilepath = GetFolderPath(SpecialFolder.Desktop) & "\temp.txt" 'File path for test temp file
testfso = New FileSystemObject
Dim file As TextStream = testfso.CreateTextFile(testfilepath, True) 'create test file.
With file
.Write("Some text here.")
.Close()
End With
Call Initialize_handler() 'set the folder to "watch" with the itemsadd event.
Dim eMail As Outlook.MailItem = olApp.CreateItem(Outlook.OlItemType.olMailItem) 'create email item.
With eMail
.Display() 'Show email (needs to be done now b/c the HTMLBody property is set to the email signature when the email is displayed with this method)
.To = "[email protected]" 'set recipient.
.Subject = "Test Email" 'set email subject.
.HTMLBody = "Testing testing 123" & .HTMLBody 'add detail to start of email body.
.Attachments.Add(testfilepath, Outlook.OlAttachmentType.olByValue, 1) 'attach link file.
.Send() 'Sent Folder ItemsAdd event should fire now.
End With
End Sub
End Class
What happens
When I step through this code, it runs every line except when I get to the MailItem.send method, the AddItem event procedure doesn't fire and it simply continues to the end of the Form_Load sub.
Other things I've tried
I tried myOlItems = olApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail).Items
instead of myOlItems = olApp.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail).Items
in the Initialize_handler sub, to no effect.
I also noticed that the MailItem unloads after it's sent so I tried a loop to have the program wait until the MailItem Is Nothing, but it simply hangs as if the MailItem doesn't actually become nothing.
Can anyone help with this please?
CodePudding user response:
Keep in mind that Items.ItemAdd
on the Sent Items folder will fire only after the message is actually sent, which might not happen for a long time.
You can also try to call Namespace.SendAndReceive
after calling Send
.
CodePudding user response:
First of all, calling Send
doesn't guarantee that your mail item will be sent immediately. The method saves all of the message's properties and marks the message as ready to be sent. Outlook passes messages to the underlying messaging system in the order in which they are marked for sending. Because of this functionality, a message might stay in a message store for some time before the underlying messaging system can take responsibility for it. The order of receipt at the destination is in the underlying messaging system's control and does not necessarily match the order in which messages were sent.
The SyncObject represents a Send\Receive
group for a user and lets users configure different synchronization scenarios, selecting which folders and which filters apply. For example, the Start
method begins synchronizing a user's folders using the specified Send\Receive group:
Public Sub Sync()
Dim nsp As Outlook.NameSpace
Dim sycs As Outlook.SyncObjects
Dim syc As Outlook.SyncObject
Dim i As Integer
Dim strPrompt As Integer
Set nsp = Application.GetNamespace("MAPI")
Set sycs = nsp.SyncObjects
For i = 1 To sycs.Count
Set syc = sycs.Item(i)
strPrompt = MsgBox( _
"Do you wish to synchronize " & syc.Name &"?", vbYesNo)
If strPrompt = vbYes Then
syc.Start
End If
Next
End Sub
There is an alternative method which Dmitry mentioned - the NameSpace.SendAndReceive method which initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile. So, to avoid synchronizing all accounts in Outlok which can take some time I'd suggest using the SyncObject's Start
method described above.
Finally, be aware the message may not be put to the Sent Items
folder at all, so you may not get the ItemAdd
event fired all. The MailItem.SaveSentMessageFolder property returns or sets a Folder
object that represents the folder in which a copy of the email message will be saved after being sent. So, it makes sense to check this value in the ItemSend
event handler whether any add-in sets this on outgoing mails.
Another property which can play a vital role there is the MailItem.DeleteAfterSubmit property which returns or sets a Boolean
value that is True
if a copy of the mail message is not saved upon being sent, and False
if a copy is saved in Sent Items
folder.
If you live in ideal and isolated world (without any add-ins) you may not care about these two properties, but if you need to deploy your solution widely it makes sense to pay attention to such facts as well.