Subject not being replaced by VBA Macro - vba

Okay so, I'm trying to edit this code I found that allows me to input variable information into a pop up box for emails. This is great and works flawlessly (although kinda slow), however I'm running into a weird issue trying to do the same thing with the subject line as well.
Using one template that I have set up, working template I get exactly what I'm looking for, it goes through all 4 of the variables INCLUDING the one on the subject line.
However, if I use a different template with the same variables, Not working template, it doesn't replace the subject line. The other two variables in the broken template pop up the dialog box - example
Can someone help fill me in on why it works on one template but not the other?
Full code:
Private WithEvents m_Inspectors As Outlook.Inspectors
Private WithEvents m_Inspector As Outlook.Inspector
Private Sub Application_Startup()
Set m_Inspectors = Application.Inspectors
End Sub
Private Sub m_Inspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
If TypeOf Inspector.CurrentItem Is Outlook.MailItem Then
'Handle emails only
Set m_Inspector = Inspector
End If
End Sub
Private Sub m_Inspector_Activate()
Dim Item As MailItem
Dim Value As String
If TypeOf m_Inspector.CurrentItem Is MailItem Then
Set mail = m_Inspector.CurrentItem
'Identify the message subject
If mail.Subject = "FMAudit Legacy Install [custbusiness]" Or mail.Subject = "FMAudit Install [custbusiness]" Then
'Check message format
If mail.BodyFormat = OlBodyFormat.olFormatPlain Then
'Replace [date] with the entered value
If InStr(mail.Body, "[custname]") > 0 Then
Value = InputBox("Enter the customer name")
If Value <> "" Then
mail.Body = Replace(mail.Body, "[custname]", Value)
End If
End If
'Replace [percent] with the entered value
If InStr(mail.Body, "[custbusiness]") > 0 Then
Value = InputBox("Enter business name")
If Value <> "" Then
mail.Body = Replace(mail.Body, "[custbusiness]", Value)
End If
End If
'Replace [percent] with the entered value
If InStr(mail.Body, "[custhost]") > 0 Then
Value = InputBox("Enter host name")
If Value <> "" Then
mail.Body = Replace(mail.Body, "[custhost]", Value)
End If
End If
Else
'Replace [date] with the entered value
If InStr(mail.HTMLBody, "[custname]") > 0 Then
Value = InputBox("Enter the customer name")
If Value <> "" Then
mail.HTMLBody = Replace(mail.HTMLBody, "[custname]", Value)
End If
End If
'Replace [percent]; with the entered value
If InStr(mail.HTMLBody, "[custbusiness]") > 0 Then
Value = InputBox("Enter business name")
If Value <> "" Then
mail.HTMLBody = Replace(mail.HTMLBody, "[custbusiness]", Value)
End If
End If
'Replace [percent]; with the entered value
If InStr(mail.HTMLBody, "[custhost]") > 0 Then
Value = InputBox("Enter host name")
If Value <> "" Then
mail.HTMLBody = Replace(mail.HTMLBody, "[custhost]", Value)
'Replace [percent] with the entered value
If InStr(mail.Subject, "[custbusiness]") > 0 Then
Value = InputBox("Enter business name subject")
If Value <> "" Then
mail.Subject = Replace(mail.Subject, "[custbusiness]", Value)
End If
End If
End If
End If
End If
End If
Set mail = Nothing
End If
End Sub

Your code could be simplified a lot by creating a separate method which just does the replacements:
Option Explicit
Private WithEvents m_Inspectors As Outlook.Inspectors
Private WithEvents m_Inspector As Outlook.Inspector
Private Sub Application_Startup()
Set m_Inspectors = Application.Inspectors
End Sub
Private Sub m_Inspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
If TypeOf Inspector.CurrentItem Is Outlook.MailItem Then
Set m_Inspector = Inspector 'Handle emails only
End If
End Sub
Private Sub m_Inspector_Activate()
Dim mail As MailItem
If TypeOf m_Inspector.CurrentItem Is MailItem Then
Set mail = m_Inspector.CurrentItem
'Check the message subject
If mail.Subject = "FMAudit Legacy Install [custbusiness]" Or _
mail.Subject = "FMAudit Install [custbusiness]" Then
ReplaceTags mail, "[custname]", "Enter the customer name"
ReplaceTags mail, "[custbusiness]", "Enter business name"
ReplaceTags mail, "[custhost]", "Enter host name"
End If 'matched subject line
End If 'is a mail item
End Sub
'replace tag `sTag` with user-supplied value in `mail` body and subject
Sub ReplaceTags(mail As MailItem, sTag As String, sPrompt As String)
Dim v, oBody As Object
'Check message format and get the body object
If mail.BodyFormat = OlBodyFormat.olFormatPlain Then
Set oBody = mail.Body
Else
Set oBody = mail.HTMLBody
End If
If InStr(oBody, sTag) > 0 Then 'check Body Text
v = Trim(InputBox(sPrompt))
If Len(v) > 0 Then oBody = Replace(oBody, sTag, v)
End If
If InStr(mail.Subject, sTag) > 0 Then 'check Subject text
If Len(v) = 0 Then v = Trim(InputBox(sPrompt)) 'don't re-prompt if already have a value
If Len(v) > 0 Then mail.Subject = Replace(mail.Subject, sTag, v)
End If
End Sub

