Follow up about using VBA to send e-mail - email

This is a follow up to several messages about using VBA to send e-mail.
Most suggestions use either Outlook, CDO, or MAPI:
Set appOL = CreateObject("Outlook.Application")
Set msgOne = CreateObject("CDO.Message")
Set mapi_session = New MSMAPI.MAPISession
But apparently Outlook will require me to change our workgroup security settings, and CDO and MAPI will require me to add a DLL or something.
I'm trying to use Excel to organize group assignments at work and I can't modify the other people's computers in any way.
Is there a simpler way to send e-mails from an Excel macro?
All I need is a block of text in the body of the message with no attachments.
I've been plowing through Google, MSDN & StackOverflow all week and I'm stuck on a slow boat to nowhere.

Building up on what Marc mentioned, Here is a tried and tested version.
Option Explicit
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Sub SendMail()
Dim objMail As String
Dim oMailSubj, oMailTo, oMailBody As String
On Error GoTo Whoa
oMailSubj = "YOUR SUBJECT GOES HERE"
oMailTo = "ABC#ABC.COM"
oMailBody = "BLAH BLAH!!!!"
objMail = "mailto:" & oMailTo & "?subject=" & oMailSubj & "&body=" & oMailBody
ShellExecute 0, vbNullString, objMail, vbNullString, vbNullString, vbNormalFocus
Application.Wait (Now + TimeValue("0:00:03"))
Application.SendKeys "%s"
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
FOLLOWUP
Thanks for the info. I had already ruled out ShellExecute because it limits the entire parameter string to 250 char and I need about 2000 for the message. But it's looking like SE is the only option that will actually work in my case. – Humanoid1000 7 hours ago
Here is the "Horrible (I love the way JFC says that!!!)" way I mentioned below in the comments which works beautifully :) BTW I have only Outlook as my default client so I have tested it with that.
CODE
Option Explicit
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub SendMail()
Dim objMail As String
Dim oMailSubj As String, oMailTo As String
Dim i As Long
Dim objDoc As Object, objSel As Object, objOutlook As Object
Dim MyData As String, strData() As String
On Error GoTo Whoa
'~~> Open the txt file which has the body text and read it in one go
Open "C:\Users\Siddharth Rout\Desktop\Sample.Txt" For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
Sleep 300
oMailSubj = "YOUR SUBJECT GOES HERE"
oMailTo = "ABC#ABC.COM"
objMail = "mailto:" & oMailTo & "?subject=" & oMailSubj
ShellExecute 0, vbNullString, objMail, vbNullString, vbNullString, vbNormalFocus
Sleep 300
Set objOutlook = GetObject(, "Outlook.Application")
'~~> Get a Word.Selection from the open Outlook item
Set objDoc = objOutlook.ActiveInspector.WordEditor
Set objSel = objDoc.Windows(1).Selection
objDoc.Activate
Sleep 300
For i = LBound(strData) To UBound(strData)
objSel.TypeText strData(i)
objSel.TypeText vbNewLine
Next i
Set objDoc = Nothing
Set objSel = Nothing
'~~> Uncomment the below to actually send the email
'Application.Wait (Now + TimeValue("0:00:03"))
'Application.SendKeys "%s"
Exit Sub
Whoa:
MsgBox Err.Description
End Sub
SNAPSHOT
Text File which has the message
Email just before it is sent

You can probably use the Shell command.
Shell("mailto:username#isp.com")
If Outlook is your default email program, I think windows will interpret that properly (it does it from the windows RUN dialog, but not sure if from VBA). Try it out. I'm not in front of Excel at the moment.
Review the params for "mailto" to see how you can add subject and body to that string.
CORRECTION:
That will only generate the email, but won't send it. Disregard my answer.

Here's the final result:
Turns out, the SendMail() worked at home but not at work, but CreateObject("Outlook.Application") did work at work.
My security settings were not the problem with Outlook, it was a mundane typo.
Either way, there's bunch of good info on this page for anyone else who's lost on this topic.

Related

Saving Email Attachments in Specified Folder, File Disappears

