Open Drafts (or selected emails) add BCC, subject, and send - vba

My VBA experience is incredibly limited.I have created basic macros for excel primarily by frankensteining multiple macros I find online together.
Here's what I am looking to do. Every morning I send out an email to a list of 200 customers, I open the new message from a list and the message auto populates (as it is a signature). Currently I then go through all these emails and add my subject and BCC. Could I possibly create a macro to open all of these emails, add my BCC, add my subject, and then send the emails.
Any and all help is much appreciated.

The following code defines an instance of Outlook.Application, and sets up a MailItem ready for sending. It uses a Dictionary object called EmailData to hold the various bits of info to populate To, BCC etc but those can be replaced with your own strings etc. I've pulled this from a function I wrote and made it a little more generic:
Public Function OL_SendMail()
Dim bOpenedOutlook, sComputer, iLoop, iAccount, sAttachArray, sAttachment
bOpenedOutlook = False
sComputer = "."
Dim oWMIService : Set oWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")
Dim colItems : Set colItems = oWMIService.ExecQuery ("Select * from Win32_Process Where Name = 'outlook.exe'")
Dim oOutlook : Set oOutlook = CreateObject("Outlook.Application")
Dim oNamespace : Set oNamespace = oOutlook.GetNamespace("MAPI")
If colItems.Count = 0 Then
' Outlook isn't open, logging onto it...
oNamespace.Logon "Outlook",,False,True
bOpenedOutlook = True
End If
Dim oFolder : Set oFolder = oNamespace.GetDefaultFolder(olFolderInbox)
If EmailData("SendFrom") = "" Then
' default to first email account the user has access to
iAccount = 1
Else
' Checking to see if the account to send from is accessible by this user...
iAccount = 0
For iLoop = 1 To oOutlook.Session.Accounts.Count
If UCase(Trim(oOutlook.Session.Accounts.Item(iLoop))) = UCase(Trim(EmailData("SendFrom"))) Then
iAccount = iLoop
Exit For
End If
Next
If iAccount = 0 Then
sErrorMsg = "Cannot send email from specified account: " & EmailData("SendFrom") & " as this user doesn't appear to have access to it in Outlook!"
OL_SendMail = False
Exit Function
End If
End If
Dim oMailItem : Set oMailItem = oOutlook.CreateItem(olMailItem)
With oMailItem
Set .SendUsingAccount = oOutlook.Session.Accounts.Item(iAccount)
.To = EmailData("To")
.CC = EmailData("CC")
.BCC = EmailData("BCC")
.Subject = EmailData("Subject")
.Body = EmailData("Body")
sAttachArray = Split(EmailData("AttachmentPaths"), ";")
For Each sAttachment In sAttachArray
.Attachments.Add(sAttachment)
Next
.Recipients.ResolveAll
.Display ' debug mode - uncomment this to see email before it's sent out
End With
'Mail Item created and ready to send
'oMailItem.Send ' this is commented out so the mail doesn't auto send, allows checking of it!!
Set oMailItem = Nothing
Set oNamespace = Nothing
If bOpenedOutlook Then
'oOutlook.Quit
End If
Set oOutlook = Nothing
Set colItems = Nothing
Set oWMIService = Nothing
OL_SendMail = True
End Function

Related

Outlook VBA: Using Word Inspector to create a Follow Up Meeting Invite

