2

As you know while you are using outlook and use (Reply/ Reply All) to an email message, the original attachments is not included on the replied message.
So, I have used the below code and assigned to a custom buttons on outlook ribbon, and it works correctly.
Instead of click on my custom button, I need to assign my code directly to outlook inbuilt functions itself (Reply and Reply All) .
I found that outlook provides two events for oMailItem Object oMailItem_Reply and oMailItem_ReplyAll.
I have used it like this:

Private Sub oMailItem_Reply(ByVal Response As Object, Cancel As Boolean)
    Call ReplyWithAttachments
End Sub
 
Private Sub oMailItem_ReplyAll(ByVal Response As Object, Cancel As Boolean)
   Call ReplyAllWithAttachments
End Sub

But when I click on outlook (Reply and Reply All) itself, then either one from the following behavior happens:
1- a new replied email created without any attachments at all ,
2- Or the new replied email created twice , one with attachments included and the other one without any attachments.
This is the full working code to add the attachments from the original email to the replied one:

Option Explicit
Option Compare Text
Sub ReplyWithAttachments()
    ReplyAndAttach (False)
End Sub
Sub ReplyAllWithAttachments()
    ReplyAndAttach (True)
End Sub
 
Function GetCurrentItem() As Object
 
    Dim objApp As Outlook.Application
 
    Set objApp = Application
'  On Error Resume Next
    Select Case TypeName(objApp.ActiveWindow)
        Case "Explorer"
            Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
        Case "Inspector"
            Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
    End Select
 
    Set objApp = Nothing
End Function
 
Sub AddOriginalAttachments(ByVal myItem As Object, ByVal myResponse As Object)
 
    Dim fldTemp As Object, strPath As String, strFile As String
    Dim myAttachments As Variant, attach As Attachment
 
    Set myAttachments = myResponse.Attachments
 
    Dim fso As New FileSystemObject
 
    Set fldTemp = fso.GetSpecialFolder(2)    'User Temp Folder
    strPath = fldTemp.Path & "\"
 
    For Each attach In myItem.Attachments
      If Not attach.FileName Like "*image###.png" And _
         Not attach.FileName Like "*image###.jpg" And _
         Not attach.FileName Like "*image###.gif" Then
        strFile = strPath & attach.FileName
         attach.SaveAsFile strFile
          myAttachments.Add strFile, , , attach.DisplayName
           fso.DeleteFile strFile
      End If
    Next
 
    Set fldTemp = Nothing
    Set fso = Nothing
    Set myAttachments = Nothing
End Sub
 
Sub ReplyAndAttach(ByVal ReplyAll As Boolean)
 
    Dim myItem As Outlook.MailItem
    Dim oReply As Outlook.MailItem
 
    Set myItem = GetCurrentItem()
 
    If Not myItem Is Nothing Then
        If ReplyAll = False Then
            Set oReply = myItem.Reply
        Else
            Set oReply = myItem.ReplyAll
        End If
 
        AddOriginalAttachments myItem, oReply
        oReply.Display
        myItem.UnRead = False
    End If
 
    Set oReply = Nothing
    Set myItem = Nothing
