Trigger an Outlook script after the email has entered the inbox - vba

I'm trying to finalize an integration between my access system and Outlook.
The basis of the system is that Outlook needs to trigger a script when an email enters a specific Inbox. This script then opens the Access DB and runs it's own function to go through that inbox, take the attachment in the email and import it into the database.
Currently both scripts "Work" in so far as Outlook calling Access and Access doing it's thing. The problem is when Outlook executes the script, it's BEFORE the message is actually in the mailbox. The access app will launch, scan the inbox as empty and close just before the message actually enters the inbox.
I've tried adding a "Pause" loop in the script, to try and have it wait until the email is readable before opening the access app, but that just froze outlook for the duration of the "Pause" instead of letting the email become readable.
Here is my script in Outlook:
Sub ExecuteDealRequest(item As Outlook.MailItem)
Dim currenttime As Date
currenttime = Now
Do Until currenttime + TimeValue("00:00:30") <= Now
Loop
Dim AccessApp As Access.Application
Set AccessApp = CreateObject("Access.Application")
AccessApp.OpenCurrentDatabase ("C:\commHU\Comm HU Request.accdb"), False
AccessApp.Visible = True
AccessApp.DoCmd.RunMacro "Macro1"
Set AccessApp = Nothing
End Sub
At this point: I'm using outlook rules to launch the script:
Apply this rule after the message arrives
With Pricing Request in the Subject
and on this computer only
Move it to the Pricing Requests folder
and run Project.ExecuteDealRequest
and stop processing more rules
Any help would be great, as this is the last piece that I need to get working

You don't need Rule, Try it this way- code in ThisOutlookSession
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
ExecuteDealRequest Item
End If
End Sub
' ---- Your Code
Sub ExecuteDealRequest(Item As Outlook.MailItem)
Dim currenttime As Date
Dim AccessApp As Access.Application
Set AccessApp = CreateObject("Access.Application")
AccessApp.OpenCurrentDatabase ("C:\commHU\Comm HU Request.accdb"), False
AccessApp.Visible = True
AccessApp.DoCmd.RunMacro "Macro1"
Set AccessApp = Nothing
End Sub

You could try something like this,
Add this code to wait for a new email
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
ThisOutlookSession.GetNamespace("MAPI").GetItemFromID(EntryIDCollection).Subject
' Check for the email subject / any property
'then call your method
End Sub

Related

Automatically Mark email in Deleted Items as Read Outlook 2016 VBA

I had a little macro set up with Outlook on another machine but now that I've switched computers I can't get it to work. When I try to run the last Private Sub, it doesn't recognize the name and pulls up the Macro selection box with no options listed.
I dislike having to manually mark emails in the Deleted Items folder as read, especially considering they had the amazing foresight to mark discarded drafts as unread.
Here's the code that used to work:
Dim WithEvents g_OlkFolder As Outlook.Items
Private Sub Application_Quit()
Set g_OlkFolder = Nothing
End Sub
Private Sub Application_Startup()
Set g_OlkFolder = Session.GetDefaultFolder(olFolderDeletedItems).Items
End Sub
Private Sub g_OlkFolder_ItemAdd(ByVal Item As Object)
Item.UnRead = False
Item.Save
End Sub
Here are a few things to try and check:
Put the cursor in the Application_Startup method and press F5. Then go back and try again. If this helps, the initialization has not run, and the g_OlkFolder variable is not set.
Put a breakpoint on the Item.UnRead = False line. If it doesn't stop there, your method isn't running.
Have you put your code in the ThisOutLookSession module?
Try using Application.Session property, or use GetNamespace method which I prefer
Example
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim DeletedFolder As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set DeletedFolder = olNs.GetDefaultFolder(olFolderDeletedItems)
Set Items = DeletedFolder.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
' do something with Item
End If
End Sub
Or define olFolderDeletedItems or replace it with 3.
See this link for details.
Upon completely throwing away my code and starting from scratch I figured out a much simpler solution than what I was trying. Thanks for all the help anyways guys!
Sub MDAU()
Dim DI As Outlook.Items
Dim MSG As Object
Set DI = Session.GetDefaultFolder(olFolderDeletedItems).Items
Set MSG = Application.CreateItem(olMailItem)
For Each MSG In DI
MSG.UnRead = False
Next
End Sub

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

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.