So I'm trying to make something that takes emails from a specific folder, and saves the attachments in a specific folder. I've taken this code from a previous post and retooled it for my purposes. It runs without error, but it isn't saving the file in the specified folder, and I can't for the life of me figure it out. Can anyone see my errors?
Sub ExtractFirstUnreadEmailDetails()
Dim oOlAp As Object, oOlns As Object, oOlInb As Object
Dim oOlItm As Object, Br As Object
Dim oOlAtch As Object
Dim eSender As String, dtRecvd As String, dtSent As String
Dim sSubj As String, sMsg As String
'~~> Get Outlook instance
Set oOlAp = GetObject(, "Outlook.application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
Set Br = oOlInb.Folders("Brokers")
'~~> Store the relevant info in the variables
For Each oOlItm In oOlInb.Items.Restrict("[UnRead] = True")
eSender = oOlItm.SenderEmailAddress
dtRecvd = oOlItm.ReceivedTime
dtSent = oOlItm.CreationTime
sSubj = oOlItm.Subject
sMsg = oOlItm.Body
Exit For
Next
Const AttachmentPath As String = "C:\Desktop\Test"
'~~> New File Name for the attachment
Dim NewFileName As String
NewFileName = AttachmentPath & Format(Date, "DD-MM-YYYY") & "-"
'NewFileName = oOlItm.Subject & Format(Date, "DD-MM-YYYY") & "-"
'~~> Extract the attachment from the 1st unread email
For Each oOlItm In Br.Items
For Each oOlAtch In oOlItm.Attachments
Subject = "Test"
NewFileName = Subject
oOlAtch.SaveAsFile NewFileName & oOlAtch.Filename
Next
Exit For
Next
End Sub
I'd be so appreciative if anyone can point anything out. Thanks!
Picking a path at random is the road to failure.
The file should be saved in a folder named Test you created in C:\Desktop
Option Explicit
Sub ExtractFirstUnreadEmailDetails()
' Set up for Outlook
' not for other applications to use Outlook VBA code
Dim oOlInb As Folder
Dim Br As Folder
Dim oOlItm As Object
Dim oOlAtch As attachment
Dim Subject As String
'~~> Get Inbox of Outlook
Set oOlInb = Session.GetDefaultFolder(olFolderInbox)
Set Br = oOlInb.Folders("Brokers")
Const AttachmentPath As String = "C:\Desktop\Test"
'~~> New File Name for the attachment
Dim NewFileName As String
'~~> Extract the attachment from the 1st unread email
For Each oOlItm In Br.Items
For Each oOlAtch In oOlItm.Attachments
Subject = "Test"
' Note the often forgotten path separator
NewFileName = AttachmentPath & "\" & Subject & Format(Date, "DD-MM-YYYY") & "-" & oOlAtch.fileName
' C:\Desktop\Test\Test17-07-2018-fileName
Debug.Print NewFileName
oOlAtch.SaveAsFile NewFileName
Next
Exit For
Next
End Sub
The result should be a file named: Test17-07-2018-Filename in the folder C:\Desktop\Test

Redemption in MS Access / Outlook (trying to include a separate message file in email)

This code is in MS Access (2010) VBA, using the Redemption library with Microsoft Outlook 2010.
I had this process working before, but we recently had a Citrix upgrade that I guess reset something in my Outlook and now the process no longer works.
I have a folder of .msg files which are basically pre-made email templates with all the proper formatting, images, text, etc.
This is what I was doing before:
Dim outlookApp As Object, namespace As Object
Dim oItem, MyItem
Set outlookApp = CreateObject("Outlook.Application")
Set namespace = outlookApp.GetNamespace("MAPI")
namespace.Logon
Set MyItem = outlookApp.CreateItemFromTemplate(path_to_dot_msg_file)
'And then there are many calls like this:
MyItem.HTMLBody = Replace(MyItem.HTMLBody, "Dear Person,", "Dear " & name)
'...
Set safeItem = CreateObject("Redemption.SafeMailItem")
Set oItem = MyItem
safeItem.Item = oItem
'this next line displays the email, and as of this line, it looks correct
'safeItem.Display
'but as of this line, the issue occurs
safeItem.HTMLBody = "<p>This is an extra message that shows up before the .msg file</p>" & safeItem.HTMLBody
safeItem.Recipients.ResolveAll
safeItem.Send
Now when the email is sent, the .msg contents aren't present at all -- the only thing that shows up is the "extra message" that I prepended to the HTMLBody.
What do I need to change or update? Is this something I need to change in the code, or in my Outlook settings, etc?
Extra: body insertion:
Function insertStringBodyTag(htmlBody As String, stringToInsert As String)
Dim s As String
Dim i As Integer
s = htmlBody
i = InStr(1, s, "<body")
i = InStr(i, s, ">")
s = Left(s, i) & stringToInsert & Right(s, Len(s) - i)
insertStringBodyTag = s
End Function
'Called with safeItem.htmlBody = insertStringBodyTag(safeItem.htmlBody, prefix_string)
You cannot concatenate 2 HTML strings and expect a valid HTML string back - the two must be merged - find the position of the "<body"substring in the original HTML body, then find the positon of the following ">" (this way you take care of the body element with attributes), then insert your HTML string following that ">".

Ms Access - Button with code doesn't work to send email

I have this code set in access, but no email is sending upon clicking the button on the form. I have outlook open. When i click the button on the form, i can't see anything that actually happens. I want the email address to be equal to the value in [text1], and I am trying to make the subject include a fixed message plus the input from [text2]. Even without these variables, I can't get this to work
Public Sub Command495_Click()
Dim mailto As String
Dim ccto As String
Dim bccto As String
mailto = [text1]
ccto = ""
bccto = ""
emailmsg = "trial"
mailsub = [text2] & ", Does this work?"
On Error Resume Next
DoCmd.SendObject acSendNoObjectType, , acFormattxt, mailto, ccto, bccto, mailsubj, emailmsg, True
End Sub
I have checked to make sure the onclick property shows event procedure. I am stuck, please help!
Here are a few suggestions and a modified version of your code.
ALWAYS use Option Explicit and compile your module before testing. You had a number of variables that were not defined and incorrect spelling of some options.
NEVER bypass errors when testing (get rid of your "On Error Resume Next") That's why you never saw an error.
Look for every place I entered ">>>" and address that issue.
Always explicitly define your variables and use the proper Type. Removes all doubt of what/where something is.
Option Compare Database
Option Explicit
Public Sub Command495_Click()
Dim mailto As String
Dim ccto As String
Dim bccto As String
Dim emailmsg As String
Dim mailsub As String
mailto = [Text1] ' >>> Where is [Text1]?? Remove for testing
ccto = ""
bccto = ""
emailmsg = "trial"
mailsub = [Text2] & ", Does this work?" ' >>> Where is [Text2]?? Remove for testing
' >>> Bad idea to ignore errors when testing!!
On Error Resume Next
'>>> Following line had: (1) 'acSendNoObjectType' which is incorrect; (2) mailsubj, which is undefined
DoCmd.SendObject acSendNoObject, , acFormatTXT, mailto, ccto, bccto, mailsub, emailmsg, True
End Sub

sending outlook based email in VBScript - error (sfile as string) line?

im trying to send an email from a VBScript, it will eventually be added into a currently working script as an else if (if this is possible).
im getting an error at line 23 character 32?
Dim outobj, mailobj
Dim strFileText
Dim objFileToRead
Set outobj = CreateObject("Outlook.Application")
Set mailobj = outobj.CreateItem(0)
strFileText = GetText("C:\test\test 2.txt")
With mailobj
.To = "user#user.com"
.Subject = "Testmail"
.Body = strFileText
.Display
End With
Set outobj = Nothing
Set mailobj = Nothing
End Sub
Function GetText(sFile as String) As String
Dim nSourceFile As Integer, sText As String
nSourceFile = FreeFile
Open sFile For Input As #nSourceFile
sText = Input$(LOF(1), 1)
Close
GetText = sText
End Function
what do i need to add to get line 23 to work and the script to finally do what i need it to, i have copied most of this script from elsewhere due to a sincere lack of VBscripting knowledge?
Take a look at the Using Automation to Send a Microsoft Outlook Message article. It provides a sample code and describes all the required steps for sending emails.
Try this: remove the GetText function entirely, and replace the line
strFileText = GetText("C:\test\test 2.txt")
with
Set fso = CreateObject("Scripting.FileSystemObject")
strFileText = fso.OpenTextFile("C:\test\test 2.txt").ReadAll

excel vba inputbox

I am have the following code for excel vba that will email a range of addresses in my sheet. Howeve, I am looking to maybe use an inputbox to determine what the range is that I would like to email. The trouble i run into is getting the input to become a value that the function mailid understands. any suggestions?
Sub EmailActiveSheetWithOutlook2()
Dim oApp, oMail As Object, _
tWB, cWB As Workbook, _
FileName, FilePath As String
Application.ScreenUpdating = False
'Set email id here, it may be a range in case you have email id on your worksheet
Sheets("Sheet1").Select
mailId = Range("b4:b5").Value
'Write your email message body here , add more lines using & vbLf _ at the end of each line
Body = "Hello, it appears you have not yet filled out the transportation contact information excel sheet. This sheet was emailed to you, please complete this and send to me saved as your firstnamelastname.xls at your earliest convience." & vbLf _
& vbLf _
& "Thanks & Regards" & vbLf _
& vbLf _
& "-Ryan " & vbLf _
'Sending email through outlook
Set oApp = CreateObject("Outlook.Application")
Set oMail = oApp.CreateItem(0)
With oMail
.To = mailid
.Subject = "Transportation Committee Notice"
.Body = Body
'.Attachments.Add tWB.FullName
.send
End With
End Sub
To replicate the effect of your current code use
mailid = Application.InputBox(Prompt:="Select Range", Type:=8)
where Type:=8 specifies a return type of Range. This returns the Value property of the selected range into mailid
Alternatively use
Dim rng as Range
Set rng = Application.InputBox(Prompt:="Select Range", Type:=8)
mailid = rng.Value
rng is then set to the selected range, and can be validated before use
Note that you should add error handling to account for, eg user Cancelling the InputBox
Do not set Application.ScreenUpdating = False before issuing InputBox as this will prevent the user interacting with the screen.
As an aside, your code uses Dim incorrectly: Dim'ing a variable without a As clause declares it as `Variant.
eg
Dim oApp, oMail As Object
actually declares oApp as a Variant, use
Dim oApp As Object, oMail As Object