Sending Email using Access VBA - vba

I am attempting to send an email out of Access. The email is not automatically sent. I have to hit send on the email pop up.
Is there something missing in my code that is preventing the email from sending.
Dim strTo As String
Dim strMessage As String
Dim strSubject As String
strTo = "Hazat.Bangurah#umm.edu"
strSubject = "New Lab Charge Codes"
strMessage = "Attached are the New Lab Charge Codes"
DoCmd.SendObject acSendQuery, "std qry_Master to HPM Lab Standard Compare", acFormatXLSX, strTo, , , strSubject, strMessage

DoCmd.SendObject will show a warning pop-up from outlook even if you use EditMessage := False. So you can apply workaround to avoid it. First save the query to you disk and add that file as attachment. This work around can be done programmatically. Try below codes to send mail without any warning pop-up but you must set Programmatic Access to Never warn me about suspicious activity. See this post from Microsoft Answer.
Private Sub CmdSendMail_Click()
Dim strTo As String
Dim strMessage As String
Dim strSubject As String
Dim attch As String
strTo = "Hazat.Bangurah#umm.edu"
attch = "D:\MyFile.xlsx"
strSubject = "New Lab Charge Codes"
strMessage = "Attached are the New Lab Charge Codes"
' Save file to disk.
DoCmd.OutputTo acOutputQuery, "Query1", acFormatXLSX, attch, False, , , acExportQualityPrint
Call SendEmailWithOutlook(strTo, strSubject, strMessage, attch)
End Sub
'======= Function to send email =======
Public Function SendEmailWithOutlook( _
MessageTo As String, _
Subject As String, _
MessageBody As String, strAttachment As String)
' Define app variable and get Outlook using the "New" keyword
Dim OutApp As Object
Dim OutMail As Object ' An Outlook Mail item
' Create a new email object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
' Add the To/Subject/Body to the message and display the message
With OutMail
.To = MessageTo
.Attachments.Add strAttachment
.Subject = Subject
.Body = MessageBody
.Send ' Send the message immediately
End With
' Release all object variables
Set OutApp = Nothing
Set OutMail = Nothing
End Function
To set Programmatic Access you must open outlook as Administrator. Then follow the screenshot below.

Related

ACCESS VBA to Send emails to addressees where an attached ACCESS PDF Report aligns that specific address

