Setting a Default Send Through Account for Contacts


Just over a year ago I wrote a post demonstrating how to verify the account you’re sending an item through. The code in that solution traps the ItemSend event and displays a dialog-box asking you to confirm the account the message is being sent from. Clicking the Yes button on that dialog sends the message through the selected account, while clicking No cancels the send giving you an opportunity to change the account the item will go from. It’s a handy solution, but it suffers from one very prominent shortcoming. You have to verify the account every time you send something. If you change accounts you have to verify again. Both are a pain, or at least they are for me. Yes, verifying the account has saved me a few times from sending via the wrong account. Most of the time though it’s just an extra step, a step I don’t need. What would be really useful is an account check with some intelligence. One that could look at a message’s addressees and set the right account for me.

The solution I settled on uses categories to tie a contact to an account. Send a message to the contact and the solution sets the correct account automatically. No verification required except in certain circumstances, which I’ll explain in a minute. Here’s an example of how it works. Imagine that I have two contacts: Bob, who is a business contact, and Jane, a friend. I edit Bob’s contact and assign it to a category called #Business. I do the same for Jane’s contact only I assign it to a category called #Personal. Finally, I edit the code, below, by telling it what category names to look for and which of my email accounts to associate with each one. I’m ready to send a message. First up is a message to Jane. I address it to her, write the message, and click Send. This triggers the code. It looks at the message, sees that it’s addressed to Jane, and retrieves her contact so it can see if she is a member of the #Business category or the #Personal category. Discovering that she is a member of #Personal it sets the message to go out under my personal account. Next, I write a message to Bob. When I send it the code performs the same check, only this time it discovers that Bob is a member of the #Business category. The code sets the message to go out via my business account and sends it on its way. No extra steps and no annoying verifications. Like a good assistant the code does the work for me.

Great, you think, but what happens if I have multiple addressees on the same message? For example, I create a message and address it to both Bob and Jane. How does the code handle that? Great question. Remember when I said that there was no verification except in certain circumstances? Well, this is one of the those circumstances. When it does its check the code will see that the message is addressed to contacts in both categories and display a dialog-box asking to confirm the account the message should go through. Here’s the logic the code uses to determine how to proceed.

  1. Are all the message addressees members of the first category? If yes, send the message through the account associated with that category. Otherwise, fall through to #2.
  2. Are all the message addressees members of the second category? If yes, send the message through the account associated with that category. Otherwise, fall through to #3.
  3. Display a dialog-box asking you to confirm the account the message will be sent through.

The other condition that will force the code to ask you for verification is when one or more addressees don’t belong to either category. In that case it doesn’t know which account to use, so it will ask you to make the decision.

Ok, multiple addressees are covered, what about distribution lists? The code is ready for them too. Just like a contact, you can assign distribution lists to categories. The code operates on the principle that everyone in the distribution list is a member of the category. Beyond that the same rules apply for it as for contacts.

I hope it goes without saying that a contact should never be a member of both categories. They can be members of other categories, but should not be a member of both #Business and #Personal, or whatever category names you tell the code to check for. If a contact is a member of both categories, then the results will still be predictable, although it won’t provide the desired result. If Bob was a member of #Personal as well as #Business, then the results would depend on whether he’s the only addressee on a message or what category the other addressees belong to. Here’s what the results would be.

  • Bob is the only addressee. The message will go out via the account associated with whichever category the code checks for first. If you’ve set it to check the #Business category first, then it will go out under the associated account. If #Personal is first, then it will go out under that account.
  • There are other addressees and they all belong to the #Business category. The message will go out under the business account.
  • There are other addresses and they all belong to the #Personal category. The code will send the message via the personal account.
  • There are other addresses some belonging to #Business and others to #Personal. The code will prompt you to verify the account.

Does this solution work for meeting requests? Yes, but not in the same way. The code will always prompt you to verify the account a meeting request is sent through. Outlook’s object model does not provide a way to set that in code, so the only solution is to let you control it.

This solution will only work with Outlook 2007 and 2010. Earlier versions of Outlook do not support the objects required for this to function.

Instructions and Code.

Before adding the code you should decide on the categories you’ll use and the account you’ll associate with each. Go ahead and assign your contacts and distribution lists to the appropriate categories. To get the account names, create a new message and click the “Account” button directly below the Send button. You’ll need the category and account names when you add the code. The code is designed to handle two categories/accounts. If you need more than that, then contact me and I’ll explain how to modify the code accordingly.