End Sub
Waleed
  • 847
  • 1
  • 4
  • 18
  • 1
    You Reply and ReplyAll from within the events in `ReplyAndAttach`. You have a Reply or ReplyAll. Drop `ReplyAndAttach`. Replace `GetCurrentItem` instead `Set` the `oMailItem` each time you select an item `_SelectionChange` event or generate an inspector `_NewInspector` event. I have not worked out all the details, especially the inspector part is sketchy, but should be close. – niton Aug 04 '23 at 15:46
  • If you call from `oMailItem_Reply` event a `Sub` which also replies, two reply windows will be crated. The first one (displayed or not) of the Sub call and the second one generated by the initial replay (standard, without attachments). This last one cannot be killed inside the event code. It will be shown **only after the event code ends**. I think, a timer looking for that window handle (using API) and closing it (also using API) can automate the process. If interested and no other answer received, I think I can show you tomorrow how it can be handled. I have an idea, but only in my head... – FaneDuru Aug 05 '23 at 20:30
  • If you want me seeing your comment, you should tag me... Closing the reply window using API will not flicker at all. The code should find the window in the next second and the timer process will be stopped. Now, do you want only **automatically attaching the sender attachments and see the displayed `RE:` reply window, to manually send it, after checking and adding something**? – FaneDuru Aug 07 '23 at 10:51
  • @FaneDuru , Yes I want **automatically attaching the sender attachments and see the displayed RE: reply window, to manually send it, after checking and adding something**, Please, could you see the suggestion of "niton" comment. (also sorry for forgetting tagging you in the previous comment) – Waleed Aug 07 '23 at 11:11
  • I did not pay attention to other comments... I can look at it now. He is basically referring to a different way of obtaining `myItem`, not having it when the `Reply` event is triggered. I usually declare (`WithEvents`) `m_Inspertors` and `m_Insperctor` with its `Activate` event. I think I have shown that to you in another thread. 'this answer' is a kind of blog... I did not see it. The issue for you is how to set `MyItem`, the one where from tot take the attachments. I used an already existing event to initialize it when opening (from former 'MyItem_PropertyChange`... – FaneDuru Aug 07 '23 at 12:14

2 Answers2

1
  1. Please, copy the next declarations in the top part (declarations area) of ThisOutlookSession code module:
  'new variables: _________________________________
  Private WithEvents myExplorer As Outlook.Explorer
  Private WithEvents myitemExpl As Outlook.MailItem
  '________________________________________________

  Private WithEvents MyItem As Outlook.MailItem
  Private WithEvents m_Inspectors As Outlook.Inspectors
  Private WithEvents m_Inspector As Outlook.Inspector

  Private Const boolNoAttach As Boolean = True 'make it true when need to add original attachments
  1. Copy the next code events (and two Subs), or add the next code lines if the respective event already exists:
 Private Sub Application_Startup() 'it may exist, I suggested it in another answer for you
     Set m_Inspectors = Application.Inspectors
     Set myExplorer = Application.ActiveExplorer
End Sub

'the next one may also exist, I think (if you did not delete it):
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()
  'existing declarations, if any
  '.......
 If TypeOf m_Inspector.CurrentItem Is MailItem Then
   Set MyItem = m_Inspector.CurrentItem 'it looks volatile and may be lost after using once...
   'existing code, if any...
 End if
End Sub

Private Sub myItem_PropertyChange(ByVal Name As String)
    'your existing code, if any...
    Initialize_Handler
End Sub

Sub Initialize_Handler()
 Set MyItem = Application.ActiveInspector.CurrentItem
 Set myExplorer = Application.ActiveExplorer 'new line for Explorer issues handling
End Sub

Private Sub MyItem_Reply(ByVal Response As Object, Cancel As Boolean)
  If boolNoAttach Then 'only if this constant is True
    AddOrigAttachments MyItem, Response
  End If
End Sub

Private Sub MyItem_ReplyAll(ByVal Response As Object, Cancel As Boolean)
   If boolNoAttach Then 'only if this constant is True
      AddOrigAttachments MyItem, Response
   End If
End Sub

'part dealing with Explorer issues handling:
Private Sub myExplorer_SelectionChange()
 On Error Resume Next
 Set myitemExpl = myExplorer.Selection.Item(1)
End Sub

Private Sub myitemExpl_Reply(ByVal Response As Object, Cancel As Boolean)
  If boolNoAttach Then 'only if this constant is True
    AddOrigAttachments myitemExpl, Response
  End If
End Sub
Private Sub myitemExpl_ReplyAll(ByVal Response As Object, Cancel As Boolean)
  If boolNoAttach Then 'only if this constant is True
      AddOrigAttachments myitemExpl, Response
  End If
End Sub

Sub AddOrigAttachments(ByVal MyItem As Object, ByVal myResponse As Object)
    Dim MyAttachments As Variant
    Set MyAttachments = myResponse.Attachments
    
    Dim fso As Object, fldTemp As Object, strPath As String, Attachment As Outlook.Attachment, strFile As String
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fldTemp = fso.GetSpecialFolder(2)  'User Temp Folder
    strPath = fldTemp.Path & "\"
 
    For Each Attachment In MyItem.Attachments
        strFile = strPath & Attachment.FileName
        Attachment.SaveAsFile strFile
        MyAttachments.Add strFile, , , Attachment.DisplayName
        fso.DeleteFile strFile
    Next
    
    Set fldTemp = Nothing
    Set fso = Nothing
    Set MyAttachments = Nothing
End Sub

This last one may also stay in a standard module. I made some tests and I do not remember if I modified somehow your existing Sub with a similar name...

FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • @Waleed No any rush! – FaneDuru Aug 07 '23 at 14:08
  • I started with deleting everything from `ThisOutlookSession` and then used your code as it is. **(1-)** I tried to use the menu of Reply/ReplyAll (not opened the sender email yet), the result is no attachments added to the replied window at all (with no error raised). **(2-)** I tried (after opened the sender email), the codes works correctly, But If I closed the reply window and clicked again on reply/ReplyAll (sender email still opened) ,the result is no attachments added to the replied window at all (with no error raised). – Waleed Aug 08 '23 at 04:42
  • Also, I am sure there is a way to expose the sender email without firstly opening it. Because I am already using a code to the save attachments of any email message without firstly opening it, Kindly see this link of my source code https://justpaste.it/8brck – Waleed Aug 08 '23 at 04:58
  • @Waleed I am afraid I do not understand what you say. What do you understand by **"But when I click on outlook (Reply and Reply All) itself, then either one from the following behavior happens:"**. The code is obviously designed to work when you **click on outlook (Reply and Reply All)**. Do you know what an event is and how is it triggered? Since, I cannot understand what you want, I am afraid that I cannot help. What do you mean by **" I tried to use the menu of Reply/ReplyAll (not opened the sender email yet)"**? How **exactly did you test**? I am not able to understand what this means. – FaneDuru Aug 08 '23 at 06:50
  • @Waleed What do you understand by **"automatically attaching the sender attachments and see the displayed RE: reply window, to manually send it, after checking and adding something"**? How to **send it** if it is not open? I am completely confused. Are you sure that you know what you want, no offence? – FaneDuru Aug 08 '23 at 06:53
  • I am unable to use Anydisk on my work, So I will prepare a video and show you my issues – Waleed Aug 08 '23 at 06:57
  • @Waleed I am afraid that you were not too clear in your question. The above solution trigger those two events **only from an inspector (an open window)**. They are not triggered from explorer. I didn't even think about that. I do not know if it's possible. When i will have some time I will try exploring this way, too. – FaneDuru Aug 08 '23 at 08:31
  • @Waleed I think, I found a promising way. I am working on it and it looks promising... – FaneDuru Aug 08 '23 at 08:49
  • @Waleed Please, test the updated answer. Now, it should also deal with explorer issues. Please, send some feedback after testing it. – FaneDuru Aug 08 '23 at 08:58
  • I am afraid to say the issue still exists . **1-** `explorer issue` (menu) it works only for one time per outlook session and sometime not working at all (even after closing outlook and open again). **2-** `Inspector issue`, It works, but as I showed you on video (If I closed the reply window and clicked again on reply/ReplyAll (sender email still opened) ,the result is no attachments added to the replied window at all). **3-** also I found if attachment is embedded on the mail body (email is formatted as Rich Text and not HTML) then no attachments added to the replied window in all cases. – Waleed Aug 08 '23 at 10:59
  • In addition to your great efforts , I also found that this code [Link](https://justpaste.it/8brck) can save attachment from even embeded ones (in the email body) – Waleed Aug 08 '23 at 11:25
  • @Waleed 1. It shouldn't. But explorer `Change` event is triggered only if you change selection, or it keeps the last . I mean, it does not for Context menu commands, except the case you firstly select the mail, and only after that you use context menu. Otherwise, it should work on buttons from Ribbon. **Did you use the whole code as it is**? Or try changing **what you observed that it has been changed**? It works in all cases in my installations, if **selection is changed**, or it works as many as I try **for the same selection**. When clicking "again on Replay" isn't the same mail selected? – FaneDuru Aug 08 '23 at 11:58
  • @Waleed About the link you show, it looks to me that it uses exactly the same way as in your code. It only processes more mails at once (only to save attachments), which is not possible when try raising events. Am I missing anything? If you did not copy the whole code, you could miss something. The code works as it should, only as a whole package. I was searching for some minutes to find a solution for the context menu item, but Outlook looks to not expose such an event after 2007 version. It should probably be possible in a different way, if I will be able to access the XML code and adapt. – FaneDuru Aug 08 '23 at 12:02
  • I started with deleting everything from `ThisOutlookSession` and then used your **updated code as it is** , the issues as described earlier. I realize my question is complicated, But I know that you like challenging questions. I later suspected that the problem is with `Sub AddOrigAttachments`, So I changed `strPath` to my desktop and commented `fso.DeleteFile strFile` , When using reply/reply all from context menu or Ribbon, **I found that attachment never saved to my desktop** , I think this info may help to resolve all my issues. I am using Office 2016 – Waleed Aug 08 '23 at 12:36
  • @Waleed But, did you place a breakpoint in the respective sub, **to see that the code reaches it**? If the code is not able to save in a specific location, **it will raise an error**. It is difficult to solve a problem without seeing what's happening. You should split the problem in smaller slices. Try placing break points in the four cases of `Reply` and `ReplyAll` events and firstly see **if they are triggered**! If they are, the rest should be easy to be solved. But you do not have to guess it... – FaneDuru Aug 08 '23 at 12:41
  • If the mail still not opened yet but selected and used Reply/ReplyAll (from context menu or ribbon) , the surprise is both subs `MyItem_Reply` and `MyItem_ReplyAll` **are not triggered at all.** If the mail is opened and clicked Reply/ReplyAll, then the respective event sub is triggered, **But** after I closed the replied window (sender mail still opened) then both subs `MyItem_Reply` and `MyItem_ReplyAll` are not triggered again until I close the sender mail and open again. I guess the problem with **Boolean Const** `boolNoAttach` – Waleed Aug 08 '23 at 13:28
  • @Waleed This looks to mean that you do not have the complete code related to Explorer events part. Do you have a code line as `Set myExplorer = Application.ActiveExplorer` in the `Initialize_Handler` `Sub`? And forget about `boolNoAttach`. It is there only to change a boolean variable to make the whole solution not adding attachments, anymore... – FaneDuru Aug 08 '23 at 13:32
  • I wish you to trust me, as I said earlier **I deleted everything from ThisOutlookSession and then used your updated code as it is (copy and paste)** And yes, the code line `Set myExplorer = Application.ActiveExplorer` is found in the Initialize_Handler Sub, But I found that `Initialize_Handler` Sub itself **is never triggered** in all cases (context menu or from the opened mail) , I even add a line code `MsgBox` after line `Set myExplorer` and MsgBox is never appeared even after reopening outlook !! – Waleed Aug 08 '23 at 14:14
  • Can I connect to your home computer? – FaneDuru Aug 08 '23 at 15:25
  • Unfortunately I haven't outlook in my laptop. I spent last hour to determine the problem and I found this accepted answer by @niton [Link](https://stackoverflow.com/questions/46002026/outlook-events-not-firing) , I will try tomorrow and feed you back. – Waleed Aug 08 '23 at 15:33
  • @Waleed This is exactly what I wanted to suggest. I squeezed my brain to understand why it works in my installation and not in yours. I have some (important) mails I do not close them, to remember me doing something. And their windows are opened each time I start Outlook. So, when first such window is shown, it set inspectors, then trigger `m_Inspector_Activate`, followed by `myItem_PropertyChange` which calls `Initialize_Handler`. Only after running it `myExplorer` is set. Calling this `Sub` from `Application_Startup` will make it available from the beginning. – FaneDuru Aug 08 '23 at 18:13
  • @Waleed You may test my supposition firstly running the inspector (buttons from the window) and you will also have the Explorer part functional... This is what I wanted to try on your computer. You may also click inside `Initialize_Handler` and run it pressing `Ctrl + F5`, to manually initialize the necessary objects... – FaneDuru Aug 08 '23 at 18:14
  • I tried your latest update, I got **Run-time error '91':Object variable or With block variable not set** at this line of Sub Initialize_Handler `Set MyItem = Application.ActiveInspector.CurrentItem`, This error happens just after opening outlook application, I have used `On Error Resume Next` and now It works in all cases except if the attachment (of the original mail) is embedded on the body of the mail itself (the mail message was formatted as Rich Text and not HTML) , The result is no attachment found on the replied window and there is no error raised. – Waleed Aug 09 '23 at 07:35
  • In addition, now your answer is very near to be perfect like the other answer by "niton" , I think if it is possible to change the replied mail to HTML, this may fix this issue. – Waleed Aug 09 '23 at 07:37
  • @Waleed Then, change replied mail to HTML and use niton's code. Did you test it for the Inspector cases? Manually opening the mail and press Reply from there. – FaneDuru Aug 09 '23 at 09:57
  • If you mean about the answer of “nition”, yes I have tested it for Inspector cases and it works correctly like your latest update. I do not like to change the format of the original mail (sender one). – Waleed Aug 09 '23 at 10:20
  • For embedded attachments, I debugged extensively and found `strFile` is created at user temp folder `fldTemp` but it did not appear on the reply window at all, **But**, when I tried manually to change the mail format of the reply window to HTML and found that Attachment has been appeared correctly on its place. I added `MyItem.BodyFormat = olFormatHTML` to Private `Sub MyItem_Reply` but it has no effect (reply mail is still rich text), this approach worked with the other answer but it disordered the signature of sender signature on both mail windows (the original and the reply one) – Waleed Aug 09 '23 at 12:06
  • @Waleed I cannot reproduce the issue, but if you manually changed **the reply window**, I would suggest you to simulate it by changing the format of **this window** (`Response.BodyFormat = olFormatHTML`). And do that before calling `AddOrigAttachments`. – FaneDuru Aug 09 '23 at 12:17
  • I am grateful for your continuous great help and please accept my apology for not choosing your answer. – Waleed Aug 10 '23 at 06:24
  • 1
    @Waleed No any problem. I was perturbed by the understanding related to what is to be done. Since I tried setting an item from an `Inspector` (firstly opening the mail and pressing Replay from the window interface) and I already had declarations for setting the inspector and its `Open` event, I used it. Then, when you mentioned about the explorer issue I tried adding come code to cover that part, too. Without testing if explorer alone is able to solve both cases (setting the item before showing the reply window). – FaneDuru Aug 10 '23 at 06:54
  • I tried exploring the part of right click context menu (without preliminary **selecting the item in Explorer**, but not simple and I lost enthusiasm of keeping searching for a solution... – FaneDuru Aug 10 '23 at 06:55
1

This code assumes the last item selected will be replied to, whether opened first or not.

An inspector event is probably unnecessary.

Option Explicit

Private WithEvents myAttExp As explorer
Private WithEvents myAttOriginatorMail As MailItem
  
Private Sub Application_Startup()
    ' No need for a separate Initialize_Handler in ThisOutlookSession
    Set myAttExp = ActiveExplorer
End Sub

Private Sub myAttOriginatorMail_Reply(ByVal Response As Object, Cancel As Boolean)
    AddOrigAttachments myAttOriginatorMail, Response
End Sub

Private Sub myAttOriginatorMail_ReplyAll(ByVal Response As Object, Cancel As Boolean)
    AddOrigAttachments myAttOriginatorMail, Response
End Sub


Private Sub myAttExp_SelectionChange()

    ' An error occurs when there is a folder change.
    ' For reasons unknown, this addresses the error.
    On Error Resume Next
    
    If TypeOf myAttExp.selection.Item(1) Is MailItem Then
        Set myAttOriginatorMail = myAttExp.selection.Item(1)
        Debug.Print myAttOriginatorMail.subject
    End If
    
End Sub


Sub AddOrigAttachments(ByVal myOrigMail As Object, ByVal myResponse As Object)

    Dim fso As Object
    Dim fldTemp As Object
    
    Dim strPath As String
    Dim strFile As String
    
    Dim Att As Attachment
    
    Dim myAttachments As Attachments
    Set myAttachments = myOrigMail.Attachments
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fldTemp = fso.GetSpecialFolder(2)  'User Temp Folder
    Debug.Print fldTemp
    
    strPath = fldTemp.path & "\"
 
    For Each Att In myAttachments
        strFile = strPath & Att.FileName
        Debug.Print strFile
        
        Att.SaveAsFile strFile
        
        myResponse.Attachments.Add strFile, , , Att.DisplayName
        fso.DeleteFile strFile
    Next
    
End Sub
niton
  • 8,771
  • 21
  • 32
  • 52