Outlook VBA move mail in subfolder which hods mail of same subject - vba

I'd like to do the following:
On the event of receiving a new mail the subject of the mail should be checked and if the same subject exists already in any subfolder the mail shall be moved to that same subfolder. In case the same mail can't be found it shall remain in the normal inbox folder.
The target folder as such has no logical connection to the mail, so it is not called like the mail or the mail sender or something like that. It is only the folder which holds one or mails with the same subject.
I managed - by browsing through this forum - to identify the event, the subject of the mail and to perform the actual move.
What I did not manage is:
1. to create a search logic to find already existing mails with the same subject in any folder
2.to return the found folder to use it as the target destination.
This is how it looks up till now and it manages to show a message...
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.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim MoveToFolder As Outlook.MAPIFolder
If TypeName(Item) = "MailItem" Then
Set Msg = Item
MsgBox "Here the folder must be found for '" & Msg.Subject & "'."
'Msg.Move MoveToFolder
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
On top: Is there a specific smart way to do the same on other events like for example "SentMails"?
Thanks a lot for any support.
Ralf

You can use the AdvancedSearch method of the Application class which performs a search based on a specified DAV Searching and Locating (DASL) search string. You can read more about that method in the Advanced search in Outlook programmatically: C#, VB.NET article. So, you can find items with the same subject and then get their Parent property value which stands for the folder where they are stored.
Public blnSearchComp As Boolean
Private Sub Application_AdvancedSearchComplete(ByVal SearchObject As Search)
Debug.Print "The AdvancedSearchComplete Event fired"
If SearchObject.Tag = "Test" Then
m_SearchComplete = True
End If
End Sub
Sub TestAdvancedSearchComplete()
Dim sch As Outlook.Search
Dim rsts As Outlook.Results
Dim i As Integer
blnSearchComp = False
Const strF As String = "urn:schemas:mailheader:subject = 'Test'"
Const strS As String = "Inbox"
Set sch = Application.AdvancedSearch(strS, strF, “Test”)
While blnSearchComp = False
DoEvents
Wend
Set rsts = sch.Results
For i = 1 To rsts.Count
Debug.Print rsts.Item(i).SenderName
Next
End Sub
Is there a specific smart way to do the same on other events like for example "SentMails"?
You may consider handling the ItemSend event of the Application class which is fired whenever an Microsoft Outlook item is sent, either by the user through an Inspector (before the inspector is closed, but after the user clicks the Send button) or when the Send method for an Outlook item. In the event handler you can set the SaveSentMessageFolder property which allows to set a Folder object that represents the folder in which a copy of the e-mail message will be saved after being sent.

Related

Save attachments of incoming email with specific subject

On Outlook 365, so no rules + script allowed as I'm not full admin on the machine.
I need to check when mail arrives,
if it has some specific words in the subject
then save the attachment in a specific folder (it would be better with the name of the mail subject + datestamp) and then put the mail in the bin.
I tried the next code.
Option Explicit
Private WithEvents inboxItems As Outlook.Items
Private Sub Application_Startup()
Dim outlookApp As Outlook.Application
Dim objectNS As Outlook.NameSpace
Set outlookApp = Outlook.Application
Set objectNS = outlookApp.GetNamespace("MAPI")
Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items
End Sub
'--------------------- ok till here -----------
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Dim objAttachments As Outlook.Attachments
Set objAttachments = Msg.Attachments
If TypeName(Item) = "MailItem" Then
If InStr(Msg.Subject, "Magic Red Carpet") Then
objAttachments.SaveAsFile "C:\Users\xx12345\Desktop\vba\" & objAttachments.Msg.Subject&date
End If
End If
ErrorHandler:
MsgBox "dho!"
End Sub
You need to use the item object passed as a parameter to the ItemAdd event of the Items class in the code:
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
On Error GoTo ErrorHandler
Dim objAttachments As Outlook.Attachments
Set objAttachments = Item.Attachments
If TypeName(Item) = "MailItem" Then
If InStr(Item.Subject, "Magic Red Carpet") Then
objAttachments.SaveAsFile "C:\Users\xx12345\Desktop\vba\" & objAttachments.Msg.Subject&date
End If
End If
End Sub
Note, the Subject string may contain symbols not allowed in file names. So, I'd recommend checking for them before calling the SaveAsFile method.
Also you may consider handling the NewMailEx event of the Application class instead. This event fires once for every received item that is processed by Microsoft Outlook. The item can be one of several different item types, for example, MailItem, MeetingItem, or SharingItem. The NewMailEx event fires 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.