The code comes in two parts. This is part 1. Follow these instructions to add the code.

  1. Start Outlook
  2. Press ALT+F11 to open the VB editor
  3. If not already expanded, expand Microsoft Office Outlook Objects
  4. Right-click on Class Modules, select Insert > Class Module
  5. In the Properties panel click on Name and enter clsSTA
  6. Copy the code from the Code Snippet box and paste it into the right-hand pane of Outlook’s VB Editor window
  7. Edit the code as needed. I included comments wherever something needs to or can change
  8. Click the diskette icon on the toolbar to save the changes
Option Explicit

'On the next line edit the name of the temporary folder as desired.
Const QUE_FOLDER = "Temp"

'First category.
'Repeat the next two lines as needed.  Edit the category name and address of the account to use for that category as needed.
Const CAT1_NAME = "#Business"
Const CAT1_ADDR = "Business@company.com"

'Second category.
Const CAT2_NAME = "#Personal"
Const CAT2_ADDR = "Personal@company.com"

Const SCRIPT_NAME = "Verify Sending Account"

Private WithEvents olkApp As Outlook.Application
Private WithEvents olkQue As Outlook.Items

Private Sub Class_Initialize()
    CheckForQueFolder
    Set olkQue = Session.GetDefaultFolder(olFolderInbox).Folders(QUE_FOLDER).Items
    Set olkApp = Outlook.Application
End Sub

Private Sub Class_Terminate()
    Set olkApp = Nothing
    Set olkQue = Nothing
End Sub

Private Sub olkApp_ItemSend(ByVal Item As Object, Cancel As Boolean)
    Dim olkRec As Outlook.Recipient, _
        olkCon As Outlook.ContactItem, _
        olkPrp As Outlook.UserProperty, _
        olkPA As Outlook.PropertyAccessor, _
        bolChanged As Boolean, _
        strAccount As String, _
        intPos1 As Integer, _
        intPos2 As Integer
    If Item.Class = olMail Then
        Set olkPrp = Item.UserProperties.Item("AcctChanged")
        If TypeName(olkPrp) = "Nothing" Then
            If AllInCategory(Item.Recipients, CAT1_NAME) Then
                Item.SendUsingAccount = Session.Accounts.Item(CAT1_ADDR)
                bolChanged = True
            Else
                If AllInCategory(Item.Recipients, CAT2_NAME) Then
                    Item.SendUsingAccount = Session.Accounts.Item(CAT2_ADDR)
                    bolChanged = True
                Else
                    If msgbox("The message is addressed to a mixture of contact types.  Are you sure you want to send it through the " & Item.SendUsingAccount & " account?", vbYesNo + vbApplicationModal, SCRIPT_NAME) = vbNo Then
                        Cancel = True
                    End If
                End If
            End If
        End If
        If bolChanged Then
            Set olkPrp = Item.UserProperties.Add("AcctChanged", olYesNo, False)
            olkPrp.Value = True
            Cancel = True
            olkApp.ActiveInspector.Close olSave
            Add2Que Item.EntryID
        End If
    Else
        Set olkPA = Item.PropertyAccessor
        strAccount = olkPA.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x0E28001E")
        intPos1 = InStr(1, strAccount, Chr(1))
        intPos2 = InStr(intPos1 + 1, strAccount, Chr(1))
        strAccount = Mid(strAccount, intPos1 + 1, intPos2 - (intPos1 + 1))
        If msgbox("Are you sure you want to send this item through the " & strAccount & " account?", vbYesNo + vbApplicationModal, SCRIPT_NAME) = vbNo Then
            Cancel = True
        End If
        Set olkPA = Nothing
    End If
    Set olkRec = Nothing
    Set olkCon = Nothing
    Set olkPrp = Nothing
End Sub

Private Sub olkQue_ItemAdd(ByVal Item As Object)
    Dim olkMsg As Outlook.MailItem
    Sleep 10
    Set olkMsg = olkApp.Session.GetItemFromID(Item.Subject)
    If TypeName(olkMsg) <> "Nothing" Then
        olkMsg.Send
    End If
    Item.Delete
    Set olkMsg = Nothing
End Sub

Private Sub CheckForQueFolder()
    Dim olkFld As Outlook.Folder
    On Error Resume Next
    Set olkFld = Session.GetDefaultFolder(olFolderInbox).Folders(QUE_FOLDER)
    If TypeName(olkFld) = "Nothing" Then
        Set olkFld = Session.GetDefaultFolder(olFolderInbox).Folders.Add(QUE_FOLDER)
    End If
    On Error GoTo 0
    Set olkFld = Nothing
