Outlook has exhausted all shared resources. Why? - vba

With this bit of VBA code in MS Access I'm getting an error if its executed too often. The only way I've found to clear it is reboot my computer. Any idea why and what can I do?
Public Function HasOutlookAcct(strEmail As String) As Boolean
Dim OutMail As Object
Dim OutApp As OutLook.Application
Dim objNs As OutLook.NameSpace
Dim objAcc As Object
'https://stackoverflow.com/questions/67284852/outlook-vba-select-sender-account-when-new-email-is-created
Set OutApp = CreateObject("Outlook.Application")
Set objNs = OutApp.GetNamespace("MAPI")
For Each objAcc In objNs.Accounts
If objAcc.SmtpAddress = strEmail Then
HasOutlookAcct = True
Exit For
End If
Next
OutApp.Quit
Set objAcc = Nothing
Set objNs = Nothing
End Function

The code looks good. The NameSpace.Accounts property returns an Accounts collection object that represents all the Account objects in the current profile. I don't see any extensive or heavy usage of the Outlook object model, but creating a new Outlook Application instance in the method for checking whether a particular account is configured in Outlook or not is not the best way of using Outlook. Instead, I'd recommend running Outlook once at some point and getting all the configured emails for saving for future usage where necessary.
Also it makes sense to disable all COM add-ins to see whether it helps or not. The problem may be related to any specific COM add-in.

Appears the error is addressed by considering the user.
The assumption, based on my results, is Outlook is not cleaned up completely when the user's instance is closed with outApp.Quit.
When Outlook is open, outApp.Quit is not applied and Outlook remains open at the end.
When Outlook is not open, it is opened in the background and later closed with outApp.Quit.
There is zero or one instance of Outlook at any time.
Option Explicit
Public Function HasOutlookAcct(strEmail As String) As Boolean
'Reference Outlook nn.n Object Library
' Consistent early binding
Dim outApp As Outlook.Application
Dim objNs As Outlook.Namespace
Dim objAcc As Outlook.Account
Dim bCreated As Boolean
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
bCreated = True
Set outApp = CreateObject("Outlook.Application")
End If
Set objNs = outApp.GetNamespace("MAPI")
For Each objAcc In objNs.Accounts
'Debug.Print objAcc.SmtpAddress
If objAcc.SmtpAddress = strEmail Then
HasOutlookAcct = True
Exit For
End If
'Set objAcc = Nothing ' Additional cleanup if needed
Next
If bCreated = True Then ' Outlook object had to be created
outApp.Quit
End If
'Set outApp = Nothing ' Additional cleanup if needed
Set objNs = Nothing
End Function
Private Sub HasOutlookAcct_Test()
Dim x As Boolean
Dim sEmail As String
sEmail = "someone#somewhere.com"
Dim i As Long
For i = 1 To 50
Debug.Print i & ": " & sEmail
x = HasOutlookAcct(sEmail)
Debug.Print " HasOutlookAcct: " & x
DoEvents
Next
Debug.Print "done"
End Sub

Related

SendUsingAccount SendAs permissions but not finding in index

