Home > Mobile >  VB.NET Outlook.items.itemadd event not firing. Trying to wait until an email is sent before executin
VB.NET Outlook.items.itemadd event not firing. Trying to wait until an email is sent before executin

Time:04-18

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.

  • Related