Outlook 2010 Running Rules on Outlook Data File - vba

I've used Thunderbird and now moving across to Outlook 2010, PC is Windows 7 Professional, 64 bit machine but I use 32 bit Office 2010.
I have 8 email addresses including 4 gmail addresses: all are IMAP. No exchange servers.
I believe that with IMAP, moving emails from the account inbox means they are no longer on the server so other devices can't see them anymore - happy to be corrected on this.
Thunderbird
I copy (not move) all emails to a Local Folders Inbox.
I then have a folder structure under that local folders Inbox.
I click a run rules button and it moves them (not copies) to the relevant sub folder.
The result is that apart from spam and legit emails without a rule, the inbox folder is emptied.
Outlook2010
I have the VBA routine that runs all rules in place and that works fine, I've even added the button to trigger that.
I have recreated my Thunderbird set-up by creating my folder structure under the Outlook Data File Inbox.
I've created for each email account a rule that all messages are copied (not moved) to that Outlook Data File Inbox.
I'm aware that rules must be created under each account and I believe no rules can be created in any Outlook Data File folder or sub folder.
However, if you then go to Rules/Alert pop up and select Run Rules Now you can select the rules to run and they will run on any folder including any Outlook Data File.
Essentially, I want to automate this process of running all rules on the Outlook Data File Inbox.
I cannot work out how to make the VBA code select that Outlook Data File Inbox, then run all rules on just that Outlook Data File Inbox.
Again, I believe this is necessary because if the Move rule runs from the account email inbox, that once the emails are moved from the account email inbox they are no longer available to be viewed on any other device.
I know I could copy all the emails from each account email inbox to the relevant sub folder and not bother copying to the Outlook Data File Inbox first. But this means I still need to regularly check all 8 email account inboxes in case an important email is in there for which I have not created a rule.
Any help would be appreciated.
Nigel

I will not be able to help you with VBA but allow me to propose an alternative.
First of all let me mention that it works for Outlook Data Files and any inbox that you specify. If you are familiar with VBA you should not have any problem with using my solution since the code is fairly simple.
Full solution has been described under similar question on superuser.
You can review it and clone it from Github project p0r. Its free.
To make it more relevant allow me to elaborate. I'm using Powershell to automate outlook and create custom rules within the script.
To connect to Outlook data file you can use following code:
$pstPath = "D:\path\to\pst\file.pst"
# CREATING OUTLOOK OBJECT
$outlook = New-Object -comobject outlook.application
$namespace = $outlook.GetNameSpace("MAPI")
# GETTING PST FILE THAT WAS SPECIFIED BY THE PSTPATH VARIABLE
$pst = $namespace.Stores | ?{$_.FilePath -eq $pstPath}
# ROOT FOLDER
$pstRoot = $pst.GetRootFolder()
# SUBFOLDERS
$pstFolders = $pstRoot.Folders
# PERSONAL SUBFOLDER
$personal = $pstFolders.Item("Personal")
And you can create your own rule by replacing the condition in the IF statement:
# MOVE EMAILS WITH SPECIFIC STRING IN TITLE TO THE SUBFOLDER /RANDOM/ UNDER PST FILE
# ! DESTINATION FOLDER SPECIFIED INLINE
IF ($Email.Subject -match "SPECIFIC STRING IN TITLE") {
$Email.Move($pstFolders.Item("Random")) | out-null
display ([string]$Email.Subject ) ([string]"Yellow")
continue
}
I'm using $Email.Move method to move email object from inbox to PST file, but you can use $Email.Copy if you prefer. Of course you can move emails between directories in Outlook data store as well.
Hope this helps. Let me know in case of any questions. I will be glad to help.

Re: I cannot work out how to make the VBA code select that Outlook Data File Inbox...
Private Sub ProcessPST()
Dim objNs As Namespace
Dim pstFolder As folder
Dim objItem As Object
Dim i As Long
Set objNs = GetNamespace("MAPI")
Set pstFolder = objNs.Folders("Test") ' <--- Test is the name of the pst
For i = 1 To pstFolder.Items.count
Set objItem = pstFolder.Items(i)
Debug.Print objItem.Subject
Next i
ExitRoutine:
Set objNs = Nothing
Set pstFolder = Nothing
Set objItem = Nothing
End Sub

Related

Pause/Stop downloading new emails while running VBA macro in Outlook [pause/stop sync]

