Get Inboxes from Outlook - vba

I configured two Exchange accounts in Outlook 2010, however I cant find out how to get to Inbox of the second account. Session.GetDefaultFolder() always return the first one.
Even enumerating Session.Accounts, finding the right account and calling Session.Account(found one).Store.GetDefaultFolder() returns wrong Inbox (from the default exchange account, not the secondary).

Does this show you all the available Inboxes?
Sub LoopThroughInboxes
Dim ol As Outlook.Application
Dim ns As Outlook.NameSpace
Dim i As Long
Set ol = Outlook.Application
Set ns = ol.GetNamespace("MAPI")
For i = 1 To ns.Folders.Count
Debug.Print ns.Folders(i).Name
Next i
If so then ns.Folders(i).Folders("Inbox") will get you the Inbox for each mailbox.

To Go to Mapix library
Mapix library link as given below
Mapix library for C++/MFC
Note: This Library valid for Inbox emails in MS Outlook

Use Store.GetDefaultFolder instead of Namespace.GetDefaultFolder.
Note that Store.GetDefaultFolder was added in Outlook 2010. In the earlier versions of Outlook use Extended MAPI (C++ or Delphi) or Redemption (I am its author) - RDOStore.GetDefaultFolder.

Maybe you have long given up on this question, but here goes...
I've had this same problem before and I solved it by adding the Outlook Account Management API. Unfortunately for you, this a c++ oriented API. (My addin was already developed in c++)
Furthermore, the OOM (Outlook Object Model) which VBA and the .NET addins use has poor (if any) support for multiple accounts. By adding to exchange accounts, you have essentially added multiple accounts to your profile.
So, You might have to go down a level, using MAPI with c++ and then hook in the Outlook Account Management API. It's a lot of work, but that's exactely what I did and it worked like a charm.
Also, here is an example:
http://www.codeproject.com/KB/IP/IOlkAccountManager.aspx

I guess this is an old one, but somebody might need it one day.
Here is code to iterate all "Sent Mail" folders in Outlook. (I think this will only work for Outlook 2010 and newer).
MSOutlook._NameSpace ns = Globals.ThisAddIn.Application.GetNamespace("MAPI");
var accounts = ns.Accounts;
foreach (MSOutlook.Account account in accounts)
{
try
{
// You might want to test if DeliveryStore is null, in case this account is not an Exchange account
MSOutlook.MAPIFolder sentFolder = account.DeliveryStore.GetDefaultFolder(MSOutlook.OlDefaultFolders.olFolderSentMail);
if(sentFolder != null)
{
SentItems = sentFolder.Items;
SentItems.ItemAdd += LogMethods.Items_Sent_ItemAdd;
}
}
catch (Exception e)
{
BaseClass.log.Log(LoggLevel.Warning, e.Message);
}
}

Related

How to access the iCloud non-default Outlook Folders with Visual Basic VB.Net

This is my very first post and I'm not a programming expert as will quickly be apparent. Please be gentle.
I created a program (using Visual Basic 2010 express) that, among other things, would populate a text box with the "Notes"/"Body" of a contact I select based on the "CustomerID" value of each contact in Outlook.
It works perfectly for the default "Contacts" and its subfolder "Contacts-SubCategory" under Outlook's "My Contacts" group shown here:
enter image description here
using the following code (the code includes Calendar/appointment items I think I can adapt with a syntax solution for contacts so those can be ignored, I hope):
Public Class CustomOutlookInterface2
Private SQL As New DatabaseControl
Private ol As New Outlook.Application
Private olns As Outlook.NameSpace = ol.GetNamespace("MAPI")
Private olContactFolder As Outlook.MAPIFolder = olns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts).Folders("Contacts-SubCategory")
Private olCalendarFolder As Outlook.MAPIFolder = olns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
Private olContactItems As Outlook.Items = olContactFolder.Items
Private NewContact As Outlook.ContactItem
Private AppointmentItem As Outlook.AppointmentItem
However, I recently downloaded "iCloud for Windows" to keep everything synchronized and noticed that it added a new group in Outlook called "iCloud" and moved contact entries into newly created "Contacts in iCloud" and "Contacts-SubCategory in iCloud" (shown in same picture above). I've made numerous attempts to adapt the previous working code to direct it to the iCloud folder. The closest I've come is...
Private ol As New Outlook.Application
Private olns As Outlook.NameSpace = ol.GetNamespace("MAPI")
Private olContactFolder As Outlook.MAPIFolder = olns.Folders.Item("iCloud")
The above doesn't cause an error. But, it also results in "string not found" when I use the following
Dim query As String = "[CustomerID]='" & CustID & "'"
NewContact = olContactItems.Find(query)
where "query" is the number I assigned to the contact and stored in the Customer ID field
Based on the flat spots on my forehead from banging my head on the desk, I think it boils down to the syntax of identifying the iCloud group then the "Contacts in iCloud" folder then the "Contacts-SubCategory in iCloud" subfolder.
In windows pathing equivalent "iCloud\Contacts in iCloud\Contacts-SubCategory in iCloud\
I can't tell you how much I'd appreciate any help. My desk is threatening to call the cops for all the headbutts I've given it.
I figured out the answer to my own question. I was going to delete the question altogether since it has not been addressed by anyone yet. However, I decided to post my solution in case it helps someone else.
In Outlook, the Contacts screen looks like this:
enter image description here
My mistake was not understanding that when iCloud for Windows created the iCloud folder it also created the “Contacts-SubCategory” as a subfolder of Contacts (it doesn’t visual look like a sub-folder). Also, the “…in iCloud” suffix shown in Outlook is NOT part of the name needed to identify the folder in code. The code that worked for me to drill down on the “…SubCategory” folder was:
Private olContactFolder As Outlook.MAPIFolder = olns.Folders.Item("iCloud").Folders("Contacts").Folders("Contacts-SubCategory")
Without the "...in iCloud" suffix that appears in Outlook. I hope this helps any other inexperienced folks like me. I suffered enough for all of you in trying to solve this as a self-taught rookie. Hopefully you found this post quickly before giving up as I almost did.