I am creating a VBA Macro in Outlook that will copy an existing meeting invite and create a follow up meeting invite. It should be fairly easy since I have all the parts to this puzzle.
My problem is with the body of the invite; all formatting and pictures are lost. For this reason, I need to use the Word Inspector object to preserve any special formatting and images. I figured out the code using Word and recording a macro.
So I have figured out the code for copying text using the Word Inspector, but I am not sure on how to paste it in another invite.
Sub copyPaste()
Dim objOL As Outlook.Application
Dim objNS As Outlook.NameSpace
On Error Resume Next
Set objOL = Application
If objOL.ActiveInspector.EditorType = olEditorWord Then
Set objDoc = objOL.ActiveInspector.WordEditor
Set objNS = objOL.Session
Set objSel = objDoc.Windows(1).Selection
objSel.WholeStory
objSel.Copy
objSel.PasteAndFormat (wdFormatOriginalFormatting)
End If
Set objOL = Nothing
Set objNS = Nothing
End Sub
Please see my current Outlook code:
Sub scheduleFollowUpMeeting()
'Declarations
Dim obj As Object
Dim Sel As Outlook.Selection
'Selecting the Email
If TypeOf Application.ActiveWindow Is Outlook.Inspector Then
Set obj = Application.ActiveInspector.currentItem
Else
Set Sel = Application.ActiveExplorer.Selection
If Sel.Count Then
Set obj = Sel(1)
End If
End If
If Not obj Is Nothing Then
MsgBox "The original meeting has been copied." & vbCrLf & "Please kindly update any new details like date/time.", , "Follow Up Meeting - Amit P Shah"
Dim objFollowUp As Outlook.AppointmentItem
Set objFollowUp = Application.CreateItem(olAppointmentItem)
'Copies existing details from original Invite
With objFollowUp
.MeetingStatus = olMeeting
.Subject = "Follow Up: " & obj.Subject
.Body = obj.Body
.Start = Now + 1 'Takes today's date and adds 1 day
.End = DateAdd("n", obj.Duration, .Start)
'Other
.AllDayEvent = obj.AllDayEvent
.BusyStatus = obj.BusyStatus
.Categories = obj.Categories
.Companies = obj.Companies
.ForceUpdateToAllAttendees = obj.ForceUpdateToAllAttendees
.Importance = obj.Importance
.Location = obj.Location
.OptionalAttendees = obj.OptionalAttendees
.ReminderMinutesBeforeStart = obj.ReminderMinutesBeforeStart
.ReminderOverrideDefault = obj.ReminderOverrideDefault
.ReminderPlaySound = obj.ReminderPlaySound
.ReminderSet = obj.ReminderSet
.ReminderSoundFile = obj.ReminderSoundFile
.ReplyTime = obj.ReplyTime
.RequiredAttendees = obj.RequiredAttendees
.Resources = obj.Resources
.ResponseRequested = obj.ResponseRequested
.Sensitivity = obj.Sensitivity
.UnRead = obj.UnRead
.Display
End With
End If
End Sub
Any help would greatly be appreciated. Many thanks in advance!
I'm not a specialist on this subject but i used to work and manipulate Outlook's AppointmentItem in C# and that's how i see the thing.
Actually, if you try to copy the body of a meeting on another meeting, like you said, you will lose all the special formating, images, etc.
The new body will only contain the caracters without format.
I think you can't put formatted text on the body property, you have to use the rtfbody property or like you did when you copy the body of your original appointment, use the WordEditor property in the Inspector object.
So, try to use the WordEditor of the new Item you're creating (like you did to take the original content) and to add content in it.
That's what i had to do for putting formatted text in the body of an AppointmentItem in C#.
I did something like that :
Word.Document myDoc = myItem.GetInspector.WordEditor;
Word.Paragraphs paragraphs = myDoc.Content.Paragraphs;
Word.Paragraph para = paragraphs.Add();
para.Range.Text = yourFormattedTextHere;
After that, you may need to release the variables created, but i'm not sure about that.

Reply body conditioned by mailbox it is sent from

So I have multiple mailboxes under my Outlook account and I am trying to get them to generate reply template based on the mailbox I am replying from (one is private, one is shared). I have tried to base the condition on SenderName and SenderEmailAddress, but to no avail (reply email gets generated with the contents of the previous email retrieved but the text I intend to put in front of it is not there; the cause is that the value of oReply.SenderEmailAddress is empty as Else clause will write the stuff as intended).
(and yes, there are snippets from code enabling reply with attachments)
Sub ReplyWithAttachments()
Dim oReply As Outlook.MailItem
Dim oItem As Object
Dim sSignature As String
Set oItem = GetCurrentItem()
If Not oItem Is Nothing Then
Set oReply = oItem.Reply
If oReply.SenderEmailAddress = "mailbox.private#something.com" Then
sSignature = "Hello and welcome!"
ElseIf oReply.SenderEmailAddress = "mailbox.shared#something.com" Then
sSignature = "Go to hell!"
End If
CopyAttachments oItem, oReply
oReply.HTMLBody = sSignature & oReply.HTMLBody
oReply.Display
oItem.UnRead = False
End If
Set oReply = Nothing
Set oItem = Nothing
End Sub
Edit:
so I managed to get somewhere with
Set oReply = oItem.Reply
sMailBox = oReply.Sender.GetExchangeUser.Address
If sMailBox = "mailbox.private#something.com" Then
sSignature = "whatever"
ElseIf sMailBox = "mailbox.shared#something.com" Then
sSignature = "bla bla bla"
Else
sSignature = "Something"
The code works as intended for the shared mailbox but for the private one, it errors out with Object variable or With block variable not set pointing to .Sender
sMailBox = oReply.Sender.GetExchangeUser.Address
I have something that I use to get sender email (as its dependent on your email exchange)
Dim strSendersEmailAddress As String
If oItem.SenderEmailType = "EX" Then
strSendersEmailAddress = oItem.Sender.GetExchangeUser.PrimarySmtpAddress
Else
strSendersEmailAddress = oItem.SenderEmailAddress
End If
You will have to get the email address before you Set oReply = oItem.Reply