I need to be able to send an email from VBA from a different email address. I have permissions to send from that address and can select it manually from the Outlook Message window. However, there is no index to it when I run the following code. All that shows up is my email address.
Sub Which_Account_Number()
'Don't forget to set a reference to Outlook in the VBA editor
Dim OutApp As Object
Dim I As Long
Set OutApp = CreateObject("Outlook.Application")
For I = 1 To OutApp.Session.Accounts.Count
MsgBox OutApp.Session.Accounts.Item(I) & " : This is account number " & I
Next I
End Sub
Is there a way to use the actual email address in the call? This is my test code for what I am trying to accomplish:
Sub SendMessagesTest()
Dim objOutlook As Object ' Outlook.Application
Dim objOutlookMsg As Object ' Outlook.MailItem
Dim objOutlookRecip As Object ' Outlook.Recipient
' Create the Outlook session.
Set objOutlook = CreateObject("Outlook.Application")
objOutlook.Session.Logon
' Create the message.
Set objOutlookMsg = objOutlook.CreateItem(0) '0 = olMailItem
With objOutlookMsg
' Set the Subject & Body of the message.
.Subject = "Test Subject"
.Body = "Test Body"
'.BodyFormat = 3 '3 = olFormatRichText (Late Binding)
'Change Item(1)to another number to use another account
Set .SendUsingAccount = "TestUser#test.com" 'objOutlook.Session.Accounts.Item(2) ' (Late Binding)
.Display
End With
Set objOutlook = Nothing
Set objOutlookMsg = Nothing
Set objOutlookRecip = Nothing
Exit Sub
End Sub
When I run it I get the error "Object Required".
I cannot use this type of code because I do not have an index number to use for the email address:
Set .SendUsingAccount = objOutlook.Session.Accounts.Item(1)
Edit: This is the code that I use to add an appointment item to another user's calendars which have been shared with me. Note: I have Publishing Editor permissions on the mailbox I am trying to Send As.
Sub CreateCalendarApptx()
Dim objApp As Object
Dim objNS As Object
Dim objFolder As Object
Dim objRecip As Object
Dim objAppt As Object
Dim objMsg As Object
Const olMailItem = 0
Const olFolderCalendar = 9
Dim strName As String
Set objApp = CreateObject("Outlook.Application")
Set objNS = objApp.getNamespace("MAPI")
Set objMsg = objApp.CreateItem(olMailItem)
strName = "OtherUser#Test.com"
'Select Calendar on which to place the appointment
'The Calendar can either be set with the name of the calendar or the Folder ID
If Left(strName, 3) = "ID:" Then
'Strip out the ID: identifier and leave just the ID
strName = Mid(strName, 5, Len(strName))
Set objFolder = objNS.GetFolderFromID(strName)
Else
Set objRecip = objMsg.Recipients.Add(strName)
objRecip.Resolve
If objRecip.Resolved Then
Set objFolder = objNS.GetSharedDefaultFolder(objRecip, olFolderCalendar)
End If
End If
Set objAppt = objFolder.Items.Add
objAppt.Subject = "Test"
objAppt.Display
Set objApp = Nothing
Set objNS = Nothing
Set objFolder = Nothing
Set objMsg = Nothing
Set objRecip = Nothing
Set objAppt = Nothing
End Sub
Edit 2:
I added another comment earlier, but the board didn't seem to like it because I attached a picture. The upshot is that when I send an email from the Outlook interface with a different name in the From: field, it sends successfully. However, when I hover over it I see "From: OtherUser#test.com Send Using Account: Me#test.com" If that is the case, the SendUsingAccount in VBA would be my email address, and there should be another property that would be the From: field.
change your statement from:
Set .SendUsingAccount = objOutlook.Session.Accounts.Item(1)
to:
Set .SendUsingAccount = objOutlook.Session.Accounts.Item("Testuser#test.com")
I was able to get SendUsingAccount to work -- except that items sat in the other account's Outbox and never were sent.
I finally got it to work by creating a mail profile that had the account I wanted to send as from as the only account. Then I added my mail account but left the SendUsingAccount as the default account for the profile to use. That way it continued to work.
But that's a bit inconvenient, except in my case the computer running the software is not my primary computer, so having the default profile set to a mail account other than mine will be bearable.
Are you sending on behalf of a delegate Exchange mailbox? Set the MailItem.SentOnBehalfOfName property.
Re: Comment to other answer post. It is unusual to do this "I can set appointments on other people's calendars from VBA".
If you have such rights, to the inbox of the other mailbox, you may be able to do this.
Option Explicit
Sub SendMailFromNonDefaultAccount()
' The only way I know this works is to
' use the "Add Account" button to add a non-default account.
' Not "Account Settings" which adds a mailbox to the default Account.
Dim myRecipient As recipient
Dim nonDefaultInboxFolder As Folder
Dim addMail As MailItem
' This is where your unusual permission, without adding an account, might yet kick in
Set myRecipient = Session.CreateRecipient("non-default email address as a string inside quotes")
Set nonDefaultInboxFolder = Session.GetSharedDefaultFolder(myRecipient, olFolderInbox)
' Add, not create, in non-default folder
Set addMail = nonDefaultInboxFolder.Items.Add
' The non-default email address will be in the "From"
addMail.Display
End Sub
With the code for the shared calendar applied to the shared inbox.
Option Explicit
Sub CreateCalendarAppt_and_mail()
Dim objApp As Object
Dim objNS As Object
Dim objFolder As Object
Dim objRecip As Object
Dim objAppt As Object
Dim objMsg As Object
Dim objInboxShared As Object
Dim objMsgShared As Object
' If there is no reference to the Outlook Object Library
Const olFolderInbox = 6
Const olMailItem = 0
Const olFolderCalendar = 9
Dim strName As String
Set objApp = CreateObject("Outlook.Application")
Set objNS = objApp.GetNamespace("MAPI")
Set objMsg = objApp.CreateItem(olMailItem)
strName = "OtherUser#Test.com"
Debug.Print strName
Set objRecip = objMsg.Recipients.Add(strName)
objRecip.Resolve
If objRecip.Resolved Then
Set objFolder = objNS.GetSharedDefaultFolder(objRecip, olFolderCalendar)
Set objAppt = objFolder.Items.Add
objAppt.Subject = "Test"
objAppt.Display
' Follows the format of the calendar code
' Looks the same as my original code
Set objInboxShared = objNS.GetSharedDefaultFolder(objRecip, olFolderInbox)
' objInboxShared.Display
Set objMsgShared = objInboxShared.Items.Add
objMsgShared.Subject = "Test Message"
objMsgShared.Display
End If
Set objApp = Nothing
Set objNS = Nothing
Set objFolder = Nothing
Set objMsg = Nothing
Set objRecip = Nothing
Set objAppt = Nothing
Set objInboxShared = Nothing
Set objMsgShared = Nothing
End Sub
I had two machines that were experiencing this same problem.
With the first machine, the user was being prompted to select a profile on opening Outlook. By setting the Control Panel/Mail profile setting so that it "Always use this profile", the problem was fixed.
The second machone had two profiles. Even though the main one was selected to "always use this profile", it still had the same problem. By removing the second profile, the problem went away.