I've been putting this code together for a few days now with some success. My code will save pdf reports by project number so my battle is half won. The second part is where I am needing help getting each pdf report to automatically send to the project's email(Proj Mgr Emial) in the table.
tblEmailProjects
Additionally, while I can generate a single email (should be two) in the ".Display" mode, it attaches all the project's pdf reports instead of just the pdf report belonging to that recipient.
Single email generated by code
Finally, my variable strList causes an Runtime error "'-2147221238 The item has been moved or deleted" even tho it has been declared and set
I think/I hope I am close and would really appreciate any help...
Dim olApp As Object
Dim olMail As Object
Dim strExport As String
Dim strList As String
Set olApp = CreateObject("Outlook.Application")
Set olMail = olApp.CreateItem(olMailItem)
Dim rst As DAO.Recordset
'Public strRptFilter As String ' not need to use a public variable
Set rst = CurrentDb.OpenRecordset("SELECT DISTINCT [Proj_Nbr],[Project Mgr Emial] FROM [TblEmailProjects] ORDER BY [Proj_Nbr];", dbOpenSnapshot)
If rst.RecordCount > 0 Then ' make sure that we have data
rst.MoveFirst
Do While Not rst.EOF
strRptFilter = "[Proj_Nbr] = " & Chr(34) & rst![Proj_Nbr] & Chr(34)
DoCmd.OpenReport "rptProjCost", acViewPreview, , strRptFilter, acHidden ' open the report hidden in preview mode setting the where parameter
DoCmd.OutputTo acOutputReport, "rptProjCost", acFormatPDF, "C:\Users\Lisa Burns\Documents\AJI\Deploy DELPHI Projects\" & rst![Proj_Nbr] & ".pdf" ' save the opened report
DoCmd.Close acReport, "rptProjCost" ' close the report
strExport = "C:\Users\Lisa Burns\Documents\AJI\Deploy DELPHI Projects\" & rst![Proj_Nbr] & ".pdf"
strList = rst![Project Mgr Emial] ' ******ERRORS HERE WHEN ACTUALLY TRYING TO SEND EMAILS INSTEAD OF JUST DISPLAYING.&_
'WHEN DISPLAYING ONLY ONE EMAIL SHOWING LAST EMAIL ADDRESS IN THE RECORDsET*****
With olMail
.To = strList '******ERRORS HERE WHEN ACTUALLY TRYING TO SEND EMAILS INSTEAD OF JUST DISPLAYING
.CC = "" 'Change if you want a CC
.BCC = "" 'Change is you want a BCC
.Subject = "Project Costs for" & "rst![Proj_Nbr]" '****CODE DOES NOT CAPTURE PROJ_NBR...INCORRECT SYNTAX?"
.Body = "Attached, please find your project cost report for project number & rst![Proj_Nbr]." 'Change to what ever you want the body of the email to say
'Attaches the exported file using the variable created at beginning
.Attachments.Add strExport '*****ADDS ALL REPORTS INSTEAD OF FILTERING THE PDF REPORT THAT IS APPROPRIATE FOR THE RECIPIENT****
.Display 'Use for testing purposes only, note out for live runs '.Send 'Use for live purposes only.
End With
DoEvents
rst.MoveNext
Loop
End If ' rst.RecordCount > 0
'Frees email objects stored in memory
Set olMail = Nothing
Set olApp = Nothing
'stop added here
rst.Close
Set rst = Nothing
End Sub
What I will suggest you split your codes into two part. First part will saves pdf to your desired folder and second part will send mail to users with individual attachment. Below is code to send mail to individuals with separate pdf attachment. First test it from an command button then include these codes to your codes. It will be easier then to deploy.
Read this post.
I hope you are aware about Add References Microsoft Outlook x.xx Object Library.
Private Sub cmdSendMails_Click()
Dim oApp As New Outlook.Application
Dim oEmail As Outlook.MailItem
Dim strEmail As String, strAttachment As String
Dim mypath As String
mypath = "C:\Users\Lisa Burns\Documents\AJI\Deploy DELPHI Projects\" 'Change the path with your folder path
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb()
Set rs = db.OpenRecordset("SELECT DISTINCT [Proj_Nbr],[Project Mgr Emial] FROM [TblEmailProjects]", dbOpenSnapshot)
On Error Resume Next 'Suppress errors
Do While Not rs.EOF
strAttachment = mypath & rs![Proj_Nbr] & ".pdf" 'Pdf name exactly as employee ID.
strEmail = rs![Project Mgr Emial] 'Email address from table column.
Set oEmail = oApp.CreateItem(olMailItem)
With oEmail
.Recipients.Add strEmail 'Add email address
.Subject = "Your subject text here."
.Body = "Your body text here."
.Attachments.Add strAttachment 'Attach PDF file.
'.Send
.Display 'Use .send to send the mail. Display will show the email editor window.
End With
Set oEmail = Nothing
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub

Is there a way to create a new Outlook email from Access 2002 without using the SendObject command?