Create a Dynamic Outlook Email using Access VBA

Here is my current setup...
I have an Access project tracking database with project description values (example: Project_ID) and I have a button "Create Email" which I've successfully gotten to open Outlook, pick an Outlook draft, and automatically generate the appropriate subject line.
However, I have no clue where to start on this next step. Any help is appreciated!
I would like the Outlook email to have dynamic fields that are linked to the fields in my Access database. I'm not even sure if I should be trying to code in Access or in Outlook for this step!
Example of what I want:
NAME,
Attached are your documents for:
Project_ID Project_Name Project_Type <--Values from my Access
database
Sincerely,
my signature
you should code in MS Access.
a pseudo code would be:
Read all values from your access table
create outlook object, mail object
Open outlook mail and add subject, content, attachments
send or leave it to the employee to send
call this like
send_email_message "to#to.to","","","Email subject","Add your email content/body like project id= &field1, project name = field2 and so on"
you can attach more than one file just join the document name with a ";" delimiter. like
"C;\file1.txt;c:\File2.txt"
here a sending email function:
this function uses outlook objects (import them in reference)
or change it to late binding by vba.createobject("outlook.application")
Function SEND_EMAIL_MESSAGE(mTo As String, mCC As String, mBC As String, mSubject As String, mBody As String, Optional useOwnSignature As Boolean = False, Optional DisplayMsg As Boolean = False, Optional isHTML As Boolean = False, Optional AttachmentPath = "") As Boolean
'---------------------------------------------------------------------------------------
' Procedure : SEND_EMAIL_MESSAGE
' Author : KRISH KM
' Date : 01/09/2013
' Purpose : Send emails using outlook
'---------------------------------------------------------------------------------------
'
' Please check the reference for Microsoft Outlook 14.0 object library for outlook 2010.
Dim oAPP As Outlook.Application
Dim oMail As Outlook.MailItem
Dim oAPPAttach As Outlook.Attachment
Dim mSignature As String
On Error GoTo ERROR_EMAIL
' Create the Outlook session.
Set oAPP = New Outlook.Application
' Create the message.
Set oMail = oAPP.CreateItem(olMailItem)
With oMail
' Add the To recipient(s) to the message.
.to = mTo
.cc = mCC
.BCC = mBC
.Subject = mSubject
If useOwnSignature Then .BodyFormat = olFormatHTML
.Display
If useOwnSignature Then
If isHTML Then
mSignature = .HTMLBody
.HTMLBody = mBody & mSignature
Else
mSignature = .body
.body = mBody & mSignature
End If
Else
.body = mBody
End If
' Add attachments to the message.
If Not IsMissing(AttachmentPath) Then
Dim mFiles() As String
If (VBA.Right(AttachmentPath, 1)) <> ";" Then AttachmentPath = AttachmentPath & ";"
mFiles = VBA.Split(AttachmentPath, ";")
Dim i As Integer
For i = 0 To UBound(mFiles) - 1
If Not mFiles(i) = "" Then .Attachments.Add (mFiles(i)) 'Set oAPPAttach = .Attachments.Add(mFiles(i))
Next i
End If
' Should we display the message before sending?
If DisplayMsg Then
.Display
Else
.Send
End If
End With
SEND_EMAIL_MESSAGE = True
EXIT_ROUTINE:
On Error GoTo 0
Set oAPP = Nothing
Set oMail = Nothing
Exit Function
ERROR_EMAIL:
SEND_EMAIL_MESSAGE = False
GoTo EXIT_ROUTINE
End Function

Extract AddressEntry object details for Exchange User