Outlook VBA to save sent meeting requests/replies to a specified folder

I found the code below (here) to get outlook VBA to save sent email to a specified folder.
The code works well, however, any time that it runs on a sent meeting request or meeting reply, it errors.
I have been able to identify line 9 as the line where the error occurs:
Set Item.SaveSentMessageFolder = objFolder
My assumption, then, is that the Item.SaveSentMessageFolder code is incompatible with meeting-type objects. However, I am uncertain as to what the equivalent coding would be for meeting-type objects.
Can this code be modified to handle meeting-type objects in the same fashion that message-type objects are handled?
Private Sub Application_ItemSend(ByVal Item As Object, _
Cancel As Boolean)
Dim objNS As NameSpace
Dim objFolder As MAPIFolder
Set objNS = Application.GetNamespace("MAPI")
Set objFolder = objNS.PickFolder
If TypeName(objFolder) <> "Nothing" And _
IsInDefaultStore(objFolder) Then
Set Item.SaveSentMessageFolder = objFolder
End If
Set objFolder = Nothing
Set objNS = Nothing
End Sub
Public Function IsInDefaultStore(objOL As Object) As Boolean
Dim objApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objInbox As Outlook.MAPIFolder
On Error Resume Next
Set objApp = CreateObject("Outlook.Application")
Set objNS = objApp.GetNamespace("MAPI")
Set objInbox = objNS.GetDefaultFolder(olFolderInbox)
Select Case objOL.Class
Case olFolder
If objOL.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
End If
Case olAppointment, olContact, olDistributionList, _
olJournal, olMail, olNote, olPost, olTask
If objOL.Parent.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
End If
Case Else
MsgBox "This function isn't designed to work " & _
"with " & TypeName(objOL) & _
" items and will return False.", _
, "IsInDefaultStore"
End Select
Set objApp = Nothing
Set objNS = Nothing
Set objInbox = Nothing
End Function
At least one other person has found the property to be ineffective for meeting items.
https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/meetingitem-savesentmessagefolder-property-outlook
"Setting or getting this property has no noticeable effect. Do not use this property."
Try monitoring the Sent Items folder.
Place this code in the ThisOutlookSession module.
Private WithEvents sentMailItems As items
Private Sub Application_Startup()
Set sentMailItems = Session.GetDefaultFolder(olFolderSentMail).items
End Sub
Private Sub sentMailItems_ItemAdd(ByVal Item As Object)
Dim objFolder As Folder
If TypeOf Item Is MeetingItem Then
Set objFolder = Session.PickFolder
If TypeName(objFolder) <> "Nothing" Then
Item.Move objFolder
End If
End If
Set objFolder = Nothing
End Sub

Open Outlook using VBA in MS Access

