How do I use ItemAdd on the Sent Items folder? - vba

This question looks like it should have been answered here:
Outlook VBA Save Copy Sent Item
I am unable to find the referenced "Items.ItemAdd" event amongst the list of events in the VB Editor for Outlook 2016.
Application.ItemSend is located in "ThisOutLookSession". The script I came up with looks 90% similar to the one posted in the original question and I have the same problem. The mail item is saved in it's pre-send condition.
I can't use "MailItem.SaveSentMessageFolder" as I am trying to move the sent mail to a PST.
The Event is explained here:
https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/items-itemadd-event-outlook
In case someone asks "Why not use the AutoArchive Function?", my organization has some terrible group policies set up for both Sent Items and AutoArchive. I can't wade through the mess to get AutoArchive for sent items set up.

Work with Items.ItemAdd Event (Outlook)
Example
Option Explicit
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderSentMail)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.mailitem Then
' code to copy the sent Item here
End If
End Sub

Related

How to convert inbox ItemAdd to run on a subfolder? [duplicate]

This question already has answers here:
Using visual basic to access subfolder in Inbox?
(3 answers)
Closed 1 year ago.
My code isn't working because emails are being forwarded to subfolders with a rule.
I cannot remove this rule nor make any rules on this computer.
I realized that newMailEx is probably the answer to my problems. Would there be a way to convert my code to run off of that instead of item_add?
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Items = objNS.Folders.Item("Data").Folders.Item("Inbox").Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
Dim Msg As Outlook.MailItem
If TypeOf Item Is Outlook.MailItem Then
'''code to check subject lines and do various things to attachments for the various cases
End If
End Sub
If you are creating a VBA macro in Outlook you need to choose the Application in the left drop-down menu and choose the NewMailEx event to generate the event handler in the editor.
After choosing the NewMailEx entry from the drop-down list you will get the following where you can add your code:
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
End Sub
So, in the event handler you may use the `` method in the following way:
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
Dim mail as Outlook.MailItem
Set mail = Application.Session.GetItemFromID(strEntryId)
MsgBox mai.Subject
End Sub
Please remember that different kind of items can be passed to the event handler. For example, it can be an appointment item (meeting request). You need to check its message class before casting to the MailItem class to make sure you deal with mail items. Otherwise, an exception could be thrown if non-existing method or property is called.

How to execute a code after mail has been sent?

I'm trying to record a specific next-numbering on certain e-mails after I send them. However Application_ItemSend executes the code before it sends the e-mail.
I'm adding a reference number to the Subject, but I don't want to confuse everyone with random numbers appearing in their inbox.
Is there a way to execute code after the send?
I think I got it:
Declare a new type of events-related variable to ensure every time an e-mail is added to the "Received Items" folder an action is executed.
Private WithEvents Rcvditems As Outlook.Items
The method I used to avoid variables being restored to 'nothing' is using the same Application.Item_Send event. This option will ensure I activate my reader every time I send an e-mail.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Rcvditems = objNS.GetDefaultFolder(olFolderSentMail).Items
End Sub
... what it is doing is recalculating my variable 'Rcvditems'.
Finally, as Rcvd_Items is an event-related variable, I can assign event 'AddItem' to it.
Private Sub Rcvditems_ItemAdd(ByVal Item As Object)
On Error GoTo EscapeSub
Call MyMacro(Item)
EscapeSub:
End Sub
Like this I'm ensuring that I won't alter the e-mail when prior sending it, but just the e-mail that is added in the Received-Items folder.
By default, the sent items are placed to the Sent Items folder in Outlook. If so, you can hook to the ItemAdd event of the Items class which belongs to the Sent Items folder. It is fired when one or more items are added to the specified collection. This event does not run when a large number of items are added to the folder at once (more than sixteen) - this is a known issue in OOM and exists in all Outlook versions.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentItems).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
MsgBox Item.Subject
End Sub
Note, the MailItem.SaveSentMessageFolder property allows to set a Folder object that represents the folder in which a copy of the email message will be saved after being sent. So, it is not necessary that an Outlook item will be saved to the Sent Items folder if an add-in sets this property in the ItemSend event handler.

Trigger a macro after a new mail is received

I have a macro that prompts you to save an email to a specified folder before you send it, but I can't get the macro to work for receiving emails.
This is what I have for sending emails:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem Then
Cancel = Not SaveSentMail(Item)
End If
End Sub
Private Function SaveSentMail(Item As Outlook.MailItem) As Boolean
Dim F As Outlook.MAPIFolder
If Item.DeleteAfterSubmit = False Then
Set F = Application.Session.PickFolder
If Not F Is Nothing Then
Set Item.SaveSentMessageFolder = F
SaveSentMail = True
End If
End If
End Function
Work with Application.Startup Event (Outlook) and Items.ItemAdd Event (Outlook)
Items.ItemAdd Event (Outlook) Occurs when one or more items are added to the specified collection. This event does not run when a large number of items are added to the folder at once. This event is not available in Microsoft Visual Basic Scripting Edition (VBScript).
Application.Startup Event (Outlook) Occurs when Microsoft Outlook is starting, but after all add-in programs have been loaded.
Code Example
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
Dim Folder As Outlook.MAPIFolder
If TypeOf Item Is Outlook.mailitem Then
Set Folder = Application.Session.PickFolder
If Folder Is Nothing Then Exit Sub
Item.Move Folder
End If
End Sub
You can handle the NewMailEx event of the Application class which is fired when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item. Use this method with caution to minimize the impact on Outlook performance.
Be aware, for users with an Exchange Server account (non-Cached Exchange Mode or Cached Exchange Mode), the event will fire only for messages that arrive at the server after Outlook has started. The event will not fire for messages that are synchronized in Cached Exchange Mode immediately after Outlook starts, nor for messages that are already on the server when Outlook starts in non-Cached Exchange Mode.
Another possible option is to handle the ItemAdd event of the Items class which is fired when one or more items are added to the specified collection. Be aware, this event does not run when a large number of items are added to the folder at once (more than 16 - this is a well-known issue in OOM).
A better solution is to check for new items in the folder using the timer's event. Read more about possible solutions in the following articles:
Outlook NewMail event unleashed: the challenge (NewMail, NewMailEx, ItemAdd)
Outlook NewMail event: solution options
Outlook NewMail event and Extended MAPI: C# example
Outlook NewMail unleashed: writing a working solution (C# example)

How can I trigger an event when multiple items added at once to Outlook Folder?

I use event handlers in VBA and Outlook frequently. One of them is one which marks any item which is deleted to be marked as read.
Private Sub deletedItems_ItemAdd(ByVal Item As Object)
Application_Startup
On Error Resume Next
Item.UnRead = False
End Sub
Declared via:
Private WithEvents deletedItems As Outlook.Items
and initialized in Application_Startup as:
Dim olNameSpace As Outlook.NameSpace
Set olNameSpace = olApp.GetNamespace("MAPI")
Set deletedItems = olNameSpace.GetDefaultFolder(olFolderDeletedItems).Items
Unfortunately, this does not affect all the items if I delete multiple items at once.
Is there a way I can do something to hijack this process somehow? I looked into using the _beforeDelete event but you have to set the item correctly each time, which if I could do this problem wouldn't exist anyways.
Apparently I wasn't clear - the use case I have is when I delete messages via the delete key from my inbox, drafts, whatever.
You don't have to.
I was curious about your question so I opened up Outlook and wrote this code in ThisOutlookSession:
Private WithEvents items As Outlook.items
Public Sub SetItems()
Set items = Application.GetNamespace("MAPI") _
.GetDefaultFolder(olFolderDeletedItems) _
.items
End Sub
Private Sub items_ItemAdd(ByVal Item As Object)
Dim mail As MailItem
On Error Resume Next
Set mail = Item
Err.Clear
On Error GoTo 0
If Not mail Is Nothing Then
MsgBox mail.Subject
mail.UnRead = False
End If
End Sub
Then I ran SetItems from the immediate pane, went to my inbox and deleted a SMS message - as expected mail was Nothing. Then I deleted a single email, and got the message with the mail's subject.
When I selected two emails and hit Delete, the event was fired once for each selected email, so I saw two message boxes - it just works! :)
The Outlook API doesn't seem to offer an event which would handle all deletions at once.
i have (almost) exactly the same code and it works also for multiple items - only after sleep-mode Outlook seems to forget how to handle deleted items...
Option Explicit
Public WithEvents itDeleted As items
Private Sub Application_Startup()
Set itDeleted = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderDeletedItems).items
End Sub
Private Sub itDeleted_ItemAdd(ByVal Item As Object)
'MsgBox "deleted-sub fired" 'this only for test-purposes
If TypeOf Item Is MailItem Then
Item.UnRead = False
End If
End Sub
I think the difference in the definition of "deletedItems" is the problem; that you are not checking the mailitem-property is also not optimal.
Hope this helps,
Max

Trigger VBA code to run after a new mail is received in Outlook? [duplicate]

This question already has answers here:
How do I trigger a macro to run after a new mail is received in Outlook?
(2 answers)
Closed 5 years ago.
Win 7, Outlook 2013 I use VBA code that takes an action on some of the files that arrive in my inbox. However, I have to click/run button to run this macro.
Is there a way that this code could run automatically when an email arrives?
I have tried an Outlook rule to run the script but not successful.
I tried this, but this works only when once I run the macro
Private Sub Application_NewMail()
Call GetAttachments_From_Inbox (My Macro)
End Sub
I specifically use a script I run as a rule, applied to all messages. This gives you easy and clear access to the mail item you receive. Since you want to run this on each message setting up WithEvents on your inbox is probably your best bet.
For example:
You can create a listeners for an Outlook folder as follows:
Private WithEvents mainInboxItems As Outlook.Items
Public Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set mainInboxItems = objNS.Folders("whatever your main mailbox is called").Folders("AssignNumber").Items
'assumes your "AssignNumber" folder is a subfolder of the main inbox
'otherwise you can nest Folders("myArchive").Folders("AssignNumber).items etc
End Sub
You can do this for as many folders as you want, too.
You can then assign the ItemAdd method to each of them like:
Private Sub mainInboxItems_ItemAdd(ByVal item As Object)
'do Stuff to mailitem
Call GetAttachments_From_Inbox (item)
End Sub
All this code can go in ThisOutlookSession.