Related

Add a category for all selected emails using Outlook VBA

I'm trying to add a category to every email selected in Outlook using VBA.
The problem is that the code below adds the category only to the first email.
I'm using Outlook 2016.
Public Sub MarkSelectedAsGreenCategory()
Dim olItem As MailItem
Dim newCategory As String
newCategory = "Green category"
Dim i As Integer
For i = 1 To Application.ActiveExplorer.Selection.Count
Set olItem = Application.ActiveExplorer.Selection(i)
AddCategory olItem, newCategory
Set olItem = Nothing
Next
End Sub
Private Sub AddCategory(mailItem As mailItem, newCategory As String)
Dim categories() As String
Dim listSep As String
' Get the current list separator from Windows regional settings
listSep = CreateObject("WScript.Shell").RegRead("HKEY_CURRENT_USER\Control Panel\International\sList")
' Break the list up into an array
categories = Split(mailItem.categories, listSep)
' Search the array for the new category, and if it is missing, then add it
If UBound(Filter(categories, newCategory)) = -1 Then
ReDim Preserve categories(UBound(categories) + 1)
categories(UBound(categories)) = newCategory
mailItem.categories = Join(categories, listSep)
End If
End Sub
An update to a category on ActiveInspector.CurrentItem would generate a prompt to save.
For a selection:
olItem.Save or mailItem.Save at your convenience.

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

Validating Outlook Email Attachment Name through VB Macro

Im creating an outlook Macro to validate an Email attachment and recipient name before sending the mail.
The recipient name can be easily validated through the ItemSend Function on the Outlook session.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim Recipients As Outlook.Recipients
Dim recip As Outlook.Recipient
Dim i
Dim prompt As String
Set Recipients = Item.Recipients
For i = Recipients.Count To 1 Step -1
Set recip = Recipients.Item(i)
If InStr(LCase(recip), "bad#address.com") Then
prompt$ = "You sending this to this to " & Item.To & ". Are you sure you want to send it?"
If MsgBox(prompt$, vbYesNo + vbQuestion + vbMsgBoxSetForeground, "Check Address") = vbNo Then
Cancel = True
End If
End If
Next i
End Sub
While this helps with recipients, it does not allow to validate the attachment name before sending the mail. i.e Validate the Mail Draft. The code below helps to check for attachments present on the draft but does not help validate it.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If InStr(1, Item.Body, "attach", vbTextCompare) > 0 Then
If Item.Attachments.Count = 0 Then
answer = MsgBox("There's no attachment, send anyway?", vbYesNo)
If answer = vbNo Then Cancel = True
End If
So i tried to add item.Attachment. Name \ item.attachment.FileName but this works only if i attribute it to a outlook MailItem instead of a normal object.
Is it possible to create code to validate the attachment name for certain criteria ( name should conform to certain naming constraints ). The code has already been created and works as a normal macro and not as a session Macro.
Function Segregate_Function(Attach_Name_Pass1 As String)
Dim FullName As String
Dim Recepients As String
Region_Ext = Right(Attach_Name_Pass1, 7)
region = Left(Region_Ext, 3)
'MsgBox region
If region = "ENG" Then
Recepients = "ABC#gmail.com;XYZ#gmail.com"
Call Send_Function(Attach_Name_Pass1, Recepients)
Else
MsgBox " Not an Acceptable Attachment. Mail Could not be Generated "
End If
End Function
I would like the above code to execute when clicking on send to validate an attachment name directly, instead of having a procedural Macro running.
Do advice.
Try testing within ItemSend.
Something like this:
Option Explicit
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim att As attachment
Dim Attach_Name_Pass1 As String
Dim Region_Ext As String
Dim Region As String
Cancel = False
If Item.Attachments.count = 0 Then
If MsgBox("There's no attachment, send anyway?", vbYesNo) = vbNo Then Cancel = True
Else
Debug.Print Item.To
If InStr(Item.To, "ABC#gmail.com") > 0 Or InStr(Item.To, "XYZ#gmail.com") > 0 Then
For Each att In Item.Attachments
Attach_Name_Pass1 = att.DisplayName
Region_Ext = Right(Attach_Name_Pass1, 7)
Region = Left(Region_Ext, 3)
'MsgBox region
Debug.Print Region
If Region <> "ENG" Then
Cancel = True
MsgBox " Not an Acceptable Attachment. Send cancelled."
Exit For
End If
Next
End If
End If
End Sub