VBA Outlook userform prompt

I have a userform that is prompted when I send emails (works great. not the problem) and from there when I click the buttons on the form it moves that email to the respective folder.
What I now want is for that same userform (rather, a duplicate) to be prompted when a message in my inbox goes from unread to read. The buttons on the userform would then move that message to the respective folder.
Code to bring up userform when sending emails:
Private Sub Application_ItemSend(ByVal Item As Object, cancel As Boolean)
UserForm1.Show vbModal
cancel = False
End Sub
Code snippet for a button of the userform:
Private Sub CommandButton1_Click()
On Error GoTo error_movemessage
Dim myolapp As New Outlook.Application
Dim mynamespace As Outlook.NameSpace
Dim myinbox As Outlook.MAPIFolder
Dim mydestfolder As Outlook.MAPIFolder
Dim myitems As Outlook.Items
Dim myItem As Object
Set mynamespace = myolapp.GetNamespace("MAPI")
Set myinbox = Session.GetDefaultFolder(olFolderInbox).Parent.Folders("RetainPermanently")
Set myitems = myinbox.Items
Set mydestfolder = myinbox
Set myItem = Application.ActiveInspector.CurrentItem
myItem.Move mydestfolder
Unload Me
exit_CommandButton1_Click:
Exit Sub
error_movemessage:
MsgBox "ERROR! " & Err.Description
Resume exit_CommandButton1_Click
End Sub
I searched far and wide for pieces to this puzzle and ultimately ended up unsuccessful. Thank you in advance!
Update:
Private Sub getselecteditem_click()
Dim oApp As New Outlook.Application
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection
Dim oItem As Object
Set oExp = oApp.Application
Set oSel = oExp.Selection
For i = 1 To oSel.Count
Set oItem = oSel.Item(i)
If oItem.Class = olMail Then
End If
Next i
End Sub
Sub oItem_PropertyChange(ByVal Name As String)
Select Case Name
Case "UnRead"
If oItem.UnRead = False Then
UserForm2.Show vbModal
End If
End Select
End Sub
Still doesn't work however.
I realized that I've been making this much harder than it needs to be. I can simply get it to pull up the prompt whenever i load a mailitem that happens to be unread. Here is an update:
Private Sub Application_ItemLoad(ByVal Item As Object)
If Item.Class = olMail Then
If Item.UnRead Then
UserForm2.Show vbModal
End If
End If
End Sub
Firstly, if you move an item to a different folder when the message is sent, you are asking for trouble - if you want the message to be saved in a folder other than Sent Items, set the MailItem.SaveSentMessageFolder property.
To move a message when its read state changes, track the Explorer.SelectionChange event. When SelectionChange event fires, start tracking the events on multiple messages from the Explorer.Selection collection (there can be more than one, but you can get away with just the first one as a proof of concept). When MailItem.PropertyChange event fires on the Unread property, display your prompt and move the message.

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

VBA outlook new mail

I am trying to run a function every time a new mail arrives in outlook. I have been doing some searching but I am unable to find I way to fire code every time an email arrives. Is there a new mail event that I could utilize?
I added a simple MsgBox to it to be able to see if the event is firing but it did not seem to be working. I placed this code in the ThisOutlookSession module. Any adivice? Here is my code.
Public WithEvents myOlApp As Outlook.Application
Sub Initialize_handler()
Set myOlApp = CreateObject("Outlook.Application")
End Sub
Private Sub myOlApp_NewMail()
Dim myExplorers As Outlook.Explorers
Dim myFolder As Outlook.MAPIFolder
Dim x As Integer
Set myExplorers = myOlApp.Explorers
Set myFolder = myOlApp.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
If myExplorers.Count <> 0 Then
For x = 1 To myExplorers.Count
On Error GoTo skipif
If myExplorers.Item(x).CurrentFolder.Name = "Inbox" Then
MsgBox ("Test")
myExplorers.Item(x).Display
myExplorers.Item(x).Activate
Exit Sub
End If
skipif:
Next x
End If
On Error GoTo 0
myFolder.Display
End Sub
Try to put:
Private Sub Application_NewMail()
MsgBox "New mail"
End Sub
In "ThisOutlookSession"
There's a good example on MSDN showing how to display the inbox when a new mail arrives (using Outlook.Explorers). You can probably adapt it pretty readily for your own program.