Reference a Shared Sub Folder in an inbox

I'm looking to modify my VBA code to reference a shared inbox that has a subfolder inside of it. The commented out code worked with my main inbox folder and a sub folder called test. I've tried to use the getSharedDefaultfolder method but the code currently does not detect an email being placed in the subfolder of my shared inbox. Does anyone have any thoughts or recommendations?
Public WithEvents objInbox As Outlook.Folder
Public WithEvents objInboxItems As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set shrdRecip = olNs.CreateRecipient(test#outlook.com)
Set Inbox = olNs.GetSharedDefaultFolder(shrdRecip, olFolderInbox).Folders("test")
'Set objInbox = Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Folders("test")'
'Set objInboxItems = objInbox.Items'
Set objInboxItems = Inbox.Items
End Sub
Private Sub objInboxItems_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim objForward As Outlook.MailItem
MsgBox Item.Subject
If TypeOf Item Is MailItem Then
Set objMail = Item
MsgBox objMail.UnRead
If (objMail.UnRead Or False) Then
Set objForward = objMail.Forward
With objForward
.Subject = "Custom Subject"
.HTMLBody = "<HTML><BODY>Type body here. </BODY></HTML>" & objForward.HTMLBody
.Recipients.Add (usr#yahoo.com)
.Recipients.ResolveAll
.Send
MsgBox Item.Subject
End With
End If
End If
End Sub
Sub MyTEST()
End Sub```
You need to add the shared folder/store to your Outlook profile if you want to get events fired in VBA.
Also make sure an instance of the Items class was initialized correctly in the code to get the events fired.
I'd suggest calling the Recipient.Resolve method before accessing the shared folder, it attempts to resolve a Recipient object against the Address Book.
Are you sure objInboxItems is not null? By default, GetSharedDefaultFolder only returns the folder but not its subfolders unless the shared mailbox is added to the profile as a delegate mailbox and and all its folders are synchronized by Outlook.

Event listener for new emails to download attachments

I came up with this to create an event listener for new emails to download attachments.
I combined How do I trigger a macro to run after a new mail is received in Outlook? with https://www.extendoffice.com/documents/outlook/3747-outlook-auto-download-save-attachments-to-folder.html
I cannot create a rule with macros in Outlook and I am unable to edit the registry on my current computer, so I need a workaround.
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")
' default local Inbox
Set Items = objNS.GetDefaultFolder(olFolderInbox).Items
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
If TypeName(item) = "MailItem" Then
Set Msg = item
Dim strSubject As String
strSubject = Msg.Subject
If InStr(0, strSubject, "VBA Test") > 0 Then
Dim oAttachment As Outlook.Attachment
Dim sSaveFolder As String
sSaveFolder = "F:\Jason - DataCopies"
For Each oAttachment In Msg.Attachments
oAttachment.SaveAsFile sSaveFolder & oAttachment.DisplayName
Next
End If
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
It seems you are interested in the NewMailEx event of the Application class. This event fires once for every received item that is processed by Microsoft Outlook. The item can be one of several different item types, for example,MailItem, MeetingItem, or SharingItem. The EntryIDsCollection string contains the Entry ID that corresponds to that item.
The NewMailEx event fires 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. However, depending on the setup on the client computer, after a new message arrives in the Inbox, processes like spam filtering and client rules that move the new message from the Inbox to another folder can occur asynchronously.
Dim mail as Object
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
Set mail = Application.GetNamespace("MAPI").GetItemFromID(EntryIDCollection)
End Sub
Another possible way is to hook up to the ItemAdd event of the Inbox folder:
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)
If TypeOf Item Is Outlook.MailItem Then
Example Item ' call sub
End If
End Sub
Public Sub Example(ByVal Item As Object)
Debug.Print Item.Subject
End Sub

Outlook reply to multiple emails on demand

Just wondering if this is possible and if it is can someone assist me with?
In this scenario what we do is emails comes into shared folder. We will then have those email sorted.
After the sorting we will start putting emails into an approved folder. What I will like to do is have a VBA macro in outlook that will be able to generate a custom reply to all the emails in the approved folder.
For example if we place 5 emails in the folder and run a script it should send emails out to those 5 senders.
The email will be something generic such as "You are approved, please logout a "time".
I'd suggest starting from the Getting Started with VBA in Outlook 2010 article in MSDN. It explains the basics of programming VBA macros.
The ItemAdd event is fired when one or more items are added to the Items collection (i.e. folder). Be aware, the event is not fired when a large number of items are added to the folder at once.
So, you can handle the ItemAdd event of the approved folder to create and send a reply. The Reply method of Outlook items creates a reply, pre-addressed to the original sender, from the original message. The Send method sends the e-mail message. For example:
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
Dim myOlAtts As Outlook.Attachments
Set myOlMItem = myOlApp.CreateItem(olMailItem)
myOlMItem.Save
Set myOlAtts = myOlMItem.Attachments
' Add new contact to attachments in mail message
myOlAtts.Add Item, olByValue
myOlMItem.To = "Sales Team"
myOlMItem.Subject = "New contact"
myOlMItem.Send
End Sub
Outlook reply to multiple emails on demand
Paste the following code in "ThisOutlookSession"
Outlook will automatically send a reply when you move Emails to "approved" folder
Option Explicit
'// items in the target folder to events
Dim WithEvents TargetFolderItems As Items
Private Sub Application_Startup()
Dim olNamespace As Outlook.NameSpace
Set olNamespace = Application.GetNamespace("MAPI")
Set TargetFolderItems = olNamespace.GetDefaultFolder(olFolderInbox) _
'// Set your folder here
.Folders.Item("approved").Items
End Sub
'// ItemAdd event code
Sub TargetFolderItems_ItemAdd(ByVal Item As Object)
Dim olReply As MailItem
Set olReply = Item.Reply
olReply.HTMLBody = "You are approved " & vbCrLf & olReply.HTMLBody
olReply.Send
Set TargetFolderItems = Nothing
Set olReply = Nothing
End Sub

Moving Outlook message with specific subject to Subfolders

I am trying to write a brief VBA script that will move incoming messages from my Outlook Inbox to a subfolder. This is what I currently have (assembled from various posts), but I'm not getting any result when I send test emails. If there are any other posts that would relate to this, I would appreciate it!
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
' Default local Inbox
Set Items = objNS.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Set myInbox = GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
If TypeName(item) = "MailItem" Then
Set Msg = item
If Msg.SenderEmailAddress = "name#example.com" Then
If InStr(0, Msg.Subject, "Subject Title", vbTextCompare) > 0 Then
Msg.Move myInbox.Folders("Test").Subfolder("Destination")
End If
End If
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
It looks like you didn't define and initialize the Items object properly. For example:
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
' do something here
End Sub
Be aware, the ItemAdd event is not fired when more than 16 items is added at the same time. This is a known issue in the OOM.
Try to use the NewMailEx event of the Application class instead. And I'd suggest reading the following series of 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)
Finally, is your macro enabled in Outlook? Have you checked out the Trust center settings?
Put your code in ThisOutlookSession.
Just above your code put
Public WithEvents Items As Items
When using the built-in class module ThisOutlookSession, Sub Application_Startup() initializes the handler.