Last reviewed on May 8, 2014   —  44 Comments

Fulvio needs to use rules to move sent messages, but the sent items are not marked read when they are copied to other folders.

I’ve set up a rule for copying any message I send out to a local outbox folder (rather than the one on remote server). Therefore, I’ve uncheck the standard option “save a copy of sent messages”, as I don’t need to duplicate them remotely. Everything works fine: I have no longer remote copies of sent emails, and I have the local ones, but these latter are now bolded as unread. So, I’d like to set my custom rule as: copy sent messages to the local outbox AND mark them as read. Yet it seems to be impossible….

It's not impossible to do, but it won't work with Rules. "After Sending" rules don't support custom actions, run a script, or marking items as read. However, you can use VBA to mark sent items read.

Because the sent item is not in the default data file, you'll need to use the code at Use a folder in another pst or Mailbox to identify the data file. Paste it and the code below into the ThisOutlookSession module in the VB Editor.

Change this line: Set Items = GetFolderPath("New PST\Sent Items").Items to reflect the data file name in the folder list and the folder name you are moving the sent item to.

Code Sample: Mark Moved Messages as Read

To test this code, click in the Application_Startup module and press Run to start it without restarting Outlook. Don't forget to get the GetFolderPath function from Use a folder in another pst or Mailbox.


Private WithEvents Items As Outlook.Items

Private Sub Application_Startup()
   Set Items = GetFolderPath("New PST\Sent Items").Items
End Sub

Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
End Sub

Mark deleted items read automatically

To mark messages read as they are moved into a folder within the mailbox, such as the deleted items folder, use the following code sample.

To use the junk mail folder, use
Set Items = Ns.GetDefaultFolder(olFolderJunk).Items

Private WithEvents Items As Outlook.Items

Private Sub Application_Startup()
  Dim Ns As Outlook.NameSpace
  Set Ns = Application.GetNamespace("MAPI")
  Set Items = Ns.GetDefaultFolder(olFolderDeletedItems).Items
   
End Sub

Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
End Sub

Move sent messages using VBA

This code sample moves the sent messages using VBA, rather than a rule.

If the folder you are moving the sent items to is in a different pst file, you'll need the GetFolderPath function at Use a folder in another pst or Mailbox.

Private WithEvents Items As Outlook.Items

Private Sub Application_Startup()
Set Items = Session.GetDefaultFolder(olFolderSentMail).Items

End Sub

Private Sub Items_ItemAdd(ByVal Item As Object)
    Set MovePst = GetFolderPath("NewPST\Sent Items")
    Item.UnRead = False
    Item.Move MovePst
End Sub

More Information

More VBA samples that mark moved message as read are at:
Marking Sent Items as Read How to mark messages read when they are moved to multiple folders (WindowsITPro)
E-Mail: Mark as read Mark as read when moved to a subfolder of the Inbox (vboffice.net)
Mark mails as Read automatically in Deleted Items Folder after deleting mails from any folder (outlookcode.com)