End Sub

Private Sub Add2Que(strID As String)
    Dim olkPst As Outlook.PostItem
    Debug.Print "Add2Que"
    Set olkPst = olkQue.Add(olPostItem)
    With olkPst
        .Subject = strID
        .Body = ""
        .Save
    End With
    Set olkPst = Nothing
End Sub

Private Function AllInCategory(olkRecs As Outlook.Recipients, strName As String)
    Dim olkCon As Object, olkRec As Outlook.Recipient
    AllInCategory = True
    For Each olkRec In olkRecs
        If olkRec.AddressEntry.AddressEntryUserType = olOutlookDistributionListAddressEntry Then
            Set olkCon = Session.GetDefaultFolder(olFolderContacts).Items.Find("[Name] = '" & olkRec.Name & "'")
        Else
            Set olkCon = olkRec.AddressEntry.GetContact
        End If
        If TypeName(olkCon) = "Nothing" Then
            AllInCategory = False
            Exit For
        Else
            If TypeName(olkCon) <> "Nothing" Then
                If Not InCategory(olkCon.Categories, strName) Then
                    AllInCategory = False
                    Exit For
                End If
            Else
                AllInCategory = False
                Exit For
            End If
        End If
    Next
    Set olkCon = Nothing
    Set olkRec = Nothing
End Function

Private Function InCategory(strCats As String, strName As String) As Boolean
    Dim arrCats As Variant, varCat As Variant
    arrCats = Split(strCats, ",")
    For Each varCat In arrCats
        If varCat = strName Then
            InCategory = True
            Exit For
        End If
    Next
End Function

This is part 2. Follow these instructions to add the code.

Outlook 2007.

  1. If not already expanded, expand Microsoft Office Outlook Objects and click on ThisOutlookSession
  2. Copy the code from the Code Snippet box and paste it into the right-hand pane of Outlook’s VB Editor window
  3. Click the diskette icon on the toolbar to save the changes
  4. Close the VB Editor
  5. Click Tools > Trust Center
  6. Click Macro Security
  7. Set Macro Security to “Warnings for all macros”
  8. Click OK
  9. Close Outlook
  10. Start Outlook. Outlook will display a dialog-box warning that ThisOutlookSession contains macros and asking if you want to allow them to run. Say yes.

Outlook 2010.

  1. If not already expanded, expand Microsoft Office Outlook Objects and click on ThisOutlookSession
  2. Copy the code from the Code Snippet box and paste it into the right-hand pane of Outlook’s VB Editor window
  3. Click the diskette icon on the toolbar to save the changes
  4. Close the VB Editor
  5. Click File and select Options
  6. When the Outlook Options dialog appears click Trust Center then click the Trust Center Settings button
  7. Click Macro Settings
  8. Select either of the two bottom settings (i.e. “Notifications for all macros” or “Enable all macros (not recommended; potentially dangerous code can run)”. The choice of which to chose is up to you. If you select “Notifications”, then you’ll be prompted at times to enable macros. If you pick “Enable all” then there’s a chance that a malicious macro could run. It’s a question of how much risk you want to assume.
  9. Click Ok until the dialog-boxes have all closed
  10. Close Outlook
  11. Start Outlook. Outlook will display a dialog-box warning that ThisOutlookSession contains macros and asking if you want to allow them to run. Say yes.
Dim objSTA As clsSTA

Private Sub Application_Quit()
    Set objSTA = Nothing 
End Sub

Private Sub Application_Startup()
    Set objSTA = New clsSTA
End Sub

Notes.

  • The code uses a temporary folder which it creates under your Inbox folder. This folder is necessary for the code to work. If you delete it, then the code will fail. Close and restart Outlook and the code will re-create the folder. The reason for this folder stems from an Outlook programming restriction. Specifically, you cannot change the account a message is sent through during the send process. The workaround for this is to change the account, cancel the original send, then send the saved copy. Generally the way to do this is to implement a timer. Timers raise other issues though, so I opted for another approach. I cancel the send while writing a post to the temporary folder. Writing to the temp folder triggers another portion of the code which fetches the saved message and sends it again. Perhaps in a future version of Outlook Microsoft will allow programs to change the sending account without the need for workarounds like this.
  • Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s