How to get the date mentioned in the email into the VBA script in Outlook?

I have created a rule that executed when outlook receives an mail and it will create the appointment on outlook calendar. In that I need to get the date and time mentioned in the mail as the appointment date.
Sub NewMeetingRequestFromEmail(email As MailItem)
Dim app As New Outlook.Application
Dim meetingRequest As AppointmentItem
Set meetingRequest = app.CreateItem(olAppointmentItem)
meetingRequest.Categories = email.Categories
meetingRequest.Body = email.Body
meetingRequest.Subject = email.Subject
meetingRequest.Location = email.Subject
meetingRequest.Start = DateSerial(Year(Now), Month(Now), Day(Now) + 1) + #10:00:00 AM#
meetingRequest.Duration = 60
meetingRequest.ReminderMinutesBeforeStart = 45
meetingRequest.ReminderSet = True
Dim attachment As attachment
For Each attachment In email.Attachments
CopyAttachment attachment, meetingRequest.Attachments
Next attachment
Dim recipient As recipient
Set recipient = meetingRequest.Recipients.Add(email.SenderEmailAddress)
recipient.Resolve
For Each recipient In email.Recipients
RecipientToParticipant recipient, meetingRequest.Recipients
Next recipient
Dim inspector As inspector
Set inspector = meetingRequest.GetInspector
'inspector.CommandBars.FindControl
inspector.Display
meetingRequest.Save
End Sub
Private Sub RecipientToParticipant(recipient As recipient, participants As Recipients)
Dim participant As recipient
If LCase(recipient.Address) <> LCase(Session.CurrentUser.Address) Then
Set participant = participants.Add(recipient.Address)
Select Case recipient.Type
Case olBCC:
participant.Type = olOptional
Case olCC:
participant.Type = olOptional
Case olOriginator:
participant.Type = olRequired
Case olTo:
participant.Type = olRequired
End Select
participant.Resolve
End If
End Sub
Private Sub CopyAttachment(source As attachment, destination As Attachments)
On Error GoTo HandleError
Dim filename As String
filename = Environ("temp") & "\" & source.filename
source.SaveAsFile (filename)
destination.Add (filename)
Exit Sub
HandleError:
Debug.Print Err.Description
End Sub
The Outlook object model provides three main ways for working with item bodies:
Body.
HTMLBody.
The Word editor. The WordEditor property of the Inspector class returns an instance of the Word Document which represents the message body.
See Chapter 17: Working with Item Bodies for more information.

Outlook VBA Mailitem property SenderEmailAddress not returning address correctly

So I have a program in access that lets the user select an outlook folder to import to a table. Which then can be selected from a combobox and transferred across to a form for use.
However I am having a problem with one of the values I am getting returned. SenderEmailAddress is not actually giving me an email address, for example this is what I get saved in my table.
I have removed names for privacy.
/O=COMPANY/OU=MAIL12/CN=RECIPIENTS/CN=FIRSTNAME.LASTNAME
Now of course, if I want to pass this value back over to outlook to reply to the email, I cannot use this.
Can anybody help me please?
Public Sub LoadEmails()
On Error Resume Next
'Outlook wasn't running, start it from code
If Started = False Then
Set olApp = New Outlook.Application '("Outlook.Application")
Started = True
End If
Set myNamespace = olApp.GetNamespace("MAPI")
Set objFolder = myNamespace.PickFolder
' if outlook is closed, it will display this error
If Err <> 0 Then
MsgBox "Outlook was closed. Please log out and log back in."
Started = False
Exit Sub
End If
'Exit if no folder picked.
If (objFolder Is Nothing) Then
MsgBox "No Folder Selected"
Started = False
Exit Sub
End If
Dim adoRS As Recordset
Dim intCounter As Integer
Set adoRS = CurrentDb.OpenRecordset("TBL_UserInbox") 'Open table Inbox
'Cycle through selected folder.
For intCounter = objFolder.Items.Count To 1 Step -1
With objFolder.Items(intCounter)
'Copy property value to corresponding fields
If .Class = olMail Then
adoRS.AddNew
adoRS("Subject") = .Subject
adoRS("TimeReceived") = .ReceivedTime
adoRS("Body") = .Body
adoRS("FromName") = .SenderEmailAddress '<<< Issue
adoRS("ToName") = .To
adoRS.Update
End If
End With
Next
MsgBox "Completed"
Started = False
End Sub
That is a perfectly valid email address of type EX (as opposed to SMTP). Check the MailItem.SenderEmailType property. If it is "SMTP", use the SenderEmailAddress property. If it is "EX", use MailItem.Sender.GetExchangeUser.PrimarySmtpAddress. Be prepared to handle nulls/exceptions.