Outlook 2003 VBA to detect selected account when sending - vba

Is it possible to detect which account an email is being sent via the Application_ItemSend VBA function of Outlook 2003? The accounts are POP3/SMTP on a standalone machine, and not MAPI or Exchange based.
I have tried using "Outlook Redemption" (http://www.dimastr.com/redemption/) but I just cannot find any property / method that will tell me which of the accounts the email is being sent through.
I don't need to be able to amend/select the account being sent from, just simply detect.

I have found a way of finding the account name, thanks to this link which provides the code for selecting a particular account.
Using this code as a base, I have create a simple GetAccountName function, which is doing exactly what I need it to do.
Edit: The below will only work if you're NOT using Word as the editor.
Private Function GetAccountName(ByVal Item As Outlook.MailItem) As String
Dim OLI As Outlook.Inspector
Const ID_ACCOUNTS = 31224
Dim CBP As Office.CommandBarPopup
Set OLI = Item.GetInspector
If Not OLI Is Nothing Then
Set CBP = OLI.CommandBars.FindControl(, ID_ACCOUNTS)
If Not CBP Is Nothing Then
If CBP.Controls.Count > 0 Then
GetAccountName = CBP.Controls(1).Caption
GoTo Exit_Function
End If
End If
End If
GetAccountName = ""
Exit_Function:
Set CBP = Nothing
Set OLI = Nothing
End Function

Here is a try:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Msgbox(Item.SendUsingAccount.DisplayName)
End Sub
This will give you the display name of the current sending account.
If that's not enough, you can try the other properties of the Item.sendUsingAccount var.

In Outlook 2003, you need to use the RDOMail object in Redemption to access the Account property of a mail item. Here is some code that changes the SendAccount from the default account to another account in the OL Profile, for all items in the Outbox. It could be improved by coding an account selection subroutine that reads the accounts in the OL Profile and presents them as a list for the user to select from. In the code provided the new send account is hard-coded.
Sub ChangeSendAccountForAllItems()
On Error Resume Next
Dim oOutlook As Application
Dim olNS As Outlook.NameSpace
Dim sOrigSendAccount As String
Dim sNewSendAccount As String
Dim iNumItemsInFolder As Integer
Dim iNumItemsChanged As Integer
Dim i As Integer
Dim rRDOSession As Redemption.RDOSession
Dim rRDOFolderOutbox As Redemption.RDOFolder
Dim rRDOMail As Redemption.RDOMail
'Create instance of Outlook
Set oOutlook = CreateObject("Outlook.Application")
Set olNS = Application.GetNamespace("MAPI")
'Create instance of Redemption
Set rRDOSession = CreateObject("Redemption.RDOSession")
rRDOSession.Logon
'Set a new Send Account (using Redemption)
'Change this to any SendAccount in your Profile
sNewSendAccount = "ThePreferredSendAccountNameInTheProfile"
Set rRDOAccount = rRDOSession.Accounts(sNewSendAccount)
Response = MsgBox("New Send Account is: " & sNewSendAccount & vbCrLf & _
vbCrLf, _
vbOK + vbInformation, "Change SendAccount for All Items")
'Get items in Outbox folder (value=4) (using Redemption)
Set rRDOFolderOutbox = rRDOSession.GetDefaultFolder(olFolderOutbox)
Set rRDOMailItems = rRDOFolderOutbox.Items
iNumItemsInFolder = rRDOFolderOutbox.Items.Count
iNumItemsChanged = 0
'For all items in the folder, loop through changing Send Account (using Redemption)
For i = 1 To iNumItemsInFolder
Set rRDOItem = rRDOMailItems.Item(i)
rRDOItem.Account = rRDOAccount
rRDOItem.Save
iNumItemsChanged = iNumItemsChanged + 1
'3 lines below for debugging only
'Response = MsgBox("Item " & iNumItemsChanged & " of " & iNumItemsInFolder & " Subject: " & vbCrLf & _
' rRDOItem.Subject & vbCrLf, _
' vbOK + vbInformation, "Change SendAccount for All Items")
Next
Response = MsgBox(iNumItemsChanged & " of " & iNumItemsInFolder & " items " & _
"had the SendAccount changed to " & sNewSendAccount, _
vbOK + vbInformation, "Change SendAccount for All Items")
Set olNS = Nothing
Set rRDOFolderOutbox = Nothing
Set rRDOMailItems = Nothing
Set rRDOItem = Nothing
Set rRDOAccount = Nothing
Set rRDOSession = Nothing
End Sub

Related

How to get the e-mail addresses in the CC field?

I found code in How to get the sender’s email address from one or more emails in Outlook?.
I need to get the e-mail addresses of the CC field as well.
Sub GetSmtpAddressOfSelectionEmail()
Dim xExplorer As Explorer
Dim xSelection As Selection
Dim xItem As Object
Dim xMail As MailItem
Dim xAddress As String
Dim xFldObj As Object
Dim FilePath As String
Dim xFSO As Scripting.FileSystemObject
On Error Resume Next
Set xExplorer = Application.ActiveExplorer
Set xSelection = xExplorer.Selection
For Each xItem In xSelection
If xItem.Class = olMail Then
Set xMail = xItem
xAddress = xAddress & VBA.vbCrLf & " " & GetSmtpAddress(xMail)
End If
Next
If MsgBox("Sender SMTP Address is: " & xAddress & vbCrLf & vbCrLf & "Do you want to export the address list to a txt file? ", vbYesNo, "Kutools for Outlook") = vbYes Then
Set xFldObj = CreateObject("Shell.Application").BrowseforFolder(0, "Select a Folder", 0, 16)
Set xFSO = New Scripting.FileSystemObject
If xFldObj Is Nothing Then Exit Sub
FilePath = xFldObj.Items.Item.Path & "\Address.txt"
Close #1
Open FilePath For Output As #1
Print #1, "Sender SMTP Address is: " & xAddress
Close #1
Set xFSO = Nothing
Set xFldObj = Nothing
MsgBox "Address list has been exported to:" & FilePath, vbOKOnly + vbInformation, "Kutools for Outlook"
End If
End Sub
Function GetSmtpAddress(Mail As MailItem)
Dim xNameSpace As Outlook.NameSpace
Dim xEntryID As String
Dim xAddressEntry As AddressEntry
Dim PR_SENT_REPRESENTING_ENTRYID As String
Dim PR_SMTP_ADDRESS As String
Dim xExchangeUser As exchangeUser
On Error Resume Next
GetSmtpAddress = ""
Set xNameSpace = Application.Session
If Mail.sender.Type <> "EX" Then
GetSmtpAddress = Mail.sender.Address
Else
PR_SENT_REPRESENTING_ENTRYID = "http://schemas.microsoft.com/mapi/proptag/0x00410102"
xEntryID = Mail.PropertyAccessor.BinaryToString(Mail.PropertyAccessor.GetProperty(PR_SENT_REPRESENTING_ENTRYID))
Set xAddressEntry = xNameSpace.GetAddressEntryFromID(xEntryID)
If xAddressEntry Is Nothing Then Exit Function
If xAddressEntry.AddressEntryUserType = olExchangeUserAddressEntry Or xAddressEntry.AddressEntryUserType = olExchangeRemoteUserAddressEntry Then
Set xExchangeUser = xAddressEntry.GetExchangeUser()
If xExchangeUser Is Nothing Then Exit Function
GetSmtpAddress = xExchangeUser.PrimarySmtpAddress
Else
PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
GetSmtpAddress = xAddressEntry.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
End If
End If
End Function
How could I adapt the code to include the e-mail addresses from the CC field as well?
I tried setting Recipients but couldn't get the desired outcome.
You need to replace the GetSmtpAddress function with your own where you could get the CC recipients in the following way (a raw sketch):
Function GetSmtpAddress(Mail As MailItem) as String
Dim emailAddress as String
Dim recipient as Outlook.Recipient
Dim recipients as Outlook.Recipients
Set recipients = Mail.Recipients
For Each recipient In recipients
If recipient.Type = olCC Then
If recipient.AddressEntry.Type = "EX" Then
emailAddress = emailAddress & " " & recipient.AddressEntry.GetExchangeUser.PrimarySmtpAddress
Else
emailAddress = emailAddress & " " & recipient.Address
End If
End If
Next
Return emailAddress
End Function
You may find the How To: Fill TO,CC and BCC fields in Outlook programmatically article helpful.
Loop through all recipients in the MailItem.Recipients collection, check that Recipient.Type = olCC. For each Recipient object use Recipient.Address. Note that you can end up with EX type addresses (instead of SMTP). Check that Recipient.AddressEntry.Type is "SMTP". If it is not, use Recipient.AddressEntry.GetExchangeUser.PrimarySmtpAddress instead (do check for nulls).

Return to previous mail item in Outlook on item close

I've written something that quickly changes an email subject to add the sender initials, so that I can click it before I add it to a JIRA issue using the Outlook JIRA plugin.
Currently, this is mildly annoying because it has to open the message to change the subject of the email and then when it returns, it moves onto the next message. This adds the mild inconvenience of having to make me move back to the correct message.
I'd be grateful for help figuring out how to make it return to the correct message. Maybe with MailItem.EntryID but I can't figure out how to point to it on close.
Sub EditSubject()
Dim Item As Outlook.MailItem
Dim oInspector As Inspector
Dim strSubject As String
Set oInspector = Application.ActiveInspector
If oInspector Is Nothing Then
Set Item = Application.ActiveExplorer.Selection.Item(1)
Item.Display 'Force the pop-up
Set oInspector = Application.ActiveInspector 'Reassign oInpsector and Item again
Set Item = oInspector.CurrentItem
Else
Set Item = oInspector.CurrentItem
End If
Dim Initials As String
strSubject = Item.Subject
Dim splitName() As String
splitName = Split(Item.SenderName, ",")
Initials = Left$(splitName(1), 2)
Initials = Right$(Initials, 1) + Left$(splitName(0), 1)
Item.Subject = UCase$(Initials) & " - " & strSubject
Item.Close (olSave)
Set Item = Nothing
Set oInspector = Nothing
End Sub
References:
[1] Saving emails with sender's initials
[2] Updating email subject in Outlook VBA
There is no need to open an inspector window for an item. You can change the Subject line without opening an actual item in a new inspector window.
Sub EditSubject()
Dim Item As Outlook.MailItem
Dim oInspector As Inspector
Dim strSubject As String
Set oInspector = Application.ActiveInspector
If oInspector Is Nothing Then
Set Item = Application.ActiveExplorer.Selection.Item(1)
Else
Set Item = oInspector.CurrentItem
End If
Dim Initials As String
strSubject = Item.Subject
Dim splitName() As String
splitName = Split(Item.SenderName, ",")
Initials = Left$(splitName(1), 2)
Initials = Right$(Initials, 1) + Left$(splitName(0), 1)
Item.Subject = UCase$(Initials) & " - " & strSubject
Item.Save
Set Item = Nothing
Set oInspector = Nothing
End Sub
The problem was not reproduced but you can reselect the item.
Option Explicit
Sub EditSubject_PreserveSelection()
Dim Item As mailItem
If ActiveInspector Is Nothing Then
Set Item = ActiveExplorer.Selection.Item(1)
Item.Display 'Force the pop-up
Else
Set Item = ActiveInspector.currentItem
End If
Dim Initials As String
Dim splitName() As String
'splitName = Split(Item.SenderName, ",")
'Initials = Left$(splitName(1), 2)
'Initials = Right$(Initials, 1) + Left$(splitName(0), 1)
'Item.subject = UCase$(Initials) & " - " & strSubject
Item.subject = "Initials" & " - " & Item.subject
Item.Close (olSave)
ActiveExplorer.ClearSelection
ActiveExplorer.AddToSelection Item
Set Item = Nothing
End Sub

Error creating Outlook Task Item in Sub-folder of Task folder

I've been using a routine that I discovered on Stack Overflow to automatically create a task item in Outlook in the default Tasks folder. I attempted to modify it to create the task in one of two sub-folders of Tasks named "New FTEs" and "New Consultants".
Running this code results in this message from the error handler.
Error Number: -2147221233
Error Source: AddOlkTask
Error Description: The attempted operation failed. An object could not be found.
The problem code is shown between 'start new code and 'end new code. I've tried many variants of this code, but I can't crack it (no pun intended).
Sub AddOlTask(sSubject, sBody, dtDueDate, dtReminderDate, name, program)
On Error GoTo Error_Handler
Dim noDue, pFolder, reminderSetFlag As String
reminderSetFlag = False
If program <> "Career Path Curriculum" Then
dtDue = dtDueDate
dtReminder = dtReminderDate
reminderSetFlag = True
End If
If program = "Active Consultant" Then
pFolder = "New Consultants"
Else
pFolder = "New FTEs"
End If
Const olTaskItem = 3
Dim olApp As Object
Dim OlTask As Object
Set olApp = CreateObject("Outlook.Application")
Set OlTask = olApp.CreateItem(olTaskItem)
With OlTask
.Subject = name & ": " & sSubject
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.dueDate = dtDue
.ReminderSet = reminderSetFlag
.ReminderTime = dtReminder
.Categories = "Mandatory SkillSoft Training" 'use any of the predefined Categorys or create your own
.body = sBody
.Display
.Save
End With
'start new code
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim tsk As Outlook.TaskItem
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderTasks)
Set olFolder = olFolder.Folders(pFolder) 'error raised on this line
'end new code
Error_Handler_Exit:
On Error Resume Next
Set OlTask = Nothing
Set olApp = Nothing
Exit Sub
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & "Error Number: " & _
Err.Number & vbCrLf & "Error Source: AddOlkTask" & vbCrLf & "Error Description: " & _
Err.Description, vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Sub
I had a similar problem and perhaps the cause of your problem is the same. I discovered the default Inbox was not in the store into which all my emails were loaded from my ISP. The default Inbox was in fact empty because it had never been used.
Run the macro below to discover what default folders you have and which store contains them.
Sub DsplUsernameOfDefaultStores()
Dim NS As Outlook.NameSpace
Dim DefaultFldr As MAPIFolder
Dim FldrTypeNo() As Variant
Dim FldrTypeName() As Variant
Dim InxFldr As Long
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
FldrTypeNo = VBA.Array(olFolderCalendar, olFolderConflicts, olFolderContacts, _
olFolderDeletedItems, olFolderDrafts, olFolderInbox, _
olFolderJournal, olFolderJunk, olFolderLocalFailures, _
olFolderManagedEmail, olFolderNotes, olFolderOutbox, _
olFolderSentMail, olFolderServerFailures, _
olFolderSuggestedContacts, olFolderSyncIssues, olFolderTasks, _
olPublicFoldersAllPublicFolders, olFolderRssFeeds)
FldrTypeName = VBA.Array("Calendar", "Conflicts", "Contacts", _
"DeletedItems", "Drafts", "Inbox", _
"Journal", "Junk", "LocalFailures", _
"ManagedEmail", "Notes", "Outbox", _
"SentMail", "ServerFailures", _
"SuggestedContacts", "SyncIssues", "Tasks", _
"AllPublicFolders", "RssFeeds")
Debug.Print "Stores containing default folders"
For InxFldr = 0 To UBound(FldrTypeNo)
Set DefaultFldr = Nothing
On Error Resume Next
Set DefaultFldr = NS.GetDefaultFolder(FldrTypeNo(InxFldr))
On Error GoTo 0
If DefaultFldr Is Nothing Then
Debug.Print "No default " & FldrTypeName(InxFldr)
Else
Debug.Print "Default " & FldrTypeName(InxFldr) & " in """ & DefaultFldr.Parent.Name & """"
End If
Next
End Sub
Second attempt at identifying the problem
I have added two sub-folders to my Tasks folders and then used the following macro to successfully display their names.
I have used Session instead of GetNamespace("MAPI"). These are supposed to be equivalent but I have once had Session work when GetNamespace("MAPI") did not. I don't remember the details and I did not investigate since I was happy to use Session.
You will need to amend my Set Fldr ... statement if your Tasks folder is not in the same location as mine. You can use Set Fldr = Session.GetDefaultFolder(olFolderTasks) if you prefer.
I have displayed the names with square brackets round them to highlight any stray spaces within the name.
Sub DsplTaskFolders()
Dim Fldr As Folder
Dim InxTskFldrCrnt
Set Fldr = Session.Folders("Outlook data file").Folders("Tasks")
For InxTskFldrCrnt = 1 To Fldr.Folders.Count
Debug.Print "[" & Fldr.Folders(InxTskFldrCrnt).Name & "]"
Next
End Sub
Thanks again Tony. You're code helped me understand the issue. I was not creating the custom folders in the correct location in Outlook. I created then under Inbox, when I should have created them under Tasks. The difference is not obvious. You basically have to right-click on the object Tasks - username#domain.com and select Create New Folder. If you right-click somewhere else, for instance, on the To-Do List, you'll create the folder under Inbox. It's working now.

Remove duplicate Outlook items from a folder

issue
Outlook 2016 corrupted while I was moving items from an online archive into a pst file.
The PST file has been recovered .... but many items (~7000) are duplicated 5 times
There are a range of item types, standard messages, meeting requests etc
what I tried
I looked at existing solutions and tools, including:
duplicate removal tools - none of which were free other than a trial option to remove 10 items at a time.
A variety of code solutions including:
Jacob Hilderbrand's effort which runs from Excel
Macro in Outlook to delete duplicate emails-
I decided to go the code route as it was relatively simple and to gain more control over how the duplicates were reported.
I will post my self solution below as it may help others.
I would like to see other potential approaches (perhaps powershell) to fixing this problem which may be better than mine.
The approach below:
Provides users with a prompt to select the folder to process
Checks duplicates on the base of Subject, Sender, CreationTime and Size
Moved (rather than delete) any duplicates into a sub-folder (removed items) of the folder being processed.
Create a CSV file - stored under the path in StrPath to create a external reference to Outlook of the emails that have been moved.
Updated: Checking for size surprisingly missed a number of dupes, even for otherwise identical mail items. I have changed the test to subject and body
Tested on Outlook 2016
Const strPath = "c:\temp\deleted msg.csv"
Sub DeleteDuplicateEmails()
Dim lngCnt As Long
Dim objMail As Object
Dim objFSO As Object
Dim objTF As Object
Dim objDic As Object
Dim objItem As Object
Dim olApp As Outlook.Application
Dim olNS As NameSpace
Dim olFolder As Folder
Dim olFolder2 As Folder
Dim strCheck As String
Set objDic = CreateObject("scripting.dictionary")
Set objFSO = CreateObject("scripting.filesystemobject")
Set objTF = objFSO.CreateTextFile(strPath)
objTF.WriteLine "Subject"
Set olApp = Outlook.Application
Set olNS = olApp.GetNamespace("MAPI")
Set olFolder = olNS.PickFolder
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olFolder2 = olFolder.Folders("removed items")
On Error GoTo 0
If olFolder2 Is Nothing Then Set olFolder2 = olFolder.Folders.Add("removed items")
For lngCnt = olFolder.Items.Count To 1 Step -1
Set objItem = olFolder.Items(lngCnt)
strCheck = objItem.Subject & "," & objItem.Body & ","
strCheck = Replace(strCheck, ", ", Chr(32))
If objDic.Exists(strCheck) Then
objItem.Move olFolder2
objTF.WriteLine Replace(objItem.Subject, ", ", Chr(32))
Else
objDic.Add strCheck, True
End If
Next
If objTF.Line > 2 Then
MsgBox "duplicate items were removed to ""removed items""", vbCritical, "See " & strPath & " for details"
Else
MsgBox "No duplicates found"
End If
End Sub
Here's a script that takes advantage of sorting emails to check for duplicates much more efficiently.
There's no need to maintain a giant dictionary of every email you've seen if you are processing emails in a deterministic order (e.g. received date). Once the date changes, you know you'll never see another email with the prior date, therefore, they won't be duplicates, so you can clear your dictionary on each date change.
This script also takes into account the fact that some items use an HTMLBody for the full message definition, and others don't have that property.
Sub DeleteDuplicateEmails()
Dim allMails As Outlook.Items
Dim objMail As Object, objDic As Object, objLastMail As Object
Dim olFolder As Folder, olDuplicatesFolder As Folder
Dim strCheck As String
Dim received As Date, lastReceived As Date
Set objDic = CreateObject("scripting.dictionary")
With Outlook.Application.GetNamespace("MAPI")
Set olFolder = .PickFolder
End With
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olDuplicatesFolder = olFolder.Folders("Duplicates")
On Error GoTo 0
If olDuplicatesFolder Is Nothing Then Set olDuplicatesFolder = olFolder.Folders.Add("Duplicates")
Debug.Print "Sorting " & olFolder.Name & " by ReceivedTime..."
Set allMails = olFolder.Items
allMails.Sort "[ReceivedTime]", True
Dim totalCount As Long, index As Long
totalCount = allMails.count
Debug.Print totalCount & " Items to Process..."
lastReceived = "1/1/1987"
For index = totalCount - 1 To 1 Step -1
Set objMail = allMails(index)
received = objMail.ReceivedTime
If received < lastReceived Then
Debug.Print "Error: Expected emails to be in order of date recieved. Previous mail was " & lastReceived _
& " current is " & received
Exit Sub
ElseIf received = lastReceived Then
' Might be a duplicate track mail contents until this recieved time changes.
' Add the last mail to the dictionary if it hasn't been tracked yet
If Not objLastMail Is Nothing Then
Debug.Print "Found multiple emais recieved at " & lastReceived & ", checking for duplicates..."
objDic.Add GetMailKey(objLastMail), True
End If
' Now check the current mail item to see if it's a duplicate
strCheck = GetMailKey(objMail)
If objDic.Exists(strCheck) Then
Debug.Print "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
objMail.Move olDuplicatesFolder
DoEvents
Else
objDic.Add strCheck, True
End If
' No need to track the last mail, since we have it in the dictionary
Set objLastMail = Nothing
Else
' This can't be a duplicate, it has a different date, reset our dictionary
objDic.RemoveAll
lastReceived = received
' Keep track of this mail in case we end up needing to build a dictionary
Set objLastMail = objMail
End If
' Progress update
If index Mod 10 = 0 Then
Debug.Print index & " Remaining..."
End If
DoEvents
Next
Debug.Print "Finished moving Duplicate Emails"
End Sub
And the helper function referenced above for "uniquely identifying" an email. Adapt as needed, but I think if the subject and full body are the same, there's no point in checking anything else. Also works for calendar invites, etc.:
Function GetMailKey(ByRef objMail As Object) As String
On Error GoTo NoHTML
GetMailKey = objMail.Subject & objMail.HTMLBody
Exit Function
BodyKey:
On Error GoTo 0
GetMailKey = objMail.Subject & objMail.Body
Exit Function
NoHTML:
Err.Clear
Resume BodyKey
End Function
I've wrote a VBA script called "Outlook Duplicated Items Remover"
The source code is available on GitHub
It will find all duplicated items in a folder and its subfolders and move them to a dedicated folder
I simplified the duplicate search as in my case I imported multiple duplicates from PST files but the full mail body didn't match. I don't know why, as I am sure those mail are true duplicates.
My simplification is to match ONLY the receive TIME STAMP and the SUBJECT.
I added an error exception for an error I got some times on the function: Set olDuplicatesFolder = olFolder.Folders("Duplicates").
I did a different format for the debug.print messages.
Attribute VB_Name = "DelDupEmails_DATE_SUBJECT"
Sub DeleteDuplicateEmails_DATE_SUBJECT()
Dim allMails As Outlook.Items
Dim objMail As Object, objDic As Object, objLastMail As Object
Dim olFolder As Folder, olDuplicatesFolder As Folder
Dim strCheck As String
Dim received As Date, lastReceived As Date
Set objDic = CreateObject("scripting.dictionary")
With Outlook.Application.GetNamespace("MAPI")
Set olFolder = .PickFolder
End With
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olDuplicatesFolder = olFolder.Folders("Duplicates")
On Error GoTo 0
If olDuplicatesFolder Is Nothing Then Set olDuplicatesFolder = olFolder.Folders.Add("Duplicates")
Debug.Print "Sorting " & olFolder.Name & " by ReceivedTime..."
Set allMails = olFolder.Items
allMails.Sort "[ReceivedTime]", True
Dim totalCount As Long, index As Long
totalCount = allMails.Count
Debug.Print totalCount & " Items to Process..."
'MsgBox totalCount & " Items to Process..."
lastReceived = "1/1/1987"
For index = totalCount - 1 To 1 Step -1
Set objMail = allMails(index)
On Error Resume Next
received = objMail.ReceivedTime
On Error GoTo 0
If received < lastReceived Then
Debug.Print "Error: Expected emails to be in order of date recieved. Previous mail was " & lastReceived _
& " current is " & received
Exit Sub
ElseIf received = lastReceived Then
' Might be a duplicate track mail contents until this recieved time changes.
' Add the last mail to the dictionary if it hasn't been tracked yet
If Not objLastMail Is Nothing Then
Debug.Print olFolder & " : Found multiple emails recieved at " & lastReceived & ", checking for duplicates..."
'MsgBox "Found multiple emails recieved at " & lastReceived & ", checking for duplicates..."
objDic.Add GetMailKey(objLastMail), True
End If
' Now check the current mail item to see if it's a duplicate
strCheck = GetMailKey(objMail)
If objDic.Exists(strCheck) Then
Debug.Print "#" & index & " - Duplicate: " & lastReceived & " " & objMail.Subject
'Debug.Print "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
'MsgBox "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
objMail.Move olDuplicatesFolder
DoEvents
Else
objDic.Add strCheck, True
End If
' No need to track the last mail, since we have it in the dictionary
Set objLastMail = Nothing
Else
' This can't be a duplicate, it has a different date, reset our dictionary
objDic.RemoveAll
lastReceived = received
' Keep track of this mail in case we end up needing to build a dictionary
Set objLastMail = objMail
End If
' Progress update
If index Mod 100 = 0 Then
Debug.Print index & " Remaining... from " & olFolder
'MsgBox index & " Remaining..."
End If
DoEvents
Next
Debug.Print "Finished moving Duplicate Emails"
MsgBox "Finished moving Duplicate Emails"
End Sub
Function GetMailKey(ByRef objMail As Object) As String
On Error GoTo NoHTML
'GetMailKey = objMail.Subject & objMail.HTMLBody
GetMailKey = objMail.Subject ' & objMail.HTMLBody
Exit Function
BodyKey:
On Error GoTo 0
'GetMailKey = objMail.Subject & objMail.Body
GetMailKey = objMail.Subject ' & objMail.Body
Exit Function
NoHTML:
Err.Clear
Resume BodyKey
End Function

