Last reviewed on April 21, 2015   —  13 Comments

I want to delete an older email when a new message comes in (they have the same subject line).

This run a script sample is perfect to use with status reports and similar messages where you really only need to keep the most recent copy. For it to work, the messages need to have the same subject line (and the subject should be unique, because all messages matching the condition will be deleted.)

To use, create a Rule that checks the message subject and choose Run a Script as the action, selecting this script. The macro checks the Item.Subject, so if you need to run it on messages with different subjects you can use one rule.

While it only runs if Outlook is open, old messages won't pile up, as it deletes all older messages that meet the conditions when Outlook is open.

Use a script to delete older messages

See Outlook's Rules and Alerts: Run a Script for more information on using Run A Script rules.

Sub DeleteOlderMessages(Item As Outlook.MailItem)

Dim objInbox As Outlook.MAPIFolder
Dim intCount As Integer
Dim objVariant As Variant

Set objInbox = Session.GetDefaultFolder(olFolderInbox)

' Remove these lines if you don't want to add a category
Item.Categories = "Delete Older"

For intCount = objInbox.Items.Count To 1 Step -1
 Set objVariant = objInbox.Items.Item(intCount)
 If objVariant.MessageClass = "IPM.Note" Then
    If objVariant.Subject = Item.Subject And objVariant.SentOn < Item.SentOn Then
    End If
 End If

Set objInbox = Nothing
End Sub

How to use macros

First: You will need macro security set to low during testing.

To check your macro security in Outlook 2010 or 2013, go to File, Options, Trust Center and open Trust Center Settings, and change the Macro Settings. In Outlook 2007 and older, it’s at Tools, Macro Security.

After you test the macro and see that it works, you can either leave macro security set to low or sign the macro.

Open the VBA Editor by pressing Alt+F11 on your keyboard.

To put the code in a module:

  1. Right click on Project1 and choose Insert > Module
  2. Copy and paste the macro into the new module.

More information as well as screenshots are at How to use the VBA Editor


  1. M.Sornamuthu says

    Dear Ms Diane Poremsky,

    Thanks for the above code

    Can you please give me the code which can run in all sub folders



    • Diane Poremsky says

      I'm sorry, I don't have a very of this that runs on all subfolders. You might be able to use the processfolder sub. You'd call it using
      processFolder (objNS.GetDefaultFolder(olFolderInbox))

      Private Sub processFolder(ByVal oParent As outlook.MAPIFolder)
      Dim oFolder As outlook.MAPIFolder

      ' do whatever here

      If (oParent.Folders.Count > 0) Then
      For Each oFolder In oParent.Folders
      Call processFolder(oFolder)
      End If
      End Sub

  2. Netpilot says

    Hi Diane,

    This script is SO close to what I've been trying to figure out how to do with new RSS items from a VBA script!

    We all know of the problem that Outlook has with receiving duplicate items from certain RSS feeds, depending on how the RSS server is configured. A new duplicate RSS item appears to have the same "From", "Subject", and date "Received" values, but has a newer date "Modified" value.

    When a new RSS item arrives, I'd like a VBA macro to delete all items in that folder which have the same From, Subject, and date Received values, but an older date Modified.

    I have had two problems figuring out how to do this:

    1) RSS items go into their own folder - this script assumes the item will be in the Inbox. Is there a way to trigger a script that processes only items in an RSS folder when a new item arrives?

    2) The script you wrote seems to iterate through and compare the new message to all of the previous items in the folder. With hundreds, or possibly thousands, of items in a folder, that could take a long time, especially when executing in real-time while new items are being received. Is there a way in Outlook VBA to iterate through the items in, say, date Received order so the iteration could stop when the compared date Received is older than the date Received of the new message?

    You would be a hero to many, many people if you came up with a script to solve this problem!

    Thanks in advance.

    • Diane Poremsky says

      I think the answer for both is No, but will look into it - it would be handy for me too. :) I have a feed that gets a lot of duplicates - i can stop it by setting Outlook to not treat changed items as new but I need the changed items, just not 200 copies. :)

    • Netpilot says

      Thanks for your reply. Yeah, the 'Don't treat changed items as new' setting doesn't do what we want. And anyone I know who uses feeds has at least one offender. :)

      Well, I've considered a workaround for #1 - Configure RSS settings to have items from all offending feeds go into a generic RSS folder named 'RSS Inbox', so you know where it lands. Then have a rule with a condition that checks for RSS items from all offending feeds by Feed Name (aka Title), then runs a script.

      The script would be hard-coded to look at the new item, and with a Select Case, based on the Feed Name, move it to its associated folder (same as the Feed Name by default), then compare older items in that folder against it, deleting as appropriate. Kind of messy, but gets the job done.

      The part I really don't know how to do is #2 - avoid iterating through all items in the associated folder. Is it possible to order, hash, or somehow sort the collection of obj[DestinationFolder].Items by date Received so that the search for duplicates can be stopped in a reasonable amount of time?

      Actually, I'm not even sure if scripts are run synchronously or asynchronously, i.e.., does Outlook wait until a script is finished before processing more rules on that item or any rules on the next incoming item? If it does not wait, the script had better be really well optimized.

  3. Peter M says

    Hi. Thank you very much. I am using your script exactly as it is and it is very helpful. Unfortunately, in the morning and especially after the weekend (so after the computer was running without interaction for many hours) i receive this error between once and many times:

    Microsoft Visual Basic
    Run-time error '[numbers here]'
    Method 'SentOn' of object '_MailItem' failed

    and when i click on Debug it highlights this line:

    If objVariant.Subject = Item.Subject And objVariant.SentOn < Item.SentOn Then

    and it seems that objVariant is NULL at this point so he can't get the SentOn

    can you help? what can i change in the script?

    thank you very much!


    • Diane Poremsky says

      If there are a lot of messages to process, it can fail because Outlook is downloading messages and the message count changes, confusing the script. The easiest fix is to add On Error Resume Next right before the line that fails - when it errors, it should skip to the next message.

  4. Ryan says

    Can't believe I am so close to finding a solution to this issue. I just need a little more (step by step) detail on setting this up. I am using Office 2013. Please help. This would be a life saver

    • Diane PoremskyDiane Poremsky says

      Scripts with names in this format:
      sub macroname (item as outlook.item)

      can only be run from other macros or using rules.

      if the name is in this format:
      public sub macroname()
      then you can run it any time in the editor or from the macro list.

Leave a Reply

Please post long or more complicated questions at OutlookForums by

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