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!
Related
I have over 200 emails to send with individual attachments.
The list is in Excel.
With code from elsewhere, I managed to open an email, with the attachment, email address, subject and body text.
I want the loop to pause once the email has been opened, so I can check the details, add in a signature etc. I then want the loop to move on to the next iteration but not until I click "Send".
Also, more minor point, but vbNewLine doesn't seem to create a new line?
Sub SendEmail_Example1()
Dim EmailApp As Outlook.Application
Dim Source As String
Dim Attachment As String
Dim edress As String
Set EmailApp = New Outlook.Application
Dim EmailItem As Outlook.MailItem
Set EmailItem = EmailApp.CreateItem(olMailItem)
i = 2
Do Until IsEmpty(Cells(i, 1))
Attachment = "C:\Users\username\Downloads\" + Cells(i, 4)
edress = Cells(i, 1)
EmailItem.To = edress
EmailItem.Subject = "Test Email From Excel VBA"
EmailItem.HTMLBody = "Hi," & vbNewLine & vbNewLine & _
"This is my first email from Excel" & _
vbNewLine & vbNewLine & _
"Regards," & vbNewLine & _
"VBA Coder"
Source = ThisWorkbook.FullName
EmailItem.Attachments.Add (Attachment)
EmailItem.Display
i = i + 1
Loop
Set EmailApp = Nothing
Set EmailItem = Nothing
End Sub
It's been 15 years since I tried this, but try the modal property on the EmailItem.Display method
https://learn.microsoft.com/en-us/office/vba/api/outlook.mailitem.display
I need my Access Database to create emails that are sent at the press of a button.
This works for Outlook, and I adapted the code for Gmail.
I don't want to hardcode the email username and password. I want to pick it up from a combobox on the main form.
I get the error
Private Sub Email_Allocation_List_Click()
Dim newMail As CDO.Message
Dim mailConfiguration As CDO.Configuration
Dim fields As Variant
Dim msConfigURL As String
On Error GoTo errHandle
Set newMail = New CDO.Message
Set mailConfiguration = New CDO.Configuration
mailConfiguration.Load -1
Set fields = mailConfiguration.fields
With newMail
.Subject = "subject"
.From = [Forms]![Main form]![EmailAddress].Column(1)
.To = "email address"
.CC = "email address"
.BCC = ""
.TextBody = "Hello, " & vbNewLine & vbNewLine & _
"Please find attached todays list of lines to be allocated." & _
vbNewLine & vbNewLine & "Kind Regards." & vbNewLine & vbNewLine & "Carly"
.AddAttachment "file location"
End With
msConfigURL = "http://schemas.microsoft.com/cdo/configuration"
With fields
.Item(msConfigURL & "/smtpusessl") = True
.Item(msConfigURL & "/smtpauthenticate") = 1
.Item(msConfigURL & "/smtpserver") = "smtp.gmail.com"
.Item(msConfigURL & "/smtpserverport") = 465
.Item(msConfigURL & "/sendusing") = 2
.Item(msConfigURL & "/sendusername") = [Forms]![Main form]![EmailAddress].Column(1)
.Item(msConfigURL & "/sendpassword") = [Forms]![Main form]![EmailAddress].Column(2)
.Update
End With
newMail.Configuration = mailConfiguration
newMail.Send
MsgBox "E-Mail has been sent", vbInformation
exit_line:
'// Release object memory
Set newMail = Nothing
Set mailConfiguration = Nothing
Exit Sub
errHandle:
MsgBox "Error: " & Err.Description, vbInformation
GoTo exit_line
End Sub
I checked the comboboxes work with a text box.
After a lot of messing around, you are correct, the code is fine - and it was reading the contents of the combo box correctly - however GMail didn't accept the log in information if there was a capital letter on the email address!!! Now working beautifully.
For some reason, I can't get the selected item which would be an email from my inbox to attach as an attachment when I create a new mail from my macro. I'm using Windows 10 / Outlook 2016. I had this working in Windows 7 Office 2010, but I'm not sure why it's not working now. Any help would be greatly appreciated.
Sub SendEmail()
Dim Inbox As Object
Dim MyItem As Object
Dim AddEmail As Boolean
Dim i As Long
Dim iAnswer As VbMsgBoxResult
'Check if User wants to copy an existing email to new form
iAnswer = MsgBox(Prompt:=" Do you want to copy the selected email to new form? (If you select YES, Keep the current email selected - DO NOT SELECT ANOTHER EMAIL - Until you finish sending)", _
Buttons:=vbYesNo, Title:="Copy Selected Email")
If iAnswer = vbYes Then
AddEmail = True
End If
'Check Version of Outlook (2007 vs 2010)
If Outlook.Application.Version = "12.0.0.6680" Then
On Error GoTo FolderError:
Set Inbox = Outlook.Application.GetNamespace("MAPI").Folders("Mailbox - #Incoming_Workshare")
On Error Resume Next
Else
On Error GoTo FolderError:
Set Inbox = Outlook.Application.GetNamespace("MAPI").Folders("#Incoming_Workshare")
On Error Resume Next
End If
'Open Form From Folder (The Inbox =)
Set MyItem = Inbox.Items.Add("IPM.Note.Workflow Sharing 2016")
MyItem.Display
MyItem.Subject = "Automatically Generated Based on Job Information"
'Check Version of VBA and Form to make sure you are using latest macro
If Not MyItem.Mileage = 11 Then
'Check if User wants to copy an existing email to new form
iAnswer = MsgBox(Prompt:="ALERT - Macro has been updated - Select Yes to Update" & vbCrLf & "(Note: Outlook will be restarted)", _
Buttons:=vbYesNo, Title:="Automatic Macro Update")
If iAnswer = vbYes Then
Shell "wscript C:\Macro\UpdateOutlookMacro.vbs", vbNormalFocus
End If
End If
'Copy Selected Emails to New Email if you selected Yes
If AddEmail = True Then
'Check if a there is a reference to the long access time projects in the subject or body to add instructions to also send as attachment (LARGE PROJECTS)
If InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "TUCAN") > 0 Or _
InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "RUDY") > 0 Or _
InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "SARGENT") > 0 Then
MyItem.HTMLBody = "<b>Additional Instructions from Originating Location:</b>" & Chr(11) & "PLEASE SEND BACK HYPERLINKS AND ATTACHMENTS FOR ALL EDITED FILES" & Chr(11) & Chr(11) & Chr(11) & Chr(11) & "---------------------------------------------" & Chr(11) & "Original Banker Email:" & Chr(11)
Else
MyItem.HTMLBody = "<b>Additional Instructions from Originating Location:</b>" & Chr(11) & Chr(11) & Chr(11) & Chr(11) & Chr(11) & "---------------------------------------------" & Chr(11) & "Original Banker Email:" & Chr(11)
End If
MyItem.BodyFormat = olFormatRichText
'Check large job 15MB
If (ActiveExplorer().Selection.Item(1).Size >= 15728640) Then
MsgBox "Alert! The attached original email size is " & Format(ActiveExplorer().Selection.Item(1).Size / 1048576, 0#) & " MBs. There are errors when sending large emails. Please save attachments as links to reduce the filesize.", , Title:="Email Size Too Big"
End If
MyItem.Attachments.Add ActiveExplorer().Selection.Item(1)
'Check if Sender is an autoforward from a mailbox, alerting to be manually updated
MyItem.UserProperties("Clocker") = ActiveExplorer().Selection.Item(1).SenderName + "; " + ActiveExplorer().Selection.Item(1).CC
If MyItem.UserProperties("Clocker") = "OH Mail; " Or MyItem.UserProperties("Clocker") = "NO Mail; " Or MyItem.UserProperties("Clocker") = "LAV Mail; " Or MyItem.UserProperties("Clocker") = "OK Mail; " Or MyItem.UserProperties("Clocker") = "WY Mail; " Then
'MsgBox "Alert! Please populate the Requestor/Clocker field. It cannot be listed as the Advisory Presentation Mailbox"
'MyItem.UserProperties("Clocker") = "" ' Removed Q4
Dim CorrectedClocker1, CorrectedClocker2, CorrectedClocker3 As String
Correctedclocker1 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "From:", "Sent:"))
If InStr(ActiveExplorer().Selection.Item(1).body, "Cc:") > 0 Then
CorrectedClocker2 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "To:", "Cc:"))
CorrectedClocker3 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "Cc:", "Subject:"))
Else
CorrectedClocker2 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "To:", "Subject:"))
CorrectedClocker3 = ""
End If
CorrectedClocker2 = Replace(CorrectedClocker2, "#Completed", "")
CorrectedClocker3 = Replace(CorrectedClocker3, "#Completed", "")
MyItem.UserProperties("Clocker") = CorrectedClocker1 & "; " & CorrectedClocker2 & "; " & CorrectedClocker3
Else
If InStr(MyItem.UserProperties("Clocker"), "[Cvcs]") > 0 Then
Is this running inside Outlook VBA?. Should Attachments.Add line be the following?
MyItem.Attachments.Add Outlook.Application.ActiveExplorer.Selection.Item(1)
Get rid of the "On Error Resume Next" statements - they are hiding runtime errors.
If you want to add a mailbox item as an attachment to a new message.
You need to set the Outlook.OlAttachmentType property to olEmbeddeditem.
You can add a mail item as an attachment by referring to the code below.
Sub ResolveName()
Dim myItem As Object
Dim Item As Object
Dim myFolder As Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderInbox)
Set myItem = Application.CreateItem(olMailItem)
Set Item = myFolder.Items(2)
'Item.Display
myItem.Attachments.Add Item, Outlook.OlAttachmentType.olEmbeddeditem, 1, "first"
myItem.Display
End Sub
I need to create outlook task from shared inbox. So far when below code runs, task is created with owner of shared inbox as I want, but when saved I get "You must be in a public folder to change the owner field of a task" error and owner is changed back to me.
I couldn't find solution or it might have been beyond my understanding. I appreciate the help. Thanks!
If task = "YES" Then
user_task = "GR"
Const olTaskItem = 3
Dim OlApp As Object
Dim OlTask As Object
Set OlApp = CreateObject("Outlook.Application")
Set OlTask = OlApp.CreateItem(olTaskItem)
With OlTask
'.Assign
'.Recipients.Add "shared#inbox.com" 'workaround to assign task for another owner, but does not show .BCC so not suitable solution.
.Owner = "shared#inbox.com" ' does not work. changes back to my user
.Subject = material_full_email & " spp "
.StartDate = Date
.DueDate = Date + 7
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.ReminderSet = False
'.ReminderTime = dtReminderDate
'.Categories = "Business" 'use any of the predefined Categorys or create your own
.Body = Date & " " & user_task & ":" & " RFQ sent: " & Supplier1 & " / " & Supplier2 & " / " & Supplier3 & " / " & Supplier4
'.Save 'use .Display if you wish the user to see the task form and make
.Display 'them perform the save
End With
End If
Instead of using Application.CreateItem, call Application.Session.CreateRecipient passing the name or address of the owner of the mailbox, call Application.Session.GetSharedDefaultFolder, then use MAPIFolder.Items.Add.
UPDATE:
Set OlApp = CreateObject("Outlook.Application")
set NS = olApp.getNamespace("MAPI")
NS.Logon
ste Recip = NS.CreateRecipient("someuser#company.demo")
set SharedFolder = NS.GetSharedDefaultFolder(Recip, olFoldersTasks)
Set OlTask = SharedFolder.Items.Add
...
I managed to get below code work. I believe biggest problem was MS Outlook library not ticked in references.
If task = "YES" Then
user_task = "GR"
Const olTaskItem = 3
Dim olApp As Object
Dim ns As Object
Dim OlTask As Object
Dim SharedFolder As Object
Set olApp = CreateObject("Outlook.Application")
Set ns = olApp.GetNamespace("MAPI")
ns.Logon
Set Recip = ns.CreateRecipient("inboxname")
Set SharedFolder = ns.GetSharedDefaultFolder(Recip, olFolderTasks)
Set OlTask = SharedFolder.Items.Add("IPM.Task")
'Set OLApp = CreateObject("Outlook.Application")
'Set OlTask = OLApp.CreateItem(olTaskItem)
With OlTask
'.Assign
'.Recipients.Add "shared#inbox.com"
'.Owner = "shared#inbox.com" ' not needed
.Subject = material_full_email & " spp "
.StartDate = Date
.DueDate = Date + 7
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.ReminderSet = False
'.ReminderTime = dtReminderDate
'.Categories = "Business" 'use any of the predefined Categorys or create your own
.Body = Date & " " & user_task & ":" & " RFQ sent to suppliers: " & Supplier1 & " / " & Supplier2 & " / " & Supplier3 & " / " & Supplier4
'.Save 'use .Display if you wish the user to see the task form and make
.Display 'them perform the save
End With
End If
I think that I have something more simple for this:
Dim objOLApp As Outlook.Application
Dim NewTask As Outlook.TaskItem
' Set the Application object
Set objOLApp = New Outlook.Application
Set NewTask = objOLApp.Session.Folders.Item(x).Items.Add(olTaskItem)
With NewTask...
Where 'x' stands for your shared inbox ID (for me this is 5). You can use MsgBox Prompt:=objOLApp.Session.Folders.Item(x) to check. It should return shared inbox adress on correct ID (adress#server.com).
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