Send HTML-formatted email messages from Access - ms-access

Is there any way to send a mail in HTML format (and if possible with attachments) when your default mail client isn't Outlook?
Many thanks for any solution.

You should be able to use CDO (Collaboration Data Objects). The code will look something like this:
Option Compare Database
Option Explicit
Sub cdoHtmlTest()
Const urlPrefix = "http://schemas.microsoft.com/cdo/configuration/"
Dim msg As Object ' CDO.Message
Set msg = CreateObject("CDO.Message") ' New CDO.Message
With msg.Configuration.Fields
.Item(urlPrefix & "sendusing") = 2 ' cdoSendUsingPort
.Item(urlPrefix & "smtpserver") = "smtp.example.com"
.Item(urlPrefix & "smtpserverport") = 25
.Item(urlPrefix & "smtpauthenticate") = 1 ' cdoBasic
.Item(urlPrefix & "sendusername") = "mySmtpUserName"
.Item(urlPrefix & "sendpassword") = "mySmtpPassword"
.Item(urlPrefix & "smtpusessl") = False
.Update ' remember to do this step!
End With
With msg
.To = "gord#example.com"
.From = "gord#example.com"
.Subject = "HTML message test"
.HTMLBody = "This is a <strong>TEST</strong>."
.Send
End With
Set msg = Nothing
End Sub
For more examples (including how to send attachments), look here.

Related

Sending Access reports by email as HTML

I have an MS Access report that contains records of clients from one table (including the email address) and linked grouped records from other tables fetched by a Query.
I want to send the content of the report to each client separately in the body of the email (not as an attachment), I am able to get the text put in the body of the email but without the formatting and without the picture in the header.
I used the following code which runs behind a click of a button. I would appreciate if anyone can help with the formatting issue AND if there is a way I can automate sending the emails for my 200+ clients without clicking the button each time (like a loop or something):
Private Sub Command70_Click()
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim appOutlook As Outlook.Application
Dim MailOutlook As Outlook.MailItem
Dim RTFBody
Set appOutlook = CreateObject("Outlook.application")
Set MailOutlook = appOutlook.CreateItem(olMailItem)
DoCmd.OutputTo acOutputReport, "report1", acFormatHTML, "Report.htm", , , , acExportQualityScreen
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.OpenTextFile("Report.htm", ForReading, False, TristateTrue)
RTFBody = f.ReadAll
f.Close
With MailOutlook
.To = Me.Email.Value
.CC = "anwarmirza.ridha#gmail.com"
.Subject = Me.CR_Number & " " & Me.English_Name & " Weekly Report"
.HTMLBody = "Dear Supplier" & Chr$(13) & Chr$(13) & _
RTFBody
.Send
End With
Set MailOutlook = Nothing
Set appOutlook = Nothing
End Sub
Since MS Access reports are specialized rich text formats, conversion to HTML is not easily available. You would need to rebuild your report with HTML markup. However, there is another approach.
Consider creating an Outlook email template (.oft) with all needed images, colors, fonts, and other formatting with placeholders such as %...% markers:
Dear %ClientName%:
Thank you for purchase of %product% for %totalsales% on %salesdate%. We appreciate your business of %years% years.
%salestable%
Best wishes,
MyCompany Management
Then, have MS Access loop through a recordset of email details and text for message body to fill in placeholders. Handle any date/current/percent formatting in SQL or VBA. Because you need a group level multi-record summary, run two loops at 1) client level and 2) sales level.
strSQL = "SELECT ClientID, ClientName, ...email details... FROM myClientsTable"
Set clientRST = CurrentDb.OpenRecordset(strSQL)
Do While Not clientRST.EOF
Set MailOutlook = appOutlook.CreateItemFromTemplate("C:\Path\To\ClientEmail.oft")
strSQL = "SELECT Col1, Col2, Col3 ...sales details..." _
& " FROM mySalesTable" _
& " WHERE ClientID = " & clientRST!ClientID
Set salesRST = CurrentDb.OpenRecordSet(strSQL)
' TABLE COLUMNS
strTable = "<table><th>"
For i = 1 to salesRST.Fields.Count
strTable = strTable & "<td>" & salesRST.Fields(i-0).Name & "</td>"
Next i
strTable = strTable & "</th>"
' TABLE ROWS
salesRST.MoveFirst
While Not salesRst.EOF
strTable = strTable & "<tr>"
For i = 1 to salesRST.Fields.Count
strTable = strTable & "<td>" & salesRST.Fields(i-0).Value & "</td>"
Next i
strTable = strTable & "</tr>"
salesRST.MoveNext
Wend
strTable = strTable & "</table>"
salesRST.Close
With MailOutlook
' DYNAMIC RECIPEINT
.To = clientRST!Email
.CC = "anwarmirza.ridha#gmail.com"
' DYNAMIC SUBJECT
.Subject = clientRST!CR_Number & " " & clientRST!English_Name & " Weekly Report"
' REPLACE PLACEHOLDERS
.HTMLBody = Replace(.HTMLBody, "%ClientName%", clientRST!ClientName)
.HTMLBody = Replace(.HTMLBody, "%product%", clientRST!product)
.HTMLBody = Replace(.HTMLBody, "%totalsales%", clientRST!totalsales)
.HTMLBody = Replace(.HTMLBody, "%salesdate%", clientRST!salesdate)
.HTMLBody = Replace(.HTMLBody, "%years%", clientRST!client_years)
' ADD SALES TABLE
.HTMLBody = Replace(.HTMLBody, "%salestable%", strTable)
.Send
End With
Set MailOutlook = Nothing
clientRST.MoveNext
Loop
clientRST.Close