I have a client that is using Access 2002 because it allows Replication. He is using this on Windows 10 with Outlook from Office 365.
The goal is to create a new email with all of the info filled in and attach a scanned proposal so that my client can review the email, make any changes that he wants and then send it.
In Access, the SendObject command creates and opens a plain text email and while this email is open my Outlook macro to scan a document and attach it to the email will not run.
So I would like to create a new Outlook email from Access that allows me to run my Outlook macro.
Or if I could get Access 2002 to create an email and attach the scanned document to it, I think I could get by with using msgboxes to verify specific items.
Below is the Access macro with the SendObject command followed by the Outlook macro.
Private Sub EmailProposal_Click()
'Access macro.
Dim stDocName As String
Dim stEmailAddress As String
Dim stSubject As String
Dim stMessage As String
stDocName = "rptProposal"
stEmailAddress = Forms!RequestForm!EmailAddress.Value
stSubject = "PROPOSAL"
stMessage = "Your proposal is attached." & vbCrLf & vbCrLf & "If you have any questions, please call us."
'Email the proposal.
DoCmd.SendObject acReport, stDocName, acFormatRTF, stEmailAddress, , , stSubject, stMessage
End Sub
Sub Scan()
'Outlook macro.
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
On Error Resume Next
Dim objCommonDialog As WIA.CommonDialog
Dim objImage As WIA.ImageFile
Dim strPath As String
Set objCommonDialog = New WIA.CommonDialog
'This shows the dialog box. I'd rather tell it what to do instead of having to manually choose each time.
Set objImage = objCommonDialog.ShowAcquireImage
strPath = Environ("TEMP") & "\TempScan.jpg" 'Save the scan.
If Not objImage Is Nothing Then
objImage.SaveFile strPath ' save into temp file
On Error GoTo ErrHandler
If TypeName(ActiveWindow) = "Inspector" Then
If ActiveInspector.IsWordMail And ActiveInspector.EditorType = olEditorWord Then
ActiveInspector.WordEditor.Application.Selection.Inlineshapes.AddPicture strPath 'Insert into email. I want to attach it instead.
End If
End If
Kill strPath
Else
MsgBox "The Scan macro in Outlook did not find a document." & vbCrLf & vbCrLf & _
"Please place the proposal in the printer so it can be scanned.", vbOKOnly
End If
lbl_Exit:
Set objImage = Nothing
Set objCommonDialog = Nothing
Exit Sub
ErrHandler:
Beep
Resume lbl_Exit
End Sub
It seems you just need to automate Outlook for sending out emails with the required content set up. Take a look at the following articles that give you the basics of Outlook automation:
Automating Outlook from a Visual Basic Application
Automating Outlook from Other Office Applications
Sub Send_Mail_Outlook()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "eugene#astafiev.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub

Differences between when we manually forward and email versus when we use a macro to forward an email in outlook

I haven't noticed manually forwarding an email using outlook (2016) forward button is giving me different result from when I use a macro to forward it. Here is my macro:
Sub W()
Dim helpdeskaddress As String
Dim objMail As Outlook.MailItem
Dim strbody As String
Dim oldmsg As String
Dim senderaddress As String
Dim addresstype As Integer
' Set this variable as your helpdesk e-mail address
helpdeskaddress = "blah#blah.com"
Set objItem = GetCurrentItem()
Set objMail = objItem.Forward
' Sender E=mail Address
senderaddress = objItem.SenderEmailAddress
'Searches for # in the email address to determine if it is an exchange user
addresstype = InStr(senderaddress, "#")
' If the address is an Exchange DN use the Senders Name
If addresstype = 0 Then
senderaddress = objItem.SenderName
End If
'adds the senders e-mail address as the created by object for the ticket and appends the message body
strbody = "#created by " & senderaddress & vbNewLine & vbNewLine & objItem.Body
objMail.To = "receiver#blah.com"
objMail.Subject = objItem.Subject
objMail.Body = strbody
' remove the comment from below to display the message before sending
'objMail.Display
'Automatically Send the ticket
objMail.Send
MsgBox ("The email has been sent for verification. You may receive a report in a few moments.")
Set objItem = Nothing
Set objMail = Nothing
End Sub
and a function to obtain the current email object item:
Function GetCurrentItem() As Object
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = _
objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = _
objApp.ActiveInspector.CurrentItem
Case Else
End Select
End Function
When I forward an email, I can see all images (linked to another website on the Internet) I am forwarding but when I use the following macro, all I see is the text inside the email. Is there anyway I can make the following macro to do the similar job as manually forwarding does?
To forward the original content, use HTMLBody instead of Body:
strbody = "HTML-encoded content"
objMail.HTMLBody = strbody & objMail.HTMLBody
Sample HTML Format specific text in Outlook

Attach .jpg screenshot to Outlook mail

