VBA - Convert Exchange Online Email Address as SMTP Address - vba

I get the exchange online addresses from users, but I want to convert or somehow get the SMTP Address of them.
I am not sure how to get the SMTP Address from Email1Address.
Set objOL = CreateObject("Outlook.Application")
Set objNS = objOL.GetNamespace("MAPI")
Set objContactsFolder = objNS.GetDefaultFolder(olFolderContacts)
Set objItems = objContactsFolder.Items
For Each obj In objItems
'Test for contact and not distribution list
If obj.Class = olContact Then
Set objContact = obj
With objContact
If .Email1Address <>"" Then
'I want to add the SMTP-Address after the .LastNameAndFirstName of a User
strFileAs = .LastNameAndFirstName
.Email1DisplayName= strFileAs
.Save
End If
End With
End If
Err.Clear
Next

I used this for the email object, see if you can implement it:
dim email as string
If myItem.SenderEmailType = "EX" Then
email = myItem.Sender.GetExchangeUser.PrimarySmtpAddress
Else
email = myItem.SenderEmailAdress
End If

Related

Reply to Meeting Request from non-default Account

When replying to a meeting invite sent to a non-default account in Outlook 365 desktop, it typically responds from the default account. The following code fixed that problem, but recently stopped working correctly.
My replies used to say, "Yes, NONdefaultrecipientemail#gmail.com will attend" "From: nondefaultrecipientemail#gmail.com."
Now it says, "Yes, Defaultemail#gmail.com will attend" "From: nondefaultrecipientemail#gmail.com on behalf of Defaultemail#gmail.com."
Any ideas on why this no longer works and how to fix it?
Thanks!
Sub MeetingResponse(myAction As String)
'If a meeting request is sent to the non-default email address, replies, etc., will normally come from the default email.
'This macro changes the send from email address to the correct one.
Dim myNameSpace As Outlook.NameSpace
Dim myAppt As Outlook.AppointmentItem
Dim oMtgResponse, oReplyForward, oMtgRequest As Outlook.MeetingItem
Dim oAccount As Outlook.Account
Dim SendAcct As Variant
Dim SendEmailAddr As String
Dim FolderParent As String
Set myNameSpace = Application.GetNamespace("MAPI")
'Determine which account invite was sent to.
FolderParent = Application.ActiveExplorer.CurrentFolder.Parent
For Each oAccount In Application.Session.Accounts
If oAccount.DeliveryStore.GetDefaultFolder(olFolderInbox).Parent = FolderParent Then
SendAcct = oAccount.DisplayName
Exit For
End If
Next
Set oMtgRequest = GetCurrentItem()
If TypeName(oMtgRequest) <> "Nothing" Then
Set myAppt = oMtgRequest.GetAssociatedAppointment(True)
'Set send from account
For Each oAccount In Application.Session.Accounts
If oAccount = SendAcct Then
Select Case UCase(myAction)
Case "ACCEPT"
Set oMtgResponse = myAppt.Respond(olResponseAccepted, True)
oMtgResponse.SendUsingAccount = oAccount
oMtgResponse.Display
oMtgRequest.Delete
Case "DECLINE"
Set oMtgResponse = myAppt.Respond(olResponseDeclined, True)
oMtgResponse.SendUsingAccount = oAccount
oMtgResponse.Display
oMtgRequest.Delete
'Original inviter may be notified this was forwarded.
Case "FORWARD"
Set oReplyForward = oMtgRequest.Forward
oReplyForward.SendUsingAccount = oAccount
oReplyForward.Display
'Original inviter will not be notified this was forwarded.
'Creates new appointment based on original one.
Case "FORWARDSILENT", "FORWARD SILENT"
Dim oAppt As AppointmentItem
Set oAppt = Application.CreateItem(olAppointmentItem)
With oAppt
.MeetingStatus = olMeeting
.Subject = "Accepted: " & myAppt.Subject
.Start = myAppt.Start
.Duration = myAppt.Duration
.Location = myAppt.Location
.Body = myAppt.Body
.Display
.SendUsingAccount = oAccount
End With
Case "REPLY"
Set oReplyForward = oMtgRequest.reply
oReplyForward.SendUsingAccount = oAccount
oReplyForward.Display
Case "FORWARDASATTACHMENT", "FORWARD AS ATTACHMENT"
Case Else
MsgBox "Could not process! Incorrect action provided.", vbCritical + vbOKOnly
End Select
Exit For
End If
Next
End If
End Sub 'MeetingResponse
The MeetingItem.SendUsingAccount property allows setting an Account object that represents the account to use to send the MeetingItem. But in your code you are trying to set the property to a string which contains the display name of the Account chosen.
Declare an instance of the Account class in the code and initialize it in the following way:
FolderParent = Application.ActiveExplorer.CurrentFolder.Parent
For Each oAccount In Application.Session.Accounts
If oAccount.DeliveryStore.GetDefaultFolder(olFolderInbox).Parent = FolderParent Then
Set SendAcct = oAccount
Exit For
End If
Next
Then you can set the MeetingItem.SendUsingAccount property correctly:
oMtgResponse.SendUsingAccount = oAccount

Fetch the manager from an email address

I'm trying to get the "Manager" of a specific person (and hopefully iterate for a targeted list after). How to do this for a specific email address and not the Global Address List?
Dim appOL As Outlook.Application ' Object
Dim oGAL As Outlook.AddressEntries ' .NameSpace Object
Dim oContact As Outlook.AddressEntry ' Object
Dim oUser As ExchangeUser ' Object
Set appOL = New Outlook.Application ' CreateObject("Outlook.Application")
Set oGAL = appOL.GetNameSpace("MAPI").AddressLists("Global Address List").AddressEntries("first.last#email.com")
oContact = oGAL.Item(1)
MsgBox oContact.Manager
Replace the lines
Set oGAL = appOL.GetNameSpace("MAPI").AddressLists("Global Address List").AddressEntries("first.last#email.com")
oContact = oGAL.Item(1)
with the following (assuming you are working with a selected message in Outlook):
if appOL.ActiveExplorer.Selection.Count > 0 Then
set msg = appOL.ActiveExplorer.Selection(1)
set sender = msg.Sender
if Not (sender is null) Then
set manager = sender.Manager
End If
End If
If you are working with an one-off name, use something like
set recip = appOL.Session.CreateRecipient("The name to resolve")
if recip.Resolve Then
set manager = recip.AddressEntry.Manager
End If

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

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

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

Add bcc recipients using Outlook VBA

I need to add bcc recipients to an email loaded from a template. The recipients should be all of the contacts in a certain category. I have the following so far, except it is extremely inefficient and causes Outlook to become unresponsive:
Sub Distribute_Newsletter()
Set newItem = Application.CreateItemFromTemplate("P:\Subscription Templates\subscription template.oft")
newItem.Display
Set oNS = Application.GetNamespace("MAPI")
Set oContacts = oNS.Folders(1).Folders("Contacts")
Dim emailAddress As String
For Each oContactItem In oContacts.Items
If oContactItem.Class = olContact Then
emailAddress = oContactItem.Email1Address
If Not emailAddress = "" Then 'And oContactItem.Categories
Set objRecip = newItem.Recipients.Add(emailAddress)
objRecip.Type = olBCC
End If
End If
Next
Set oNS = Nothing
Set oContacts = Nothing
Set objRecip = Nothing
Set newItem = Nothing
End Sub
What I ended up doing was moving newItem.Display down to just before Set newItem = Nothing. This may not be the most efficient solution, but it gets the job done without causing a crash.