Embedding an HTML file with images in an Outlook email generated by Excel VBA

I want to send a personalized email generated by Excel VBA.
The email contains personalized text followed by a html file that contains images.
I tried the following code but the images are not displayed.
Sub Mail_Outlook_With_Html_Doc()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Dim oFSO As Object
Dim oFS As Object
Dim sText As String
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFS = oFSO.OpenTextFile("C:\....\invite.htm")
Do Until oFS.AtEndOfStream
sText = oFS.ReadAll()
Loop
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
'strbody = personalized email body generated here
On Error Resume Next
With OutMail
.display
.To = ToAdd
.CC =
.BCC = ""
.Subject = "Test Email"
.ReadReceiptRequested = True
' the html file is appended here to the personalized email body generated
.HTMLBody = strbody & sText
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
The invite.htm referred above contains images which are not visible when the email is sent. Neither in the email messages sent nor in the email messages received.
Here ia an example that works for me you need to adapt it according to your needs.
This will embed the image in the body of the email and will attach it from what I remember. Please note you need to display the email first and then send it that is the only way to show on different device, i learn that the hard way. It can be done via code as the below example if you want to display and review the email just comment out the .Send after you are happy you can press manually send.
Option Explicit
Dim titleName As String
Dim firstName As String
Dim lastName As String
Dim fullName As String
Dim clientEmail As String
Dim ccEmail As String
Dim bccEmail As String
Dim emailMessage As String
Sub GenerateInfo()
Dim WS As Worksheet
Dim lrow As Long
Dim cRow As Long
Set WS = ActiveSheet
With WS
lrow = .Range("E" & .Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
For cRow = 2 To lrow
If Not .Range("L" & cRow).value = "" Then
titleName = .Range("D" & cRow).value
firstName = .Range("E" & cRow).value
lastName = .Range("F" & cRow).value
fullName = firstName & " " & lastName
clientEmail = .Range("L" & cRow).value
Call SendEmail
.Range("Y" & cRow).value = "Yes"
.Range("Y" & cRow).Font.Color = vbGreen
Else
.Range("Y" & cRow).value = "No"
.Range("Y" & cRow).Font.Color = vbRed
End If
Next cRow
End With
Application.ScreenUpdating = True
MsgBox "Process completed!", vbInformation
End Sub
Sub SendEmail()
Dim outlookApp As Object
Dim outlookMail As Object
Dim sigString As String
Dim Signature As String
Dim insertPhoto As String
Dim photoSize As String
Set outlookApp = CreateObject("Outlook.Application")
Set outlookMail = outlookApp.CreateItem(0)
'Change only Mysig.htm to the name of your signature
sigString = Environ("appdata") & _
"\Microsoft\Signatures\Marius.htm"
If Dir(sigString) <> "" Then
Signature = GetBoiler(sigString)
Else
Signature = ""
End If
insertPhoto = "C:\Users\marius\Desktop\Presale.jpg" 'Picture path
photoSize = "<img src=""cid:Presale.jpg""height=400 width=400>" 'Change image name here
emailMessage = "<BODY style=font-size:11pt;font-family:Calibri>Dear " & titleName & " " & fullName & "," & _
"<p>I hope my email will find you very well." & _
"<p>Our <strong>sales preview</strong> starts on Thursday the 22nd until Sunday the 25th of November." & _
"<p>I look forward to welcoming you into the store to shop on preview.<p>" & _
"<p> It really is the perfect opportunity to get some fabulous pieces for the fast approaching festive season." & _
"<p>Please feel free to contact me and book an appointment." & _
"<p>I look forward to seeing you then." & _
"<p>" & photoSize & _
"<p>Kind Regards," & _
"<br>" & _
"<br><strong>Marius</strong>" & _
"<br>Assistant Store Manager" & _
"<p>"
With outlookMail
.To = clientEmail
.CC = ""
.BCC = ""
.Subject = "PRIVATE SALE"
.BodyFormat = 2
.Attachments.Add insertPhoto, 1, 0
.HTMLBody = emailMessage & Signature 'Including photo insert and signature
'.HTMLBody = emailMessage & Signature 'Only signature
.Importance = 2
.ReadReceiptRequested = True
.Display
.Send
End With
Set outlookApp = Nothing
Set outlookMail = Nothing
End Sub
Function GetBoiler(ByVal sFile As String) As String
Dim fso As Object
Dim ts As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
GetBoiler = ts.readall
ts.Close
End Function

Insert Dynamic Table into email

The below script generates a text list and inserts it into an email and sends to specific people. It works fine as plain text. What I am trying to accomplish is to create a dynamic html table and insert into the body of the email. I have tried to add html tags around the TextBody for the .HTMLBody property, but no email came out. I changed the template files to .html files and created html tables in there, but the email had the code as plain text.
Here is a sample of the working output:
AREA: Line 2
SPID: 308582 Name: LINE 2 ROBERTS NO 2 COOLING LINE East
Expectation: BiMonthly
Projected: +2mos Last Sampled Approved Date: 2013-06-10
I would like to have all the text before the colons to be the headers and then the results listed below the headers.
Option Explicit
Dim mConnectionString, objFSO, vEmailTemplateFile, vEmailTemplateSPID
Dim blnDebugMode, DebugLogLevel
Dim oConn 'ADO connection
Dim vLogDir,LogFilePrefix,gstrmsg
Dim adminEmail, EmailSubject, smtpServer
mConnectionString = "Provider=SQLOLEDB;Server=;Initial Catalog;Integrated Security=;"
vEmailTemplateFile = "C:\EMAILScripts\SampleReminderTemplate.txt"
vEmailTemplateSPID = "C:\EMAILScripts\SampleReminderSPIDTemplate.txt"
'Read in SPID template
sSPIDTemplate = ""
Set objFileStreamIn = objFSO.OpenTextFile(vEmailTemplateSPID, ForReading)
Do Until objFileStreamIn.AtEndOfStream
sSPIDTemplate = sSPIDTemplate & objFileStreamIn.ReadLine & vbCrLf
Loop
objFileStreamIn.Close
'Read in email template and create email by replacing tokens and then send
sEmailMsg = ""
Set objFileStreamIn = objFSO.OpenTextFile(vEmailTemplateFile, ForReading)
Do Until objFileStreamIn.AtEndOfStream
sEmailMsg = sEmailMsg & objFileStreamIn.ReadLine & vbCrLf
Loop
objFileStreamIn.Close
sEmailMsg = Replace(sEmailMsg,"{name}",sName)
sEmailMsg = Replace(sEmailMsg,"{body}",sBody)
'LogMessage "sEmailMsg: " & sEmailMsg, False, LogDebug
If blnDebugMode Then
sEmail = adminEmail '<< In debug mode send ALL emails to the admin address set above
End If
If blnEmail Then
If SendMailByCDO(adminEmail, EmailSubject, FullErrorMsg, "", "", smtpServer, adminEmail) <> 0 Then
LogMessage "Could Not send email: " & ErrMsg, False, LogError
If errNumber <> Err.Number Then
Err.Clear
End If
End If
End If
'***************************************
'* Sends an email To aTo email address, with Subject And TextBody.
'* The email is In text format.
'* Lets you specify BCC adresses, Attachments, smtp server And Sender email address
'***************************************
Function SendMailByCDO(aTo, Subject, TextBody, BCC, Files, smtp, aFrom )
'On Error Resume Next
Dim Message 'As New CDO.Message '(New - For VBA)
Set Message = CreateObject("CDO.Message")
With Message.Configuration.Fields
.Item("http://schemas.microsoft.com/cdo/configuration/sendemailaddress") = aFrom
'SMTP settings - without authentication, using standard port 25 on host smtp
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = cdoSendUsingPort
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtp
'SMTP Authentication
.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = cdoAnonymous
'**** You can also specify authentication properties for the smtp session using
'**** smtpauthenticate and sendusername + sendpassword:
'* .Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = cdoBasic
'* .Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "info#mycompany.to"
'* .Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
'* .Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True/False
'****
.Update
End With
'Set other message fields.
With Message
.From = aFrom
.To = aTo
.Subject = Subject
'Set TextBody property If you want To send the email As plain text
'.TextBody = TextBody
'* Set HTMLBody property If you want To send the email As an HTML formatted
.HTMLBody = TextBody
'Blind copy And attachments are optional.
If Len(BCC)>0 Then .BCC = BCC
If Len(Files)>0 Then .AddAttachment Files
'Send the email
.Send
End With
IF blnDebugMode and Err.Number <> 0 then
Wscript.Echo "SendMailByCDO err: " & err.description
End IF
'Returns zero If successful. Error code otherwise
SendMailByCDO = Err.Number
End Function
EDIT1: removed extra code to only show email functions.
I created an html file called SampleReminderSPIDTemplateTable.html to replace SampleReminderSPIDTemplate.txt and in that file is the following:
<html xmlns="http://www.w3.org/1999/xhtml">
<table style="width:100%">
<tr>
<td>{AREANAME}</td>
<td>{SPID}</td>
<td>{SPIDNAME}</td>
<td>{LASTSAMPLEAPPROVEDDATE}</td>
<td>{EXPECTATION}</td>
<td>{PROJECTED}</td>
</tr>
</table>
</html>
I also try this to .HTMLBody property, but no emails went out.
.HTMLBody = "<html><body><pre>" & TextBody & "</pre></body></html>"

Send Email using VBA 'Function Run-time error 438'

I'm trying to send email using VBA code, the function is working and the email is sent, but the problem is when function end 'Run-time error 438 object doesn't support this property or method' appears
here is the code:
Public Function SendEmail(ItemName As String, Total_Qnty As Integer)
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
Set Flds = iConf.Fields
' send one copy with Google SMTP server (with autentication)
schema = "http://schemas.microsoft.com/cdo/configuration/"
Flds.Item(schema & "sendusing") = 2
Flds.Item(schema & "smtpserver") = "smtp.gmail.com"
Flds.Item(schema & "smtpserverport") = 465
Flds.Item(schema & "smtpauthenticate") = 1
Flds.Item(schema & "sendusername") = "example#gmail.com"
Flds.Item(schema & "sendpassword") = "*****"
Flds.Item(schema & "smtpusessl") = 1
Flds.Update
With iMsg
.To = "example#hotmail.com"
.From = "example#gmail.com"
.Subject = "Mail from gmail"
.HTMLBody = "The Stock Safty Level of Item: " & ItemName & " is DOWN, The total quantity you have is: " & Total_Qnty & "!!"
Set .Configuration = iConf
.Send
End With
Set iMsg = Nothing
Set iConf = Nothing
Set Flds = Nothing
End Function
Pleased any ideas .. Thank you
Most probably it's a binary compatibility issue between components.
Microsoft says "Run Time Error 438 - Object Doesn't Support this Property or Method:
The most common cause of error 438 is not maintaining binary compatibility between successive versions of your components. Each COM interface has an associated GUID that is called an interface ID (IID). Each coclass has an associated GUID that is called class ID (CLSID). When you compile an ActiveX component in Visual Basic, the CLSIDs and IIDs are compiled into the component's type library."
In this link it's explained how to solve a similar problem:
http://www.vbforums.com/showthread.php?460591-RESOLVED-Runtime-error-438-Object-doesn-t-support-this-property-or-method
Reverse the order of these:
Set iMsg = Nothing
Set iConf = Nothing
Set Flds = Nothing
Flds is a member of iConf which, currently, you have already disposed of.

Sending an Email from MS Access No third party dll allowed

I need to send a series of email notifications from an MS Access Database.
No third party dll's like Redemption
Cannot trip the outlook security warnings
The email will have a pdf attachment
I know to do this I need to use MAPI, but I can't seem to find a way to do this with VBA.
Any help would be appreciated
Thanks,
Scott
If you can live with requiring CDO to be present on the machine, and you don't mind a user-provided SMTP server, you can use that. Just google for some example code, but for you convenience I'll paste some below from www.rondebruin.nl :
Sub CDO_Mail_Small_Text()
Dim iMsg As Object
Dim iConf As Object
Dim strbody As String
' Dim Flds As Variant
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
' iConf.Load -1 ' CDO Source Defaults
' Set Flds = iConf.Fields
' With Flds
' .Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
' .Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") _
' = "Fill in your SMTP server here"
' .Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
' .Update
' End With
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
With iMsg
Set .Configuration = iConf
.To = "ron#debruin.nl"
.CC = ""
.BCC = ""
.From = """Ron"" <ron#something.nl>"
.Subject = "Important message"
.TextBody = strbody
.Send
End With
End Sub
Adding an attachment would be done using .AddAttachment "C:\files\filename.pdf" on the iMsg.
If the user has outlook installed:
Dim strErrMsg As String 'For Error Handling
Dim olApp As New Outlook.Application
Dim olNameSpace As Outlook.NameSpace
Dim olMail As Outlook.MailItem
Dim oleGrf As Object
Dim strFileName As String
Set olNameSpace = olApp.GetNamespace("MAPI")
Set olMail = olApp.CreateItem(olMailItem)
Set oleGrf = Me.OLEchart.Object
strFileName = "c:\temp\Graph.jpg"
oleGrf.Export FileName:=strFileName
With olMail
.To = "someone#somewhere.com"
.Subject = "Graph Info " & Format(Now(), "dd mmm yyyy hh:mm")
.Attachments.Add strFileName
.ReadReceiptRequested = False
.Send
End With
Kill strFileName
Also check out Tony Toews's Microsoft Access Email FAQ
See the page Microsoft Access Email FAQ - Directly via the Winsock I haven't tried those myself but you should be able to adapt the VB6 code to send the emails directly.