I created a form that contains an attachment field that screenshots are attached to in .jpg format.
I am trying to send emails from the form.
I would like to attach the screenshots to the email, (the one that is already attached on the form).
I tried using the .attachment.add me.attachmentfield. This is not attaching anything to the email.
Also I am using a combobox to select a person to send the email to, (this is stored in another table along with an email address). I am unable to populate the To box in the email with the email address of the individual selected.
Actually an Access attachment field is not an email attachment. Access doesn't have a build in email client, so you must use an email client library like CDO or the Outlook Object library:
Public Function SendEmail(strRecipients As String, strSubject As String, _
Optional strBody As String, Optional strFilePath As String, _
Optional strFileExtension As String) As String
On Error GoTo ProcError
Dim myObject As Object
Dim myItem As Object
Dim strFullPath As String
Dim strFileName As String
Dim strAttachPath As Variant
Dim intAttachments As Integer
Set myObject = CreateObject("Outlook.Application")
Set myItem = myObject.CreateItem(0)
With myItem
.Subject = strSubject
.To = strRecipients
If Len(Trim(strBody)) > 0 Then
.body = strBody
End If
If Len(Trim(strFileExtension)) = 0 Then
strFileExtension = "*.*"
End If
If Len(strFilePath) > 0 Then
strFullPath = strFilePath & "\" & strFileExtension
If Len(Trim(strFullPath)) > 0 Then 'An optional path was included
strFileName = Dir(strFullPath)
Do Until strFileName = ""
intAttachments = intAttachments + 1
strAttachPath = (strFilePath & "\" & strFileName)
.Attachments.add (strAttachPath)
' Debug.Print strAttachPath
strFileName = Dir()
Loop
End If
End If
.Send
SendEmail = "Message placed in outbox with " & intAttachments & " file attachment(s)."
End With
ExitProc:
Set myItem = Nothing
Set myObject = Nothing
Exit Function
ProcError:
MsgBox "Error " & Err.Number & ": " & Err.Description, _
vbCritical, "Error in SendMail Function..."
SendEmail = "A problem was encountered attempting to automate Outlook."
Resume ExitProc
End Function
Use Field.SaveToFile to dump the Access attachment to a temp file.

Exporting rich text to outlook and keep formatting

I have a button in Access that opens Outlook, creating an appointment.
Private Sub addAppointEstimate_Click()
Dim objOutlook As Object
Dim objOutLookApp As Object
Dim strSubject As String
Dim strBody As String
strSubject = Forms!frmMain.LastName 'more stuff to add
strBody = DLookup("EstimateText", "tblEstimateItems", "EstimateID = 78") '& Forms!frmMain!frmSubTransaction!frmSubEstimate.Form.EstimateID)
Set objOutlook = CreateObject("Outlook.Application")
Set objOutLookApp = objOutlook.CreateItem(1)
With objOutLookApp
.subject = strSubject
.RTFBody = StrConv(strBody, vbFromUnicode)
.Display
End With
End Sub
The problem is that I want to insert Rich text into the Body but it doesn't format correctly, as it shows all the HTML tags instead e.g:
<div><strong>example </strong><font color=red>text</font></div>
Is there a way I can send or convert the rich text to Outlook in a format it will recognise? (Maybe using the clipboard)
It seems many people have solution for Excel, but I am struggling to get them to work in Access:
HTML Text with tags to formatted text in an Excel cell
http://dailydoseofexcel.com/archives/2005/02/23/html-in-cells-ii/
To pass RTF formatted string to outlook email body is simple as following
Function RTF2Outlook(strRTF as String) as boolean
Dim myOlApp, myOlItem
Dim arrFiles() As String, arrDesc() As String, i As Long
Set myOlApp = CreateObject("Outlook.Application")
Set myOlItem = myOlApp.CreateItem(olMailItem)
With myOlItem
.BodyFormat = olFormatRichText
.Body = StrConv(strRTF, vbFromUnicode) 'Convert RTF string to byte array
End With
Set myOlApp = Nothing
Set myOlItem = Nothing
End Function
The secret is not to use ".RTFBody" but just ".Body" and pass to it byte array as in the code above. It took me awhile to figure it out.
Thanks to Microsoft we always will have something to figure out.
You can use a little extra overhead to create a message with the formatted HTMLBody content, then copy the content to an Appointment item.
Start by creating a message and an appointment and populating them as desired. Put the body text in the message, skip the body in the appointment for now.
Dim objOutlook As Object
Dim objMyMsgItem As Object
Dim objMyApptItem As Object
Dim strSubject As String
strSubject = "Some text" 'Forms!frmMain.LastName 'more stuff to add
Set objOutlook = CreateObject("Outlook.Application")
Set objMyMsgItem = objOutlook.CreateItem(0) 'Message Item
With objMyMsgItem
.HTMLBody = "<div><strong>example </strong><font color=red>text</font></div>"
'DLookup("EstimateText", "tblEstimateItems", "EstimateID = 78")
.Display
End With
Set objMyApptItem = objOutlook.CreateItem(1) 'Appointment Item
With objMyApptItem
.Subject = strSubject
.Display
End With
Then use the GetInspector property to interact with the body of each item via a Word editor, and copy the formatted text that way.
Dim MyMsgInspector As Object
Dim wdDoc_Msg As Object
Set MyMsgInspector = objMyMsgItem.GetInspector
Set wdDoc_Msg = MyMsgInspector.WordEditor
Dim MyApptInspector As Object
Dim wdDoc_Appt As Object
Set MyApptInspector = objMyApptItem.GetInspector
Set wdDoc_Appt = MyApptInspector.WordEditor
wdDoc_Appt.Range.FormattedText = wdDoc_Msg.Range.FormattedText
This code is tested and works in Access 2013.
You are setting the plain text Body property. Set the HTMLBody property to a properly formatted HTML string.
I came up with a solution. I have just copied and pasted the entire sub, but the answer is in there I promise. I have also highlighted the important bits.
I works on my home machine, but not on the clients. So I cant use it, but if you can improve on it let me know.
Private Sub addAppointmentEst_Click()
Dim objOutlook As Object
Dim objOutLookApp As Object
Dim strSubject As String
Dim strBody As String
On Error GoTo appointmentEstError
If Not IsNull(DLookup("EstimateID", "tblEstimate", "TransactionID = " & Me.TransactionID.Value)) Then
DoCmd.OpenForm "frmEditEstimate", , , , , acHidden '<------ OPEN FORMATTED TEXT IN A FORM
Forms!frmEditEstimate.SetFocus
Forms!frmEditEstimate!frmSubEstimateItems.Form.EstimateText.SetFocus
DoCmd.RunCommand acCmdCopy '<------ COPY FORMATTED TEXT
DoCmd.Close acForm, "frmEditEstimate", acSaveNo
End If
' If Not IsNull(Forms!frmMain.Title.Value) Then
' strSubject = strSubject & Forms!frmMain.Title.Value
' End If
If Not IsNull(Forms!frmMain.FirstName.Value) Then
strSubject = strSubject & Forms!frmMain.FirstName.Value
End If
If Not IsNull(Forms!frmMain.LastName.Value) Then
strSubject = strSubject & " " & Forms!frmMain.LastName.Value
End If
If Not IsNull(Forms!frmMain.Organisation.Value) Then
strSubject = strSubject & " (" & Forms!frmMain.Organisation.Value & ")"
End If
If Not IsNull(Forms!frmMain!frmSubTransaction.Form.Property.Value) Then
strSubject = strSubject & " - " & Forms!frmMain!frmSubTransaction.Form.Property.Value
End If
Set objOutlook = CreateObject("Outlook.Application")
Set objOutLookApp = objOutlook.CreateItem(1)
With objOutLookApp
.subject = strSubject
.Display
End With
If Not IsNull(DLookup("EstimateID", "tblEstimate", "TransactionID = " & Me.TransactionID.Value)) Then
Set objectOutlookBody = objOutlook.ActiveInspector.WordEditor
objOutLookApp.Body = vbCrLf & "Estimate ID: " & Forms!frmMain!frmSubTransaction!frmSubEstimate.Form.EstimateID.Value & _
vbCrLf & "Estimate Date: " & Forms!frmMain!frmSubTransaction!frmSubEstimate.Form.EstimateDate.Value
objectOutlookBody.Application.Selection.Paste '<----- PASTE TEXT INTO APPOINTMENT
Forms!frmMain.EmptyValue.Value = " " '<----- EMPTY CLIPBOARD
Forms!frmMain.EmptyValue.SetFocus
DoCmd.RunCommand acCmdCopy
End If
Exit Sub
appointmentEstError:
MsgBox _
Prompt:="Failed create an appointment in Outlook, with the estimate attached", _
Buttons:=vbOKOnly + vbExclamation, _
Title:="Error"
End Sub
As in previous answer, this line is the key, it copies text, hyperlinks, pictures etc. without modifying clipboard content:
wdDoc_Appt.Range.FormattedText = wdDoc_Msg.Range.FormattedText