I am trying to open Outlook when a button is clicked in MS Access, I have the following code which I have gathered online and after tinkering with it it is still not working. Here is my code:
Private Sub Command56_Click()
Dim obj
On Error Resume Next
Set obj = GetObject(, "Outlook.Application")
On Error GoTo 0
If obj Is Nothing Then Set obj = CreateObject("Outlook.Application")
End Sub
Does anyone have any suggestions?
No need to call GetObject. If Outlook is loaded, it will create a reference to it and if not, it will be loaded. It will not create a new instance though.
Private Sub Command56_Click()
Dim obj As Object
Set obj = CreateObject("Outlook.Application")
obj.Visible = True
'do work
obj.Quit '<-- This will close Outlook
Set obj = Nothing
End Sub
I have been using this procedure:
Private Sub OpenOutlook(emailAddress As String)
Dim objOutlook As Outlook.Application
Dim objOutlookMsg As Outlook.MailItem
Dim objOutlookRecip As Outlook.Recipient
Dim objOutlookAttach As Outlook.Attachment
' Create the Outlook session.
Set objOutlook = CreateObject("Outlook.Application")
' Create the message.
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)
With objOutlookMsg
' Set the Subject, Body, and Importance of the message.
.Subject = "ISF"
.Body = "This is the body of the message." & vbCrLf & vbCrLf
.Recipients.Add (emailAddress)
' Add attachments to the message.
Set objOutlookAttach = .Attachments.Add("\\sql\images\" & Forms![WebQADocumentReview].FileName)
.Display
End With
Set objOutlook = Nothing
End Sub
But you can’t use similar code with Outlook due to how Outlook opens which is quite different from other Office products. Sometimes it is important to know that Outlook is open, for example to be sure that your mails created with VBA code are sent and not waiting in your outbox.
The code below is created by MVP Ben Clothier and can either retrieve an open instance of Outlook or open Outlook if it is closed. This uses a ‘self-healing object’ approach for returning an instance of Outlook.
https://www.rondebruin.nl/win/s1/outlook/openclose.htm
Add this to the Declarations
Dim g_olApp As Object
Create the below Subroutine
Private Sub fireOutlook()
Dim olShellVal As Long
On Error GoTo FIREOUTLOOK_ERR
Set g_olApp = GetObject(, "Outlook.Application") ' If outlook is open will create obj
' If closed this will goto the error handler and then resume
If g_olApp Is Nothing Then ' This checks if object was created
olShellVal = Shell("OUTLOOK", vbNormalNoFocus) ' Opens Outlook
Set g_olApp = CreateObject("Outlook.Application") ' Creates the Object
End If
FIREOUTLOOK_EXIT:
Exit Sub
FIREOUTLOOK_ERR:
If g_olApp Is Nothing Then
Err.Clear
Resume Next
Else
MsgBox Err.Description, , "Error Number: " & Err.Number
End If
GoTo FIREOUTLOOK_EXIT
End Sub
Once this is complete the global object can be used in any code involving outlook just make sure to call the fireOutlook subroutine first.

Inserting text into incoming email Outlook 2013 locked read only

I'm struggling to insert a string in an incoming email via VBA. The routine works fine when sending mail and it will work on incoming mail if the user clicks Actions Edit. The issue is that incoming mail is locked in read only mode. I've spent the past 13.5 hours searching everywhere. It is possible in earlier versions of Outlook, however Microsoft have removed the CommandBar functionality in Office 2013. Basically I need a way to allow the mail to be editable via a setting in VBA.
Here is the routine
Sub StampReference()
Dim objOL As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objDoc As Word.Document
Dim objSel As Word.Selection
strFullReference = "Reference: " & Reference
On Error Resume Next
Set objOL = Application
If objOL.ActiveInspector.EditorType = olEditorWord Then
Set objDoc = objOL.ActiveInspector.WordEditor
Set objNS = objOL.Session
Set objSel = objDoc.Windows(1).Selection
objSel.Move wdStory, -1
objDoc.Characters(1).InsertBefore _
strFullReference & vbCrLf & vbCrLf
objSel.Move wdParagraph, 1
End If
Set objOL = Nothing
Set objNS = Nothing
End Sub
EDIT
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
user2970334

Late Binding to Open Outlook from Access

I'm trying to open the Outlook application from Access VBA when the switchboard loads. I've opened task manager and I can see an instance of Outlook appear for about 5 seconds then close, but I can't get the explorer window to open. I've been trying to piece together code from VBA: Determining whether an existing Outlook instance is open and other sources, but it's just not working. Any ideas?
And I would like to stick with late bindings so I don't have to worry about object libraries if someone opens with XP.
Function OpenEmail()
Dim olApp As Object ' Outlook.Application
Dim olFolderInbox As Object
Dim objExplorer As Object
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If olApp Is Nothing Then
MsgBox "Outlook is not Open"
Set olApp = CreateObject("Outlook.Application")
End If
Set objExplorer = CreateObject("Outlook.MAPIFolder")
Set objExplorer = olApp.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
objExplorer.Activate
'Set olApp = Nothing
End Function
Outlook is the only MS Office application where GetObject does the same thing as CreateObject. Unlike other MS Office application, CreateObject doesn't create multiple instances of Outlook.
Also olFolderInbox is an outlook constant. You will have to define it in ACCESS.
Try this
Const olFolderInbox As Long = 6
Sub Sample()
Dim olApp As Object
Dim objNS As Object
Dim olFolder As Object
Set olApp = CreateObject("Outlook.Application")
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
With olFolder
'~~> Do what you want
End With
End Sub