I'm trying to automate the sending of an email through Lotus Notes 9.0 using VBA. The code will load up notes, which asks for my password but before the password prompt shows up, I get an error. The error I run in to is "Run-time error '-2147417851 (80010105)': Automation Error The server threw an exception" When I hit debug, the line that it fails on is "Set obDoc = obDB.CreateDocument". A lot of what I've seen online example wise matches what I'm doing in my code, so I'm not sure where the problem is.
Here's the code:
Sub Send_Emails()
Dim stSubject As Variant
Dim emailList As Variant
Dim obSess As Object
Dim obDB As Object
Dim obDoc As Object
'----Create Email List - separate function, dynamically creates email list based off report processing done in other functions
CreateEmailList
'----Info for Subject
stSubject = "test subject"
'----Create Notes Session
Set obSess = CreateObject("Notes.NotesSession")
Set obDB = obSess.GETDATABASE("", "")
If obDB.IsOpen = False Then
Call obDB.OPENMAIL
End If
'----Create the e-mail - **FAILURE OCCURS HERE**
Set obDoc = obDB.CreateDocument
'----Add values to the email
With obDoc
.form = "Memo"
.SendTo = "test#test.com"
.blindcopyTo = emailList
.Subject = stSubject
.HTMLBody = "<HTML><BODY><p>test</p></BODY></HTML>"
.SaveMessageOnSend = True
.PostedDate = Now()
.Send 0, emailList
End With
'----Clean Up
Set obDoc = Nothing
Set obDB = Nothing
Set obSess = Nothing
MsgBox "The e-mail has been sent successfully", vbInformation
End Sub
You mention that you are using Notes 9, so I looked at the online help for Notes 9.01 and the help page for the OpenMail method says
Note: This method is supported in LotusScript® only. For COM, use OpenMailDatabase in NotesDbDirectory.
Now, you're actually using the OLE automation classes (rooted at Notes.NotesSession), not the COM classes (rooted at Lotus.NotesSession), so I don't know if you can use the NotesDbDirectory class or not, but the other way of opening the current user's mail database would be to call NotesSession.GetEnvironmentString("MailServer",true) and NotesSession.GetEnvironmentString("MailFile",true), and use those as the values for your call to GetDatabase.
Related
I'm using the following code to generate and open an Outlook E-Mail. However I need to be able to insert a table with some variables and my current method only allows for basic text, could anyone suggest a way in which I could integrate a table?
Try
lblStatus.Text = "Opening OutLook Mail, Please Wait..."
My.Application.DoEvents
Dim Outl As Object
Outl = CreateObject("Outlook.Application")
If Outl IsNot Nothing Then
Dim omsg As Object
omsg = Outl.CreateItem(0)
omsg.body = "Table should go here"
omsg.To = "*address goes here"
omsg.subject = SubjectLine
'set message properties here...'
omsg.Display(false) 'will display message to user
lblStatus.Text = "Outlook Mail Template Opened."
My.Application.DoEvents
End If
Catch ex As Exception
lblStatus.Text = "Opening OutLook Mail | Error Encountered"
My.Application.DoEvents
'log error
End Try
Here's an example of what the table needs to be like:
Obviously there's formatting code used by Outlook, but I don't know how to send that from visual basic into the email.
First get the DoEvents() out of your code. They are not helping anything.
As for the table, the simplest way to do it is to build the message body as a HTML string that includes the table. Of course, that requires the receiver of the email set to accept HTML.
I currently have an excel file that produces client statements. I need to track who has run their statements.
Currently, whenever statements are produced I have a macro that send me an email with their user name. However people running on a Thin Client system they get a prompt;
'A program is trying to send an email message on your behalf...'
IS there some way I can get rid of this prompt and still send the email, or has anyone got any other ideas on how to track usage. I share the file through Share Point. So that might have some capabilities?
Thank you
If there is a location on your network that everyone has access to you can write a log file. Most likely a spot on the Sharepoint server.
Something like this called from the code that is currently sending out the email.
In you VBA IDE go to the tools menu and select references. Select "Microsoft scripting runtime"
Private Sub LogUsage()
Dim ts As TextStream
Dim fs As FileSystemObject
Dim strLogFile As String
strLogFile = "\\servername\sharename\log\Usage.txt"
'Check if the file exists, if it does, open it, if it doesn't create it
Set fs = New FileSystemObject
If fs.FileExists(strLogFile) = True Then
Set ts = fs.OpenTextFile(strLogFile, ForAppending)
Else
Set ts = fs.CreateTextFile(strLogFile, True, False)
End If
'Log your entry
ts.WriteLine "Used by " & Environ$("Username") & " at " & Now & " on computer " & Environ$("Computername")
'Clean up
ts.Close: Set ts = Nothing
Set fs = Nothing
End Sub
I'd use a shared database, like SQL server or Access on a network share, rather than an e-mail. It's easier to work with than separate e-mails.
If you must use e-mail, you can use a CDO object in your Excel macro, but your users must have access to an SMTP server on your network (usually an Exchange server works for this; look at your Outlook settings and see what server it's connected to). Generally this is not a problem if everyone has access to the same LAN resources.
Add a reference in the VBA editor to Microsoft CDO for Windows 2000 Library (Tools->References in VBA. Don't worry about the "Windows 2000"; it should be available on your system).
Example code
Dim iMsg As CDO.Message
Dim iConf As CDO.Configuration
Dim Flds As ADODB.Fields
Set iMsg = New CDO.Message
Set iConf = New CDO.Configuration
Set Flds = iConf.Fields
With Flds
.Item(cdoSendUsingMethod) = cdoSendUsingPort
'Put the address of your SMTP server here
.Item(cdoSMTPServer) = "smtp.example.com"
.Item(cdoSMTPConnectionTimeout) = 10
.Item(cdoSMTPAuthenticate) = cdoBasic
.Item(cdoSendUserName) = "Username To Authenticate SMTP Server With"
.Item(cdoSendPassword) = "Password To Authenticate SMTP Server With"
.Item(cdoURLGetLatestVersion) = True
.Update
End With
With iMsg
Set .Configuration = iConf
.From = "from#example.com"
.ReplyTo = "replyto#example.com"
.MimeFormatted = False
.AutoGenerateTextBody = False
.To = "to#example.com"
.CC = "cc#example.com"
.BCC = "bcc#example.com"
.Subject = "Subject of Email"
.HTMLBody = "<body>HTML text to send</body>"
'If you need to add attachments
.AddAttachment "C:\Local\Path\To\Attachment.xlsx"
.Send
End With
I have already seen a lot of posts related to that, both on the web overall or on stackoverflow. However, I didn't see people making too much changes and really playing with this macro.
Ok, it's possible to send emails through lotus notes using VBA, but how can I make these emails cooler? Change font format or color for example? Change the styles, choosing to insert picture as a link or embedding it?
Well, this is what I got so far by searching around and making a few changes:
Sub SendEmail(Subject, Text)
Dim Maildb As Object
Dim mailDoc As Object
Dim body As Object
Dim session As Object
'Start a session to notes
Set session = CreateObject("Lotus.NotesSession")
'This line prompts for password of current ID noted in Notes.INI
'Call session.Initialize
Call session.Initialize("Your Password Here")
'Open the mail database in notes
Set Maildb = session.GetDatabase("Mail Server", "mail\ .nsf")
If Not Maildb.IsOpen = True Then
Call Maildb.Open
End If
'Create the mail document
Set mailDoc = Maildb.CreateDocument
Call mailDoc.ReplaceItemValue("Form", "Memo")
'Set the recipient (you can write the name of a list you saved in your Lotus Notes)
Call mailDoc.ReplaceItemValue("SendTo", "email1#email.com.br")
'Set subject
Call mailDoc.ReplaceItemValue("Subject", Subject)
'Create and set the Body content
Set body = mailDoc.CreateRichTextItem("Body")
Call body.AppendText(Text)
'Example to create an attachment (optional)
Call body.AddNewLine(2)
'Insert an pdf attached
Call body.EmbedObject(1453, "", "C:\Desktop\Test.pdf")
Call body.AddNewLine(2) 'add line to separate text
'Message in the end of the email
Call body.AppendText("This is an automatic message.")
'Example to save the message (optional)
mailDoc.SaveMessageOnSend = True
'Send the document
'Gets the mail to appear in the Sent items folder
Call mailDoc.ReplaceItemValue("PostedDate", Now())
Call mailDoc.send(False)
'Clean Up
Set Maildb = Nothing
Set mailDoc = Nothing
Set body = Nothing
Set session = Nothing
End Sub
Btw, I use the Windows Task Scheduler to call a VBS which will then call a macro that will call the macro to send email with a specific subject and text. As I have several macros that generates emails and each one has its subject and text, I thought this would be better.
This is the vbs (this is probably useless and everyone knows here, but I will share anyway):
'Run VBA Using VBS
Option Explicit
On Error Resume Next
ExcelMacroExample
Sub ExcelMacroExample()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("C:\Desktop\Macros.xlsm") 'Excel filename
xlApp.Run "SendEmail" 'Excel macro name
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
A couple of things here:
It's going to be easier if you can first write the code in Domino Designer (i.e. get a machine installed with the Notes Client and the Domino Designer Client). At the moment you are using Notes as a COM Server. The big disadvantage is that you have almost no debugging information if something fails. Write the code first in LotusScript, then port it to VBS (they are very similar dialects of BASIC).
You can create a Notes RichText E-Mail (this is what you are doing now with CreateRichTextItem). You can manipulate the RichTextItem with different methods, the most important one being NotesRichTextStyle, which you have to think of as 'bits of formatting that will change everything afterwards'. You need to create the NotesRichTextStyle Object, configure it (i.e. font, bold, etc) and insert it into the rich text field. If this sounds klunky, that's because it is.
Dim db As NotesDatabase
Dim session As New NotesSession
Set db = session.CurrentDatabas
Dim doc As New NotesDocument(db)
Call doc.AppendItemValue("From", session.UserName)
Call doc.AppendItemValue("Subject", _
"Meeting time changed")
Dim richStyle As NotesRichTextStyle
Set richStyle = session.CreateRichTextStyle
Dim richText As New NotesRichTextItem(doc, "Body")
Call richText.AppendText("The meeting is at ")
richStyle.Bold = True
Call richText.AppendStyle(richStyle)
Call richText.AppendText("3:00")
richStyle.Bold = False
Call richText.AppendStyle(richStyle)
Call richText.AppendText(" not 2:00")
Call doc.Save(True, False)
If you want even more control, then you can create an HTML E-Mail wrapped in Mime, but it's fiddly at best and you're looking at several days of painful steps until it works, and you really would need an experienced professional for this. This is a good start: other Stackoverflow question
The way you're referencing the user's mail reference is horrible. It's hardcoded and will only ever work for that one particular database, even if the person in question changes name, for instance. This is much better:
Dim db As New NotesDatabase( "", "" )
Call db.OpenMail
Can anyone help me figure out what's going wrong and how to fix it?
I'm trying to automate sending an email with some daily status information. I'd tried automating this from Access but kept running into (known but apparently unsolved) problems with GetObject(, "Outlook.Application") with Windows 8.1 64 and Outlook 2013. So I decided to automate starting from Outlook.
Anyway, I moved the mail message creation code into Outlook vba and had it start Access and run the Access code. This is all well and good until I get to creating the mail message. Everything starts just fine until it gets to writing to the body of message (using Word as the body editor). At the first "TypeText" command, I'm getting the error message in the title. If I click debug on the error notification dialog and then single-step through the line of code in question, it works just fine. I thought that there was some timing problem, so I stuck a 2-second wait in the code. No luck. The code in question, with some other oddities associated with testing (notably trying to type and then delete text), is below:
Public Sub CreateMetrics()
' Mail-sending variables
Dim mailApp As Outlook.Application
Dim accessApp As Access.Application
Dim mail As MailItem
Dim wEditor As Word.Document
Dim boolCreatedApp As Boolean
Dim i As Integer
Set mailApp = Application
' Create an Access application object and open the database
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase dbLoc
accessApp.Visible = True
' Open the desired form and run the click event hander for the start button
accessApp.DoCmd.OpenForm ("ProcessStatus")
accessApp.Forms![ProcessStatus].StartButton_Click
' Create the outgoing mail message
Set mail = Application.CreateItem(olMailItem)
mail.Display
mail.BodyFormat = olFormatHTML
Set wEditor = mailApp.ActiveInspector.WordEditor
With accessApp.Forms![ProcessStatus]
Debug.Print .lblToList.Caption
Debug.Print .lblSubject.Caption
Debug.Print .lblIntroduction.Caption
Debug.Print .lblAttachFilepath.Caption
End With
mail.To = accessApp.Forms![ProcessStatus].lblToList.Caption
mail.Recipients.ResolveAll
mail.Subject = accessApp.Forms![ProcessStatus].lblSubject.Caption
mail.Attachments.Add accessApp.Forms![ProcessStatus].lblAttachFilepath.Caption
Sleep 2000
' Error occurs in the next line ***********************************************
wEditor.Application.Selection.TypeText Text:="Test"
wEditor.Application.Selection.HomeKey
wEditor.Application.Selection.Delete Count:=4
wEditor.Application.Selection.PasteSpecial DataType:=wdPasteBitmap
wEditor.Application.Selection.HomeKey
wEditor.Application.Selection.TypeText accessApp.Forms![ProcessStatus].lblIntroduction.Caption
wEditor.Application.Selection.TypeText Text:=Chr(13) & Chr(13)
wEditor.Application.Selection.EndKey
' wEditor.Application.Selection.EndKey
' wEditor.Application.Selection.TypeText Text:=Chr(13)
' wEditor.Application.Selection.TypeText Text:=configs("EmailSignature")
' End With
With mailApp.Session.Accounts
i = 1
Do While i <= .Count
' Use either the specified email address OR the last outlook email address
If RegEx_IsStringMatching(.Item(i).SmtpAddress, accessApp.Forms![ProcessStatus].lblSenderRegex.Caption) Or i = .Count Then
mail.SendUsingAccount = .Item(i)
i = .Count + 1
Else
i = i + 1
End If
Loop
End With
mail.Save
accessApp.Quit
End Sub
I added a "mail.Display" just before the line that was causing the failure, which seemed, incorrectly, to have fixed the problem.
I have now solved this problem by executing a document.select on the document associated with the email I was creating. To select the right document (there doesn't seem to be any guarantee of which one that would be within the wEditor.Application.Documents collection, though it was typically the first one), I created an almost-certainly unique piece of text and assigned it to the body of the email, which I could then go and find. Here's the new code that I added to the code above:
Dim aDoc As Word.Document
Dim strUniqueID As String
. . .
mail.Attachments.Add accessApp.Forms![ProcessStatus].lblAttachFilepath.Caption
strUniqueID = accessApp.Forms![ProcessStatus].lblSubject.Caption & Rnd(Now()) & Now()
mail.Body = strUniqueID
' Search for the unique text. aDoc.Content has extra characters at the
' end, so compare only for the length of the unique text
For Each aDoc In wEditor.Application.Documents
If Left(aDoc.Content, Len(strUniqueID)) = strUniqueID Then
aDoc.Select
mail.Body = ""
End If
Next aDoc
wEditor.Application.Selection.TypeText Text:="Test"
. . .
I looked at a lot of examples of code that did this kind of thing. None of them performed a select or said anything about needing one. Debugging was made that much harder because the select occured implicitly when the debugger was invoked.
Possible Duplicate:
Send e-mail through VBA
Send email from Excel in Exchange environment
I have this so far
Dim objOutl
Set objOutl = CreateObject("Outlook.Application")
Set objMailItem = objOutl.CreateItem(olMailItem)
objMailItem.Display
strEmailAddr = "me.me#you.com"
objMailItem.Recipients.Add strEmailAddr
objMailItem.Body = "Hi"
objMailItem.Attachments.Add "access.xml"
Set objMailItem = nothing
Set objOutl = nothing
It works! But only on computers that have Outlook. How can I get this to work with computers that have Windows Live?
Windows Live Mail (WLM) doesn't support automation via VBA, so it isn't as straightforward as with Outlook.
For other options, try typing [vba] e-mail in the search field. You'll get quite a few hits; here is a relevant sample: Hit, hit, hit. Some of these give you working code for sending mail using CDO. This is what I would do if I were you.
If you must use WLM, then have a look at this mail add-ins for Excel which does support WLM.
Otherwise you're stuck using VBA's SendMail method, which is very limited:
Can only send an Excel object such as a sheet, workbook, chart, range, etc.
Can't write text in the body of the e-mail
Can't use the CC or BCC fields
Can't attach files (other than the Excel object calling the method)
Example code:
Dim wb As Workbook
Set wb = ActiveWorkbook
wb.SendMail "me.me#you.com", _
"Insert subject here"
For more examples look here: http://www.rondebruin.nl/sendmail.htm
the following suppose to work on access (vba) (code is not mine):
Public Function send_email()
Set cdomsg = CreateObject("CDO.message")
With cdomsg.Configuration.Fields
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 'NTLM method
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.gmail.com"
.Item("http://schemas.microsoft.com/cdo/configuration/smptserverport") = 587
.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 60
.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "mygmail#gmail.com"
.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "mypassword"
.Update
End With
' build email parts With cdomsg
.To = "somebody#somedomain.com"
.From = "mygmail#gmail.com"
.Subject = "the email subject"
.TextBody = "the full message body goes here. you may want to create a variable to hold the text"
.Send
End With
Set cdomsg = Nothing
End Function
note if you want to use other email service you should alter the code a bit.
some other options here - msdn reference
Hope it helps.