Is there a way to extract the details in this dialog box via VBA?
Details Dialog Box http://i.msdn.microsoft.com/dynimg/IC84336.gif
I need, especially the content in the E-Mail address tab.
You can pretty much get the fields easily, the E-mail Addresses is the harder part. References: Microsoft Exchange Property Tags
This code exports some details but most importantly the Email addresses to a text file.
Sub ListGAL()
On Error Resume Next
Const LogFile = "C:\Test\OLK_GAL.log"
Const sSCHEMA = "http://schemas.microsoft.com/mapi/proptag/0x"
Const PR_EMS_AB_PROXY_ADDRESSES = &H800F101E
Dim oNameSpace As NameSpace, oGAL As AddressList, oEntry As AddressEntry
Dim oFSO As Variant, oLF As Variant, oExUser As ExchangeUser, i As Long
' Oulook objects
Set oNameSpace = Outlook.Application.GetNamespace("MAPI")
' Global Address List object
Set oGAL = oNameSpace.AddressLists("Global Address List")
'----------
' Log file objects
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oLF = oFSO.CreateTextFile(LogFile)
'----------
For Each oEntry In oGAL.AddressEntries
i = i + 1
Debug.Print i & vbTab & oEntry.Name
If oEntry.AddressEntryUserType = olExchangeUserAddressEntry Then
oLF.WriteLine "Entry " & i & " (olExchangeUserAddressEntry)"
oLF.WriteLine "Name: " & oEntry.Name
oLF.WriteLine "Address: " & oEntry.Address
Set oExUser = oEntry.GetExchangeUser
' SMTP ADDRESSES
oLF.WriteLine "SMTP Addresses:"
oLF.WriteLine vbTab & Join(oExUser.PropertyAccessor.GetProperty(sSCHEMA & Hex(PR_EMS_AB_PROXY_ADDRESSES)), vbCrLf & vbTab)
Set oExUser = Nothing
oLF.WriteLine String(50, Chr(151)) ' Separator
End If
Next
'----------
' Close Log File, clean up
oLF.Close
Set oGAL = Nothing
Set oNameSpace = Nothing
Set oLF = Nothing
Set oFSO = Nothing
End Sub
i have go a function of reading the address-book:
Function Get_mail(Absender As String)
Dim OutApp As Outlook.Application
Dim OutTI As Outlook.TaskItem
Dim OutRec As Outlook.Recipient
Set OutApp = New Outlook.Application
Set OutTI = OutApp.CreateItem(3)
OutTI.Assign
Set OutRec = OutTI.Recipients.Add(Absender)
OutRec.Resolve
If OutRec.Resolved Then
On Error GoTo exit_function
Get_mail = OutRec.AddressEntry.GetExchangeUser.PrimarySmtpAddress
End If
exit_function: Exit Function
Set OutApp = Nothing
Set OutTI = Nothing
End Function
as far as I know you can only read out the Primary Mail-address from the mail-addresses-tab; to see what else there ist delete the part ".PrimarySmtpAddress", mahe the dot and you should get the list of other properties.
I am quite sure you need the reference on Microsoft Outlook 14.0 Object Library.
The Input "Absender" can be any string . if this string can be resolved as address book-entry in an outlook-mail, you will also have a positive result from the code above.
To call the function, if for example you have a string "mail_adress_from_adressbook" you would put:
mail_adress_from_adressbook = get_mail("Joe Smith")
I hope this helps,
Max
Sure, you can access any GAL object property shown by Outlook (and then some) even if the properties are not explicitly exposed by the AddressEntry or ExchangeUser objects using AddressEntry.PropertyAccessor.GetProperty as long as you know the MAPI property's DASL name
The DASL property names can be retrieved using OutlookSpy (I am its author): either click IAddrBook button to drill down to a particular address entry or, if you have a message addressed to one of the GAL recipients, click IMessage button, go to the GetRecipientTable tab, double click on the recipient to open it as IMailUser:
In your particular case, you need PR_EMS_AB_PROXY_ADDRESSES (DASL name "http://schemas.microsoft.com/mapi/proptag/0x800F101F") - it is a multivalued string property, which means AddressEntry.PropertyAccessor.GetProperty will return an array of strings. Each value is prefixed with the address type (e.g. "EX:" or "smtp:"), the default SMTP address will be prefixed with "SMTP:" (note the upper case):
Set User = Application.session.CurrentUser.AddressEntry
AddressList = User.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x800F101F")
If IsArray(AddressList) Then
For i = LBound(AddressList) To UBound(AddressList)
MsgBox AddressList(i)
Next
End If

How to add an embedded image to an HTML message in Outlook 2010