Comments

  1. Claire says

    Good to know--though I must say that Gmail's "mark as read" option for foldered mail is a bit quicker than VBA ;)

    • Diane Poremsky says

      If you use rules to move mail, you can mark read using rules - but Outlook only lets you copy mail after sending and doesn't offer a mark as read option for it. (Don't ask me why - I think it should.)

  2. Fulvio says

    Dear Diane,
    said that I'm quite far from being a VBA expert (in fact, this is my very first time), I tried to write down in sequence, under ThisOutlookSession module, what you indicated, following the instructions for replacing the string as well. As soon as I try to run the module to test it, I got an error message (translating from italian): "Invalid attribute within Sub or Function". could you help me further? Thanks
    Hereafter what is currently in my editor:

    Function GetFolderPath(ByVal FolderPath As String) As Outlook.Folder
    Dim oFolder As Outlook.Folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolderPath_Error
    If Left(FolderPath, 2) = "\\" Then
    FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If
    'Convert folderpath to array
    FoldersArray = Split(FolderPath, "\")
    Set oFolder = Application.Session.Folders.Item(FoldersArray(0))
    If Not oFolder Is Nothing Then
    For i = 1 To UBound(FoldersArray, 1)
    Dim SubFolders As Outlook.Folders
    Set SubFolders = oFolder.Folders
    Set oFolder = SubFolders.Item(FoldersArray(i))
    If oFolder Is Nothing Then
    Set GetFolderPath = Nothing
    End If
    Next
    End If
    'Return the oFolder
    Set GetFolderPath = oFolder
    Exit Function

    GetFolderPath_Error:
    Set GetFolderPath = Nothing
    Exit Function
    End Function

    Private WithEvents Items As Outlook.Items

    Private Sub Application_Startup()
    Set Items = GetFolderPath("Cartelle Personali\Posta Inviata").Items
    End Sub

    Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
    End Sub

    • Diane Poremsky says

      Do the colors of the text in the VBA editor more or less match the ones on the pages online? Red text is bad. Check the quotes and verify they are plain old quotes and not smart quotes.

  3. Stuart says

    Hi Diane

    I got the code in to mark all the emails as read when sent from one email address and stored in a defined folder.
    Now how do I start a new project to do the same thing for the other email address and its defined folder.

    I don't know how to start a new project.

    using outlook 2007

    thanks

  4. Martins says

    Hi Diane,

    I try to get this work, but it comes back with: Compile error: "Invalid attribute in Sub or Function" and marks "WithEvents Items As Outlook.Items"

    Thanks for help!

    My full code:

    Private WithEvents Items As Outlook.Items
    Private Sub Application_Startup()
    Set Items = GetFolderPath("New PST\Sent Items").Items
    End Sub
    Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
    End Sub
    Function GetFolderPath(ByVal FolderPath As String) As Outlook.Folder
    Dim oFolder As Outlook.Folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolderPath_Error
    If Left(FolderPath, 2) = "\\" Then
    FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If
    'Convert folderpath to array
    FoldersArray = Split(FolderPath, "\")
    Set oFolder = Application.Session.Folders.Item(FoldersArray(0))
    If Not oFolder Is Nothing Then
    For i = 1 To UBound(FoldersArray, 1)
    Dim SubFolders As Outlook.Folders
    Set SubFolders = oFolder.Folders
    Set oFolder = SubFolders.Item(FoldersArray(i))
    If oFolder Is Nothing Then
    Set GetFolderPath = Nothing
    End If
    Next
    End If
    'Return the oFolder
    Set GetFolderPath = oFolder
    Exit Function
    GetFolderPath_Error:
    Set GetFolderPath = Nothing
    Exit Function
    End Function

    • Diane Poremsky says

      Make sure you change the path here to the actual pst name folder -

      Set Items = GetFolderPath("New PST\Sent Items").Items

      and it should work (when you put the first part at the top of =ThisOutlookSession as per my other comment). You need just the code in the comment (I removed the stuff you don't need, to reduce confusion and make it easier to read.)

    • Diane Poremsky says

      Make sure you change the path here to the actual pst name folder -

      Set Items = GetFolderPath("New PST\Sent Items").Items

      and it should work (when you put the first part at the top of (ThisOutlookSession as per my other comment). You need just the code in the comment (I removed the stuff you don't need, to reduce confusion and make it easier to read.)

    • Diane Poremsky says

      This part needs to be at the top of ThisOutlookSession.

      Private WithEvents Items As Outlook.Items
      Private Sub Application_Startup()
      Set Items = GetFolderPath("New PST\Sent Items").Items
      End Sub

      Also, you only need the GetFolderPath function from the bottom of the other page, not all of the code on the page. (I'll fix my instructions.)

  5. Chris Gilbert says

    Don't know if anyone is reading this old thread, but I think if I turn off the save copy in Sent folder in Email Options and handle everything through Rules, then my Journal can't be used to save incoming and outgoing emails as entries there for record-keeping purposes which I find valuable for recreating my work for billing purposes.

    • Diane Poremsky says

      It's possible - i have not tested it with journaling, in part because the journal is broken in Outlook 2010 and sent to death row in 2013.

  6. Marek says

    Hello Diane, I dont know where I am doing mistake but I cannot make this to work. I just copy/paste Martins code from September 25. where I only changed GetFolderPath to right PST folder but i am getting this error: "Compile error: Only valid object module" (Private WithEvents Items... line is in red color). In ThisOutlookSession have I insert Module or Class Module? When I try to insert Class module I am not able to test/save project...
    Please can you provide whole working code - with GetFolderPath? Thank you in advance. Marek

    • Diane Poremsky says

      Did you try pasting it in ThisOutlookSession? Double click on ThisOutlooksession on the left to open it on the right side of the editor.

  7. Marek says

    No, as I wrote before, I had only insert new "Module/Class Module" Right now I try paste code as you mention but nothing is happening. "Unread" message still remain in Sent folder... No matter if I hit F5 key or Outlook was closed/reopened.

    • Diane Poremsky says

      After you paste it in ThisOutlookSession, you need to click in the Application Startup macro and press the run button - this will start the macro without actually restarting outlook.

  8. Marek says

    Thank you for an answer but I did exactly what you wrote without success. Messages in Sent folder still remain marked as unread. Please can you check my full code:

    Private WithEvents Items As Outlook.Items
    Private Sub Application_Startup()
    Set Items = GetFolderPath("Personal Folders\Sent Items").Items
    End Sub
    Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
    End Sub
    Function GetFolderPath(ByVal FolderPath As String) As Outlook.Folder
    Dim oFolder As Outlook.Folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolderPath_Error
    If Left(FolderPath, 2) = "\\" Then
    FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If
    'Convert folderpath to array
    FoldersArray = Split(FolderPath, "\")
    Set oFolder = Application.Session.Folders.Item(FoldersArray(0))
    If Not oFolder Is Nothing Then
    For i = 1 To UBound(FoldersArray, 1)
    Dim SubFolders As Outlook.Folders
    Set SubFolders = oFolder.Folders
    Set oFolder = SubFolders.Item(FoldersArray(i))
    If oFolder Is Nothing Then
    Set GetFolderPath = Nothing
    End If
    Next
    End If
    'Return the oFolder
    Set GetFolderPath = oFolder
    Exit Function
    GetFolderPath_Error:
    Set GetFolderPath = Nothing
    Exit Function
    End Function

    • Diane Poremsky says

      It works here. Did you click in Application startup macro and click run to kick start it?

      Try adding msgbox "Working" as the first line of the itemadd macro - when the macro fires the message box will come up. That will tell us if its working.

      Private Sub Items_ItemAdd(ByVal Item As Object)
      msgbox "Working"
      Item.UnRead = False
      Item.Save
      End Sub

  9. Marek says

    Once again thank you Diane for your patience, but maybe I am stupid enough because after I am hitting RunSub/UserForm(F5) button, nothing is happend. I made two screenshots of my project/outlook. If you have a time, please look at this. http://1drv.ms/1cPCjOE Maybe you will find something what I am still missing...
    Just for testing purpose i have used this guide http://msdn.microsoft.com/en-us/library/office/ff869298.aspx and message box appears correctly.

    • Diane Poremsky says

      I'm guessing its the localization that is the problem. You tried it both with the localized name and "Sent Items"?

    • Diane Poremsky says

      If you are getting the when Outlook restarts or when you click in Application_Startup and click Run, it means the macro can't find the folder. Replace it with archive or one of the other names with only ASCII characters and click Run in the App Startup macro.

  10. Chris says

    My code is this but it gives me " object variable or with block variable not set 91" - What is wrong?

    Private WithEvents Items As Outlook.Items
    Private Sub Application_Startup()
    Dim Items As Outlook.Items
    Set Items = GetFolderPath("C:\Users\cc580e\Desktop\Chirag - Personal Folders(1).pst\Sent Items").Items
    MsgBox "test"
    End Sub
    Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
    End Sub
    Function GetFolderPath(ByVal FolderPath As String) As Outlook.Folder
    Dim oFolder As Outlook.Folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolderPath_Error
    If Left(FolderPath, 2) = "\\" Then
    FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If
    'Convert folderpath to array
    FoldersArray = Split(FolderPath, "\")
    Set oFolder = Application.Session.Folders.Item(FoldersArray(0))
    If Not oFolder Is Nothing Then
    For i = 1 To UBound(FoldersArray, 1)
    Dim SubFolders As Outlook.Folders
    Set SubFolders = oFolder.Folders
    Set oFolder = SubFolders.Item(FoldersArray(i))
    If oFolder Is Nothing Then
    Set GetFolderPath = Nothing
    End If
    Next
    End If
    'Return the oFolder
    Set GetFolderPath = oFolder
    Exit Function
    GetFolderPath_Error:
    Set GetFolderPath = Nothing
    Exit Function
    End Function

    • Diane Poremsky says

      getfolderpath path is wrong, should be the display name and folders as it appears in the folder list.

  11. Stephanie Hudson says

    With the code, all new mail in my folder is being marked as read, not just the newly sent mail. How can I alter the code so that only the mail sent from myself is marked as read.

    Details:
    I'm wanting to keep conversation threads together, including sent mail. Ideally I want all this mail in my inbox until I decide I'm done with it and save it to another folder elsewhere. That is, I want all incoming mail and sent mail in the same "inbox" folder. Right now, I'm doing that in a folder directly below Outlook's inbox called "_My Inbox_".

    A. I have a rule: After I send a message, move a copy to the "_My Inbox_" folder.
    B. I have a bunch of other rules handling mail that can go to other folders or the trash.
    C. My last rule is: After a message arrives, move it to the "_My Inbox_" folder.
    D. In Mail Options, Save messages settings, I have "When replying to a message that is not in the Inbox, save the reply in the same folder" ticked (true).
    E. In Mail Options, Save messages settings, I have "Save copies of messages in the Sent Items folder" NOT ticked (false).
    -------
    What's happening is that the Sent mail is Unread.
    I tried adding a rule to mark mail from me (sent) as read, but this doesn't work as the mail just gets moved there, it doesn't actually "arrive" as the rule expects.
    -------
    F. So, I found your code and have applied it. However, now ALL mail coming to "_My Inbox_" is marked as read.

    How can I alter the code so that only the mail sent from myself is marked as read.

    • Diane PoremskyDiane Poremsky says

      Remove the rules that touch sent items and mark them read. Use the Move sent messages using VBA macro to move the message and mark it as read.

      Use this as the move to location:
      Set MovePst = Session.GetDefaultFolder(olFolderInbox)

    • Stephanie Hudson says

      Am I putting that in the Application_Startup()? I currently have:
      Private Sub Application_Startup()
      Set Items = Session.GetDefaultFolder(olFolderInbox).Folders("_My Inbox_").Items
      End Sub

      Sorry, this is my first time with VBA in Outlook. Only used it in Excel and Access before.
      Thanks.

    • Diane PoremskyDiane Poremsky says

      The folder in the application start up is the one Outlook is watching. The folder you are moving sent items to is identified as the MovePst folder: (movepst may not make sense if you aren't moving it to a pst, but it's only a variable name and will work)
      Set MovePst = GetFolderPath("NewPST\Sent Items")

      If the folder you are moving mail to is a subfolder of the inbox and is named _My_Inbox_ then you want the movepst line to be
      Set MovePst = Session.GetDefaultFolder(olFolderInbox).Folders("_My Inbox_").Items

  12. Fred Sawtelle says

    I have a subfolder of Inbox named "Coworkers" which in turn contains several folders named for coworkers. Rules send a copy of email from each to their respective folders. I want to mark all those emails as read while leaving the ones in Inbox unread. You've explained clearly what to do here for an individual folder. Is there a way to do it for multiple folders, short of creating an instance of Outlook.Items and an ItemAdd eventhandler for each one? For example, can I say in effect, "Mark as read everything that goes into any of the subfolders of this folder"?

    • Diane PoremskyDiane Poremsky says

      Rules has an option to mark as read... which version of Outlook are you using?

  13. Fred Sawtelle says

    I'm using 2013. Choosing the "Mark as read" option marks both of them as read. I need the one in Inbox to stay unread.

    • Diane PoremskyDiane Poremsky says

      Oh. That limits your options. Is there a reason why you need copies of the messages left in the inbox?

  14. Fred Sawtelle says

    I'd never given it any thought until you asked. Inbox is where I expect to find anything that needs my attention. I could set "Unread" as the default selected folder, I guess. But with Inbox I'm able to see the flow of a group conversation at a glance. With, say, five people discussing a topic it's important to me to see their comments in order, especially if I come in in the middle of it. Trying to follow it through separate folders would be frustrating, especially when there are some dead-end branches on the conversation (i.e. not everyone replies to the latest). Outlook probably provides a way of moving through a thread, but if so I've never used it; I rely on the newest-first display of Inbox to show me at a glance what's going on. What do you suggest?

    • Diane PoremskyDiane Poremsky says

      There are two ways to handle it:
      1. Don't file mail into a bunch of folders. Leave everything in the inbox and use Quick Steps to move mail after you've read it - i use just a couple of folders and dump almost everything into one folder called Completed. If i need to find mail to/from a specific person, i use instant search or a search folder.

      2. Use rules to file mail and use the unread search folder to read it. As long as you use the By Date (Conversations) view, it will show all messages in the conversation. (Default view is by folder).

  15. Stephane says

    Hi Diane,

    Thanks a lot for your time, it's almost perfect :-p !

    In my case, I have two Inbox (two IMAP accounts). So it's working fine for the first Inbox, but how to do I tell the macro to also mark as read the mails in the 2nd sent folder ?

    I have added a 2nd "items" (called Items2) in Application_Startup with the 2nd patch, but how should I invoke it in the Items_ItemAdd function ?

    Thank you for your help !

    • Diane PoremskyDiane Poremsky says

      To add another folder you need to repeat these lines, using a different name (Items2 is fine)

      Private WithEvents Items2 As Outlook.Items

      Private Sub Items2_ItemAdd(ByVal Item As Object)
      Item.UnRead = False
      Item.Save
      End Sub

      Plus, add the folder to the application start up macro:
      Set Items = GetFolderPath("other datafile\Sent Items").Items

      Another way is to use the following format for each itemsadd macro, calling a shared macro. For this macro, it doesn't make much difference, but if the code was longer it could make it easier to read and update as well as keep the file smaller.
      Private Sub Items_ItemAdd(ByVal Item As Object)
      MarkRead Item
      End Sub

      Private Sub MarkRead(ByVal Item As Object)
      Item.UnRead = False
      Item.Save
      End Sub

  16. Jason says

    Hi Diane

    Wondering if you would be able to help me after coming across your webpage. I've setup a rule to move all my imap outgoing sent mail to my 'Sent Items' within my personal folders, i.e. to keep a backup using the local pst. However, the rules do not allow you to mark the sent item as read once transferred across, hence why I found you page. I applied the following code within the 'ThisOutlookSession' in the VBA Editior. I've changed the GetFolderPath address as it appears in outlook. However, to no avail as I keep getting 'Compile error: Sub or Function not defined'. I suspect this is because the path is incorrect - lost as I'm defining as it appears in outlook. Any pointers would be gratefully appreciated!

    Private WithEvents Items As Outlook.Items

    Private Sub Application_Startup()
    Set Items = GetFolderPath("Personal Folders\Sent Items").Items
    End Sub

    Private Sub Items_ItemAdd(ByVal Item As Object)
    Item.UnRead = False
    Item.Save
    End Sub

  17. Gus says

    Hi! I'm using this code for a long time, however my Office has been upgraded today to the 2013 version and it's no longer marking sent items as read. Any trick?

    • Diane PoremskyDiane Poremsky says

      Was the macro security reset to signed macros only? File, Options, Trust Center, Macro Security to check.

Leave a Reply

Please post long or more complicated questions at OutlookForums by Slipstick.com.

If the Post Comment button disappears, press your Tab key.