Home > Enterprise >  Modify HTMLbody of New Email created from default ribbon button?
Modify HTMLbody of New Email created from default ribbon button?

Time:11-13

I've searched for days, piecing together code from other posts around Stack Overflow and from the learn.microsoft.com documentation for a solution to this and I'm struggling... It doesn't help that I'm relatively new to Outlook VBA.

What I want to happen is that when I create a new email using the default ribbon button, automatically add a greeting to the body while also keeping the default signature that is added. (Also wanting this to work for inline replies, but I'm focusing on this first).

I already have a public function that uses TimeValue to calculate whether to add "Good morning," or "Good afternoon,", it works and returns as a string. I call a sister function that takes that string and adds it to the email. This part works.

Both of these are in a module called "AutoGreeting"

Option Explicit

Public Function Greeting() As String
' Defines greeting by time of day '
' Used in with the AddGreeting() function and clsMailHandler '

    ' If before noon, greeting is Good Morning'
    If Time >= TimeValue("8:00 AM") And Time <= TimeValue("11:59 AM") Then
        Greeting = "Good morning,"
    ' If after noon and before work ends, greeting is Good Afternoon'
    ElseIf Time >= TimeValue("12:00 PM") And Time <= TimeValue("5:10 PM") Then
        Greeting = "Good afternoon,"
    End If
End Function

' call this function to add the above calculated greeting to an email '
' i.e. Call AddGreeting(NewlyCreatedEmail)
Public Function AddGreeting(ByRef DraftEmail As mailItem)

' DraftEmail is used with reference to any MailItem object '
' like in clsMailHander > NewInspector > objCurrentItem / objMailNew '

With DraftEmail
    ' Temporarily editing the subject for testing/debugging to make sure this works
    .Subject = "AddGreeting Function"
    ' This adds the greeting but isn't able to keep the OG body AKA the auto-signature
    ' Because newInspector fires before signature is added
    .HTMLBody = Greeting() & DraftEmail.HTMLBody
End With
End Function

I'm also building a class module for event handling that is able to detect when a new inspector opens and that it's a mailitem. (Unfortunately, it's seems it's not able to detect yet whether it's a new email or if it's an email that's been retrieved and opened. like if you double-click an email from your inbox, it opens in an inspector window. I do this by accident sometimes).

Explorers and the objMailReply variable are in there because I also want this to work this inline replies. I have the event handlers for newExplorer and ActiveInlineResponse that I left out here because I'm focusing on just new emails in the inspectors for now.

Class module is called "clsMailHandler"

' Class for event handling of created emails
' re-start Outlook after compiling and saving changes to re-initialize class
' or run Application_Quit and Application_Startup from ThisOutlookSession cls

Option Explicit

Public WithEvents olApp As Outlook.Application
Public WithEvents objInspectors As Outlook.Inspectors
Public WithEvents objActInspector As Outlook.Inspector
Public WithEvents objExplorers As Outlook.Explorers
Public WithEvents objActExplorer As Outlook.Explorer
Public WithEvents objCurrentItem As Outlook.mailItem
Public WithEvents objMailNew As Outlook.mailItem
Public WithEvents objMailReply As Outlook.mailItem

' Called under Application_Startup in ThisOutlookSession as Handler class is created
Public Sub Class_Initialize()
Set olApp = Outlook.Application
' so far, all that's needed here is to initialize the explorers and inspectors w/ the app itself
Set objInspectors = olApp.Inspectors
Set objExplorers = olApp.Explorers
Set objActExplorer = olApp.ActiveExplorer
End Sub

' Called in Application_Quit as handler class is  cleared
Public Sub Class_Terminate()
'when the application is closed, the class is terminated
'un-set variables
Set olApp = Nothing
Set objInspectors = Nothing
Set objActInspector = Nothing
Set objExplorers = Nothing
Set objActExplorer = Nothing
Set objMailNew = Nothing
Set objMailReply = Nothing
Set objCurrentItem = Nothing
End Sub

' Event handler for a new inspector window opening (i.e. new email is created)
' ISSUE - or when a received email is opened in a new window (double-click)
Public Sub objInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
Dim insType As String
Set objActInspector = Inspector
' this is just to keep names of object variables short and easy to remember
Set objCurrentItem = objActInspector.CurrentItem
' grab & test type name of current inspector item
insType = TypeName(objCurrentItem)
If insType = "MailItem" Then
    ' if its a mailItem - set variable that's more specific
        Set objMailNew = objCurrentItem
    ' MsgBox is for debugging to make sure this fires
        MsgBox ("New email has been created")
    ' Function from other module that is called to add the greeting
    ' Again, this works to add the greeting, but it doesn't keep the auto-signature
        Call AddGreeting(objMailNew)
End If
End Sub

' This also fires if a received email that was opened in a new window is closed.
Public Sub objActInspector_Close()
' if the inspector window (created email) is closed, clear the variables
    Set objMailNew = Nothing
    Set objCurrentItem = Nothing
    MsgBox ("Inspector has closed")
End Sub

This is how the class is initialized from within ThisOutlookSession

Option Explicit
'Instantiate the class on global application level
Dim EventHandler As clsMailHandler

Sub Application_Startup()
'Set custom variable as new instance of class
'to initialize the class (run Class_Initialize() sub)
Set EventHandler = New clsMailHandler
End Sub

Sub Application_Quit()
'Set handler to nothing to clear instance of class
Set EventHandler = Nothing
End Sub

The trouble I'm running into, is that the event handler for newInspector can call the function that adds the greeting (and edits the subject for testing/debugging purposes), but then my auto-signature doesn't get added. I think because the newInspector event fires off before the email actually exists, so the automatic signature doesn't fire. It's also complicated by my signature needing specific formatting and to contain an image, so just adding it as plain text doesn't work.

Most of the solutions I see involve programmatically creating the email CreateItem(olMailItem), but I don't want to do it that way. I want to apply these to the way an email is created by default.

Some things I've seen sound like they might work for what I need but I don't know how to implement them as I can't find examples that I understand. Namely, inspector_activate like from this post Event that fires after signature is added.

How do I get my automatic greeting and keep my automatic signature?

EDIT: I fixed it using the inspector_Activate event. as a SEPARATE sub, so I can edit the email (successfully), after it finishes existing from the NewInspector event.

Public Sub objInspectors_NewInspector(ByVal Inspector As Outlook.Inspector)
If TypeName(Inspector.CurrentItem) = "MailItem" Then
        Set objActInspector = Inspector
End If
End Sub

Public Sub objActInspector_Activate()
MsgBox ("Inspector Activate")
Set objMailNew = objActInspector.CurrentItem
If Len(objMailNew.EntryID) = 0 Then
    Call AddGreeting(objMailNew)
  End If
  Set objActInspector = Nothing
End Sub

Found it on this random website: https://www.vboffice.net/en/developers/newinspector-and-inspector-activate/

CodePudding user response:

If there will be user interaction then the simplest solution is .Display prior to .htmlbody = Greeting() & DraftEmail.htmlbody

Option Explicit

Private Sub test()

    Dim objMailNew As MailItem

    ' Generate objMailNew any way you want
    Set objMailNew = CreateItem(olMailItem)

    ' in your code this is
    'Set objMailNew = objCurrentItem

    Call AddGreeting(objMailNew)

    objMailNew.Display

End Sub


Public Function Greeting() As String
' Defines greeting by time of day '
' Used in with the AddGreeting() function and clsMailHandler '

    ' If before noon, greeting is Good Morning'
    If Time >= TimeValue("8:00 AM") And Time <= TimeValue("11:59 AM") Then
        Greeting = "Good morning,"
    ' If after noon and before work ends, greeting is Good Afternoon'
    ElseIf Time >= TimeValue("12:00 PM") And Time <= TimeValue("5:10 PM") Then
        Greeting = "Good afternoon,"
    End If
End Function

' call this function to add the above calculated greeting to an email '
' i.e. Call AddGreeting(NewlyCreatedEmail)
Public Function AddGreeting(ByRef DraftEmail As MailItem)

' DraftEmail is used with reference to any MailItem object '
' like in clsMailHander > NewInspector > objCurrentItem / objMailNew '

With DraftEmail

    ' Temporarily editing the subject for testing/debugging to make sure this works
    .subject = "AddGreeting Function"
    
    ' Where user interaction is needed .Display is sufficient
    '.Display
    
    ' Where user interaction is not needed
    ' This simulates .Display, without flashing the mail
    Dim myInspector As Inspector
    Set myInspector = .GetInspector

    .htmlbody = Greeting() & DraftEmail.htmlbody
End With

End Function

CodePudding user response:

First, new items don't have the EntryID property set, it is empty until the item is saved to the store in Outlook. So, checking the property value can help with distinguishing new items and saved ones.

Second, you need to wait for the first Activate event of the Inspector class if you want to get the signature added to the message body. Otherwise, the default signature will be overwritten with your message body modifications.

Third, to preserve the default signature in the message body you must insert your greetings right after the opening <body> tag in the HTMLBody property value.

  • Related