I'm new to VBA Programming in Outlook.
I'm writing a macro which scans inbox and moves emails to specific folders by checking criteria such as subject, sender, body etc.
Now the problem is that when I loop through the mailbox and a new email comes in, the loop breaks.
First possible solution to this that came to my head was disabling email synchronization for the time when macro is running. I researched this further and found the Sync Object in Outlook VBA with the method Sync.Start and Sync.Stop.
docs Microsoft - SyncObject.Start method
So I declared all variables like in the link and tried the code. Everything seems to be executed without errors, I loop through all the sync objects and stop them however I noticed that emails come to my inbox anyway.
Public Sub Sync()
Dim nsp As Outlook.NameSpace
Dim sycs As Outlook.SyncObjects
Dim syc As Outlook.SyncObject
Dim i As Integer
Set nsp = Application.GetNamespace("MAPI")
Set sycs = nsp.SyncObjects
For i = 1 To sycs.Count
Set syc = sycs.Item(i)
syc.Stop
Next
End Sub
Any ideas how to make this work or other ideas how to overcome this problem are greatly appreciated. Thanks
[EDIT 1, 07.05.2020, 20:29] Thanks for your comments guys, I just got another idea in my head. I could create a temporary folder, move all emails that satisfy my criteria from inbox into this temporary folder, sort those emails to other folders from that temp folder. This should work because no new emails will be coming to the temp folder unlike inbox!
Firstly, please show your code that processes the items.
Secondly, you can sort your collection (Items.Sort) on ReceivedTime and process the Items collection backwards (Items.Count to 1 step -1)
Instead of iterating over all items in the folder and don't break the loop when a new item arrives, I'd recommend using the Find/FindNext or Restrict methods where you can find only items that correspond to your conditions. Read more about these methods in the following articles:
How To: Use Restrict method in Outlook to get calendar items
How To: Retrieve Outlook calendar items using Find and FindNext methods
Also, you can process items by small chunks by finding all items for a week or month and etc.

How to bulk export Attachments from emails (which are emails) to another folder within Outlook

I need to extract .msg attachments from emails in a range and save these into another outlook sub-folder. This works currently by dragging the attachment into a sub-folder of 'inbox' but is there a quicker way?
I have searched around a bit and found ways to extract them to a local folder but i need them to be contained within outlook.
I appreciate any help and suggestions.
Thanks.
There are two problems here - first is accessing embedded message attachments without saving them first as MSG file. Second is importing the MSG files back - you can use Application.CreateItemFromTemplate, but the item will be unsent. You can use Namespace.OpenSharedItem, and then use MailItem.Move, but it is still a kludge.
There issn't much much you can do in OOM alone. Extended MAPI would work, but it is C++ or Delphi only. If using Redemption is an option (I am its author), you can use EmbeddeedMsg property exposed by the Redemption RDOAttachment object. You can also use RDOMail.CopyTo and pass a folder as a parameter to copy an embedded message attachment to a folder:
Set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set redItem = Session.GetMessageFromId(OutlookMessage.EntryID)
set redFolder = Session.GetFolderFromId(OutlookFolder.EntryID)
for each attach in redItem.Attachments
if attach.Type = olEmbeddeditem Then
attach.EmbeddedMsg.CopyTo OutlookFolder
End If
next

VBA Outlook code to open Mail Item and Save As text