Application-Defined or Object-Defined Error Using Access

I'm trying to send automated emails through outlook from Access, but I've run into an issue where if a user does not have their email open already, I will get the Application-Defined or Object-Defined Error. I'm using a late binding to avoid the .dll's since I have users on both Office 2003 and Office 2010.
Is there anyway around this error and still allowing the emails to go through? Or possibly "forcing" outlook to open if it is not already?
Thanks in advance
Sure thing, here's the whole code to the email.
When I step through it fails at Set appOutlookRec = .Recipients.Add(myR!Email)
Option Explicit
Function SendEmail(strDep, strIssue, strPriority, strDate, strDesc, wonum, user)
Const olMailItem = 0
Const olTo = 1
Const olCC = 2
Dim sqlVar As String
Dim strSQL As String
If strDep = "Cycle" Then
ElseIf strDep = "Fabrication" Then
sqlVar = "Fabricator"
ElseIf strDep = "Facility" Then
sqlVar = "Facility"
ElseIf strDep = "Gage" Then
sqlVar = "Gage"
ElseIf strDep = "IT" Then
sqlVar = "IT"
ElseIf strDep = "Machine Shop" Then
sqlVar = "Machine_Shop_Manager"
ElseIf strDep = "Safety" Then
sqlVar = "Safety"
ElseIf strDep = "Maintenance" Then
sqlVar = "Maintenance_Manager"
ElseIf strDep = "Supplies Request" Then
sqlVar = "Supplies"
Else:
End If
Dim myR As Recordset
'Refers to Outlook's Application object
Dim appOutlook As Object
'Refers to an Outlook email message
Dim appOutlookMsg As Object
'Refers to an Outlook email recipient
Dim appOutlookRec As Object
'Create an Outlook session in the background
Set appOutlook = CreateObject("Outlook.Application")
'Create a new empty email message
Set appOutlookMsg = appOutlook.CreateItem(olMailItem)
'Using the new, empty message...
With appOutlookMsg
strSQL = "SELECT Email FROM Employees WHERE " & sqlVar & " = True"
Set myR = CurrentDb.OpenRecordset(strSQL)
Do While Not myR.EOF
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olTo
myR.MoveNext
Loop
strSQL = "SELECT Email FROM Employees WHERE '" & user & "' = Username"
Set myR = CurrentDb.OpenRecordset(strSQL)
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olCC
.Subject = wonum
.Body = "Department: " & strDep & vbNewLine & vbNewLine & _
"Issue is at: " & strIssue & vbNewLine & vbNewLine & _
"Priority is: " & strPriority & vbNewLine & vbNewLine & _
"Complete by: " & strDate & vbNewLine & vbNewLine & _
"Description: " & strDesc
.Send
End With
Set myR = Nothing
Set appOutlookMsg = Nothing
Set appOutlook = Nothing
Set appOutlookRec = Nothing
End Function
Try using .Save before .Send. I was scheduling outlook code through MS Access.
After the line Set appOutlook = CreateObject("Outlook.Application"), add the following:
set NS = appOutlook.GetNamespace("MAPI")
NS.Logon
So what appears to be happening is your reference to the Outlook.Application is- well. stagnant- for lack of a better word. You don't just want to create an Outlook Session - you want to connect to an existing running application.
I'm not a pro on Access, so I'll just suggest generalities: Try to Obtain a handle on an already running Outlook Application, otherwise have it open Outlook (Give it time to fully startup using sleep/wait and a DoEvents command) and try again to obtain that handle.
I was using VBA within Outlook attempting to read the sender names (also getting the same error). Traced it down to my method of obtaining the current outlook application handle.
Instead of:
Set appOutlook = CreateObject("Outlook.Application");
I had to:
Set appOutlook = ThisOutlookSession;
Hope this helps!