Determine currently active Outlook store in vba / wsh vbs

I'm using JavaScript and the Windows Scripting Host to work with Outlook items.
This has been straightforward enough, until one of our users pointed out that the script does not work because he has two Exchange profiles configured in Outlook.
The one the script should be working on is in the second profile, but if I access, e.g. the Outlook categories master list, this is loaded from the standard profile.
The answer is easy enough, I just need to address the correct Outlook store object. My script needs to determine, which store is being accessed in the currently active Outlook Explorer, and I could not find a native function for this.
Given an outlook application object var ol = new ActiveXObject( "Outlook.Application" ), I can natively determine the currently active Outlook explorer by simply calling ol.[ActiveExplorer()][4]; But the session object, through which stores are accessed, does not offer an equivalent function.
I've come up with a workaround, by comparing the explorer's caption
ol.ActiveExplorer().Caption // "Inbox - email#address.com - Outlook"
with a loop over the stores' display names
ol.Session.Stores.Item(counter).DisplayName // "email#address.com"
So I do have working code:
function ActiveStore(olApplication) {
var ActiveExplorerCaption=olApplication.ActiveExplorer().Caption;
for (var storeCounter=1; storeCounter<=olApplication.Session.Stores.Count; storeCounter++) {
var storeDisplayName=olApplication.Session.Stores.Item(storeCounter).DisplayName;
if (ActiveExplorerCaption.indexOf(storeDisplayName)!=-1) return olApplication.Session.Stores.Item(storeCounter);
}
return "undefined";
};
var ol = new ActiveXObject( "Outlook.Application" );
WScript.Echo("The Outlook store currently active in an explorer is called "+ActiveStore(ol).DisplayName);
But, I'm wondering:
will this code always work, i.e. are this variables always set up in this way, or just in the installations I can work with
isn't there a better way to determine the currently active store?
Since you have ActiveExplorer, you also have Explorer.CurrentFolder and thus Folder.StoreID. Then use Namespace.GetStoreFromID using that StoreID value.

Outlook 2010 Running Rules on Outlook Data File

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

Accessing a shared mailbox using redemption, for a Vb.net outlook add in

I m working on a outlook add in using Redemption, which has to move emails from my outlook inbox to a specified folder.
It works fine until it is for the local mailbox.
When i try to do the same on a shared mailbox,from my outlook it doesn't work.
Meaning on my outlook i access the shared mailbox and try to move the mail from shared mailboxes "Inbox" to a folder in shared mailbox itself.
I use the below code for the same.
oTempFolder = oRDOSession.GetSharedMailbox("mailbox name")
It throws the below error:
System.InvalidCastException: Unable to cast COM object of type 'Redemption.RDOStoreClass' to interface type 'Redemption.RDOFolder'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{15B8597F-0A55-4361-AE8B-1F690BC61EE4}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
I tried putting the mailbox name and the mailbox address also, nothing helped.
I tried the below code, found here on stackoverflow itself
store = _session.Stores.GetSharedMailbox("Example shared mailbox ");
But it didn't make a difference.
Can someone please guide me into this?
After a bit of Research and trial i found a solution to the above question.
Below code line is actual beginning of it.
store = _session.Stores.GetSharedMailbox("Example shared mailbox ");
Below is the code to find the folder in the shared mailbox you need to find.
Dim Rclass As Redemption.RDOStore
Dim oTempFolders As Redemption.RDOFolders
Dim oTempFolder As Redemption.RDOFolder
Rclass = oRDOSession.Stores.GetSharedMailbox(aFolders(0))
oTempFolders = Rclass.IPMRootFolder.Folders
For i = 1 To oTempFolders.Count
oTempFolder2 = oTempFolders.Item(i)
If oTempFolder2.Name.ToLower = "folder name" Then
oTempFolder = oTempFolder2
Exit For
End If
Next
Hope this helps someone who comes accross this issue.

Open Outlook mail Item using EntryID, StoreID, and / or PR_ENTRYID

NOTE: I'm using VBA and Office 2007. (I would use C#, but the project parameters don't allow this)
I'm attempting to find some method in Outlook, or an API, that will allow me to open an Outlook mail item by providing either the Outlook EntryID or the MAPI "PR_ENTRYID" property from an Access Database. I have found many references to said code, but I have never seen anyone actually post a solution. I have attempted in include references to mapi32.dll and OLMAPI32.dll, but I get the following error: "Can't add a reference to the specified file." I'm guessing this is because those dll's are meant for .NET.
Any help you can give would be greatly appreciated.
Use Namespace.GetItemFromID. Note the second parameter (store id) is optional. You can omit it if the store in question was already touched by Outlook is in the current session. If not, Outlook will raise the "unknown entry id" exception. If the store entry id is specified, Outlook will open it first, and the store provider will have a chance to register its entry ids with the MAPI system.
set App = CreateObject("Outlook.Application")
set NS = App.GetNamespace("MAPI")
NS.Logon
set Msg = NS.GetItemFromID(EntryID)
MsgBox Msg.Subject
For C#:
var ns = OutlookApp.GetNamespace("MAPI");
var item = ns.GetItemFromID(entryId) as MailItem;
Where OutlookApp has Microsoft.Office.Interop.Outlook._Application type.