I'm receiving Outlook mails that have other Outlook mails (*.msg) as attachments. I need them in txt format (or anything else Word can open).
I seem to have two choices:
1) Save the attachments to my drive as text files, rather than msg files. I have no idea how to do that, either manually or by code.
2) Save the attachments as msg files (I got a macro here on SO that does that), then open each file and save it at txt. But File-->Open in Outlook 2010 has no option for opening msg files. The only way I can see to open the file is to (manually) view the folder in File Explorer and double-click it. Once its open, I can use File-->SaveAs.
3) I could open and save the file in VBA. Or can I? (It seems you can't record a macro in Outlook the way you can in Word or Excel, or I would have tried it.)
EDIT: I tried Dmitri's suggestion, and this seems to work:
Dim oNamespace As NameSpace
Dim oFolder As Folder
' Get a reference to a NameSpace object.
Set oNamespace = Application.GetNamespace("MAPI")
' Open the file containing the shared item.
Set oSharedItem = oNamespace.OpenSharedItem("D:\temp.msg")
' Save the item to the folder.
oSharedItem.SaveAs "D:\temp.txt"
Save the embedded message attachments as MSG files (Attachment.SaveAsFile), then open then using Namespace.OpenSharedItem.
If you want to access the embedded message attachments as messages without saving them, you'd need either Extended MAPI (IAttach::OpenProperty(PR_ATTACH_DATA_OBJ, IID_IMessage, ...), C++ or Delphi only) or Redemption (I am its author - it exposes Attachment.EmbeddedMsg property).

Outlook VBA stops functioning the next day

I have VBA code in Outlook I use to send specific emails (with three asterics in the subject line) to the deleted folder after sent in 'This Outlook Session'.
It works correctly when Outlook is first opened, and all day long, however, the next day I find at some point overnight the VBA code has failed to function and only functions properly again if I close \ re-open Outlook??
This only started to occur when the company moved to the 2007 & 2010 versions.
I need it to run constantly on sent mail as I have early am batch processes that send out a lot of emails that I want to have removed from sent folder and placed in the deleted folder after eachis sent as this code does.
Here is the code. Since it worked well before, I can only assume the newer Outlook versions need some additional trigger to keep 'This Outlook Session' open or something of that nature.
Any thoughts would be appreciated.
Option Explicit
Private WithEvents olSentItems As Items
Private Sub Application_Startup()
Dim objNS As NameSpace
Set objNS = Application.GetNamespace("MAPI")
Set olSentItems = objNS.GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub olSentItems_ItemAdd(ByVal Item As Object)
If Item.Class = olMail And InStr(1, Trim(Item.Subject), " * * * ", vbTextCompare) > 0 _
Then
Item.Delete
End If
End Sub
I suggest that you have a look at the Trust Center Settings >> Macros. Office 2003 has it in a different way and it is all new after Office 2003.
Try different settings and see which one fits your need. They are totally four setting levels.
Also it is good idea to use only one version of Outlook. Don't interchange between 2007 and 2010 if you have both of them. Outlook versions cannot co exist with creation of bugs.
This page should be able to give me more details.
Click Here

How do I make Outlook purge a folder automatically when anything arrives in it?

I hope it's okay to ask this kind of question. Attempting to write the code myself is completely beyond me at the moment.
I need a macro for Outlook 2007 that will permanently delete all content of the Sent Items folder whenever anything arrives in it. Is it possible? How do I set everything up so that the user doesn't ever have to click anything to run it?
I know I'm asking for a fish, and I'm embarrassed, but I really need the thing...
edit:
I've pasted this into the VBA editor, into a new module:
Public Sub EmptySentEmailFolder()
Dim outApp As Outlook.Application
Dim sentFolder As Outlook.MAPIFolder
Dim item As Object
Dim entryID As String
Set outApp = CreateObject("outlook.application")
Set sentFolder = outApp.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete '' Delete from mail folder
Next
Set item = Nothing
Set sentFolder = Nothing
Set outApp = Nothing
End Sub
It's just a slightly modified version of a piece of code I found somewhere on this site deleting Deleted Items. It does delete the Sent Items folder when I run it. Could you please help me modify it in such a way that it deletes Sent Items whenever anything appears in the folder, and in such a way that the user doesn't have to click anything to run it? I need it to be a completely automated process.
edit 2: Please if you think there's a better tool to achieve this than VBA, don't hesitate to edit the tags and comment.
edit 3: I did something that works sometimes, but sometimes it doesn't. And it's ridiculously complicated. I set a rule that ccs every sent email with an attachment to me. Another rule runs the following code, when an email from me arrives.
Sub Del(item As Outlook.MailItem)
Call EmptySentEmailFolder
End Sub
The thing has three behaviors, and I haven't been able to determine what triggers which behavior. Sometimes the thing does purge the Sent Items folder. Sometimes it does nothing. Sometimes the second rule gives the "operation failed" error message.
The idea of acting whenever something comes from my address is non-optimal for reasons that I'll omit for the sake of brevity. I tried to replace it with reports. I made a rule that sends a delivery report whenever I send an email. Then another rule runs the code upon receipt of the report. However, this has just one behavior: it never does anything.
Both ideas are so complicated that anything could go wrong really, and I'm having trouble debugging them. Both are non-optimal solutions too.
Would this be an acceptable solution? Sorry its late but my copy of Outlook was broken.
When you enter the Outlook VB Editor, the Project Explorer will be on the left. Click Ctrl+R if it isn't. It will look something like this:
+ Project1 (VbaProject.OTM)
or
- Project1 (VbaProject.OTM)
+ Microsoft Office Outlook Objects
+ Forms
+ Modules
"Forms" will be missing if you do not have any user forms. It is possible "Modules" is expanded. Click +s as necessary to get "Microsoft Office Outlook Objects" expanded:
- Project1 (VbaProject.OTM)
- Microsoft Office Outlook Objects
ThisOutlookSession
+ Forms
+ Modules
Click ThisOutlookSession. The module area will turn white unless you have already used this code area. This area is like a module but have additional privileges. Copy this code to that area:
Private Sub Application_MAPILogonComplete()
' This event routine is called automatically when a user has completed log in.
Dim sentFolder As Outlook.MAPIFolder
Dim entryID As String
Dim i As Long
Set sentFolder = CreateObject("Outlook.Application"). _
GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete ' Move to Deleted Items
Next
Set sentFolder = Nothing
End Sub
I have taken your code, tidied it up a little and placed it within an event routine. An event routine is automatically called when the appropriate event occurs. This routine is called when the user has completed their log in. This is not what you requested but it might be an acceptable compromise.
Suggestion 2
I have not tried an ItemAdd event routine on the Sent Items folder before although I have used it with the Inbox. According to my limited testing, deleting the sent item does not interfere with the sending.
This code belongs in "ThisOutlookSession".
Option Explicit
Public WithEvents MyNewItems As Outlook.Items
Private Sub Application_MAPILogonComplete()
Dim NS As NameSpace
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
With NS
Set MyNewItems = NS.GetDefaultFolder(olFolderSentMail).Items
End With
End Sub
Private Sub myNewItems_ItemAdd(ByVal Item As Object)
Debug.Print "--------------------"
Debug.Print "Item added to Sent folder"
Debug.Print "Subject: " & Item.Subject
Item.Delete ' Move to Deleted Items
Debug.Print "Moved to Deleted Items"
End Sub
The Debug.Print statements show you have limited access to the sent item. If you try to access more sensitive properties, you will trigger a warning to the user that a macro is assessing emails.