I have Office 2003 VBA code that uses the technique described here to embed an image in an HTML message using undocumented MAPI properties and CDO 1.21.
CDO 1.21 is no longer supported, but according to MSDN, most of its functionality is now incorporated into the Outlook 2010 object model.
Where can I find a sample that embeds images in an Outlook 2010 message using the Outlook 2010 object model?
Found the answer here.
The key bits being:
Const PR_ATTACH_MIME_TAG = "http://schemas.microsoft.com/mapi/proptag/0x370E001E"
Const PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001E"
Const PR_ATTACHMENT_HIDDEN = "http://schemas.microsoft.com/mapi/proptag/0x7FFE000B"
...
Set colAttach = l_Msg.Attachments
For x = 1 To Items.Count
Set l_Attach = colAttach.Add(Items.Item(x))
Set oPA = l_Attach.PropertyAccessor
oPA.SetProperty PR_ATTACH_MIME_TAG, ItemTypes.Item(x)
oPA.SetProperty PR_ATTACH_CONTENT_ID, "item" & x
oPA.SetProperty PR_ATTACHMENT_HIDDEN, True
Next
Here other example:
Option Explicit
'Add reference to MS Outlook x.x Object Library
'Picture to be added as an attachment and modified src location for each embedded picture.
Private Sub Command1_Click()
Dim oApp As Outlook.Application
Dim oEmail As MailItem
Dim colAttach As Outlook.Attachments
Dim oAttach As Outlook.Attachment
'create new Outlook MailItem
Set oApp = CreateObject("Outlook.Application")
Set oEmail = oApp.CreateItem(olMailItem)
'add graphic as attachment to Outlook message
'change path to graphic as needed
Set colAttach = oEmail.Attachments
Set oAttach = colAttach.Add("D:\my documents\[color=red]MyPic.jpg[/color]")
oEmail.Close olSave
'change the src property to 'cid:your picture filename'
'it will be changed to the correct cid when its sent.
oEmail.HTMLBody = "<BODY><FONT face=Arial color=#000080 size=2></FONT>" & _
"<IMG alt='' hspace=0 src='[color=red]cid:MyPic.jpg[/color]' align=baseline border=0> </BODY>"
oEmail.Save
oEmail.Display 'fill in the To, Subject, and Send. Or program it in.
Set oEmail = Nothing
Set colAttach = Nothing
Set oAttach = Nothing
Set oApp = Nothing
End Sub
you can find it on:
http://www.vbforums.com/showthread.php?278600-VB-Embedd-an-image-into-an-Outlook-email-message-body
This is a vb code snippet by Dmitry Streblechenko (MVP). It worked fine for me.
Set objOutlook = CreateObject("Outlook.Application")
Set Ns = objOutlook.GetNamespace("MAPI")
Ns.Logon
Set objOutlookMsg = objOutlook.CreateItem(olMailItem)
Set objOutlookRecip = objOutlookMsg.Recipients.Add("test#dimastr.com")
objOutlookRecip.Type = olTo
objOutlookMsg.Subject = "test"
' add graphic as attachment to Outlook message
Set colAttach = objOutlookMsg.Attachments
Set l_Attach = colAttach.Add("z:\Temp\8\1.jpg ")
l_Attach.PropertyAccessor.SetProperty "http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/jpeg" '
Change From 0x370eE001E
l_Attach.PropertyAccessor.SetProperty "http://schemas.microsoft.com/mapi/proptag/0x3712001F", "myident"
'Changed from 0x3712001E
objOutlookMsg.PropertyAccessor.SetProperty "http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", True
'
Set body format to HTML
objOutlookMsg.BodyFormat = olFormatHTML
objOutlookMsg.HTMLBody = "html tags goes here< img align="
baseline " order="
1 " hspace="
0 " src="
cid: myident " width="
" 600="
" > </img> end html tags"
objOutlookMsg.Save
objOutlookMsg.Send
Here is the method I've found works the best for me. I used to just link to the subfolder but found some international users experienced huge lag and even crashed there inbox. I switched to the below so that the image was imbedded in the email and it solved the lag issues because the file is actually embedded in the email.
Sub sendKeyMailer()
Dim emlMsg As Object
Set emlMsg = CreateObject("CDO.Message")
strBody = "<html> yadda yadda tricks are for kids. <br><br>"
strBody = strBody & "<img src=""cid:myimage.jpg""><BR><BR>"
strBody = strBody & "but tricks make the world go round.</html>"
emlMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
emlMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "<<yourserver>>"
emlMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
emlMsg.Configuration.Fields.Update
emlMsg.AddRelatedBodyPart "C:\temp\The Big Eskimo Roll.jpg", "myimage.jpg", cdoRefTypeId
emlMsg.Fields.Item("urn:schemas:mailheader:Content-ID") = "<myimage.jpg>"
emlMsg.Fields.Update
With emlMsg
.To = "allthepeople#yourcompany.com"
.From = "aGrpLst#yourcompany.com"
.Subject = "Humpty dumpty had a great fall" '''I have kids....;^D.....
.HTMLbody = strBody
'.AddAttachment "C:\temp\The Big Eskimo Roll.jpg"
.Send
End With
Set emlMsg = Nothing
End Sub