0

I want, when I create an email using the default ribbon button, to add a greeting to the body while also keeping the default signature.

I have a public function that uses TimeValue to calculate whether to add "Good morning," or "Good afternoon,". I call a sister function that adds it to the email.

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 built a class module for event handling to detect when a new inspector opens and that it is a mailitem. (Unfortunately, it's seems not able to detect yet whether it is a new email or if it is an email that's been retrieved and opened. 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 there because I also want to do this for inline replies. I have the event handlers for newExplorer and ActiveInlineResponse that I left out here because I'm focusing on 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 event handler for newInspector calls 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 exists, so the automatic signature doesn't fire.

Most of the solutions I see involve programmatically creating the email CreateItem(olMailItem), but I want to apply these to emails created by default.

Some other offered solutions I've seen might work, but I can't find examples I fully understand. Like inspector_activate from Event that fires after signature is added.

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

Faith
  • 53
  • 6
  • Does this answer your question? [How to add default signature in Outlook](https://stackoverflow.com/questions/8994116/how-to-add-default-signature-in-outlook) – niton Nov 11 '22 at 18:23
  • No, unfortunately it doesn't. Again, all of the proposed solutions in that post use CreateItem(olMailItem) to make and edit the new email. Yes, this gives direct control, but it would require me putting it into some sort of custom ribbon button, I'd rather just be able to edit any email that is created the default way. If I could use .Display to force the new email inspector to display, I would, but I keep getting runtime errors. It's not an event, so I can't watch for it like objMailNew_WhenDisplay, which would be ideal. – Faith Nov 11 '22 at 20:57
  • How you generate the mail is not relevant. Add the lines `Dim myInspector As Outlook.Inspector` and `Set myInspector = .GetInspector` as shown here https://stackoverflow.com/a/72719341/1571407 – niton Nov 11 '22 at 21:22
  • I couldn't get .GetInspector to work. .GetInspector is a property of MailItems that are already fully created- not of inspectors themselves. the NewInspector event I'm using all happens as the inspector itself is created and classified as a mailitem- the mailitem can't be edited within NewInspector. I fixed it using inspector_Activate as a separate sub, see my original post for the edited code. – Faith Nov 11 '22 at 21:39
  • Apologies should have taken more time on this. The suggested duplicate is not compatible with your event code. Good that you found a solution. – niton Nov 14 '22 at 19:58

2 Answers2

1

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.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • So in the second sub, the line `If Len(objMailNew.EntryID) = 0` is checking for if the EntryID hasn't been set yet, and since it's new it would be 0? Thank you! I'm glad I understand that portion now since that's the part I found on that website I linked. +1 – Faith Nov 14 '22 at 18:29
  • 1
    Yes, you are on the right avenue. – Eugene Astafiev Nov 14 '22 at 18:37
1

My own answer: I fixed it using the Inspector_Activate event as a SEPARATE sub. The default "new email" ribbon button creates a new inspector window that the _NewInspector event catches and sets as the active inspector. Inspector_Activate event then gets triggered as the email itself finishes its own creation/initialization process. Then the AddGreeting() function is called to edit the .HTMLbody and add the automated greeting.

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/

Faith
  • 53
  • 6