Setting a Bulk Message Delay


Yesterday, while reading tweets, I stumbled across this one from ~R4~:

#Outlook folks out there: Is there a way to ‘bulk delay delivery’? Save outgoing email in a folder & autosend all email at specific time?

Outlook has the ability to set a message to go out on a specific date at a specific time, but that is set on a per message basis. There is no built-in way of setting Outlook to delay all messages unless you want to take the time to set a delay on each one. That would be tedious and the tedium would grow in direct proportion to the number of messages you want to send. It also would not work for a mail merge since the merge process sends the items immediately. One possible solution is to set Outlook to work off-line, then send messages. With Outlook working off-line the messages would accumulate in the outbox until such time as you allow Outlook to reconnect. The problem with this solution is that you can’t send or receive anything else because that would mean reconnecting Outlook which would immediately send the messages waiting in the outbox.

The solution then is to employ a macro to set the delay for you. The logic for this is straightforward. Use a switch to toggle delaying on/off. When delaying is toggled on the macro asks for the time/date to delay until. As messages are sent the macro checks to see if delaying is on. If it is, then the item is automatically set to wait until the specified time. If delaying is off, then nothing occurs.

With this macro in place ~R4~ can toggle delaying on, send a batch of messages that will be delayed, then toggle delaying off and continue sending and receiving normally. No need to take Outlook off-line.

The code for this comes in two parts.

Part 1.

Instructions.

  1. Start Outlook
  2. Press ALT+F11 to open Outlook’s VB editor
  3. If not already expanded, expand Project1
  4. Right-click Class Modules and select Insert > Class Module
  5. In the Properties panel click on Name and enter BulkDelayManager
  6. Copy the code from the Code Snippet box and paste it into the right-hand pane of Outlook’s VB Editor window
  7. Click the diskette icon on the toolbar to save the changes
Private bolBulkDelay As Boolean, _
        datBulkDelaySendAt As Date, _
        intDelay As Integer
Private WithEvents olkApp As Outlook.Application

Private Sub Class_Initialize()
    'On the next line enter the number of seconds to delay messages for if you want all messages to be delayed for a fixed amount of time.  Enter 0 if you want to be prompted for the date/time to delay until.'
    intDelay = 0
    bolBulkDelay = False
    Set olkApp = Outlook.Application
End Sub

Private Sub Class_Terminate()
    Set olkApp = Nothing
End Sub

Public Sub Toggle()
    bolBulkDelay = Not bolBulkDelay
    If intDelay = 0 Then
        If bolBulkDelay Then
            datBulkDelaySendAt = InputBox("Enter the date/time that messages will be delayed until.", "Set Bulk Delay Time", Format(Now(), "mm/dd/yy hh:nn AMPM"))
            If Not IsDate(datBulkDelaySendAt) Then
                bolBulkDelay = False
            End If
        End If
    End If
    msgbox "Bulk Delaying is now " & IIf(bolBulkDelay, " on.", " off."), vbInformation + vbOKOnly, "Bulk Delay Manager"
End Sub

Private Sub olkApp_ItemSend(ByVal Item As Object, Cancel As Boolean)
    If bolBulkDelay Then
        If intDelay = 0 Then
            Item.DeferredDeliveryTime = datBulkDelaySendAt
        Else
            Item.DeferredDeliveryTime = DateAdd("s", intDelay, Now)
        End If
        Item.Save
    End If
End Sub

Part 2.

Instructions.

  1. If not already expanded, expand Microsoft Office Outlook Objects and click on ThisOutlookSession
  2. Copy the code snippet below and paste it into the right-hand pane of Outlook’s VB Editor window
  3. Click the diskette icon on the toolbar to save the changes
  4. Close the VB Editor
  5. Open the Trust Center
  6. Click Macro Security
  7. Set Macro Security to “Warnings for all macros”
  8. Click OK
  9. Click the File tab.
  10. Click Options > Quick Access Toolbar.
  11. In the list under Choose commands from:, choose Macros. Find and select Project1.ThisOutlookSession.Toggle
  12. Click the Add button to add the macro, and then click the Modify… button to select a button image to associate with the macro.
  13. Click OK. You should see your new button on the Quick Access Toolbar above the File tab.
  14. Close Outlook
  15. Start Outlook. Outlook will display a dialog-box warning that ThisOutlookSession contains macros and asking if you want to allow them to run. Say yes.
Dim clsBDM As BulkDelayManager

Private Sub Application_Startup()
    Set clsBDM = New BulkDelayManager
End Sub

Private Sub Application_Quit()
    Set clsBDM = Nothing
End Sub

Sub ToggleBDM()
    clsBDM.Toggle
End Sub

Usage.

When ~R4~ wants to delay messages he will click the button on the Quick Access Toolbar. This will run the macro which will prompt him for the date/time to delay to, then toggle delaying on. Messages will now be delayed until he clicks the button again and turns delaying off.

Notes.

  1. This is a proof-of-concept macro designed to show that this can be done. The code as is does not do everything that a full solution would, such as check to make sure the date entered is valid. The macro is usable, but you could run into problems.
  2. This code is intended exclusively for Outlook 2010.
  3. The instructions may be slightly off. I do not have access to a copy of Outlook 2010 at the moment and could not check them to ensure they are correct.
  4. I have not tested the code under Outlook 2010. I tested the general process on Outlook 2007 and it worked fine there.

Change History.

  • 2011.07.20 – Added the ability to set a static delay (in seconds) in lieu of being prompted each time an item is sent.

80 comments on “Setting a Bulk Message Delay

  1. Hi David – is it possible to use this in Outlook 2016? We have Sage Payroll setup to place 90 emails with payslips attached into the DRAFT folder. It would be great if I could set Outlook to dealy the sending of any item in DRAFTS until a specific day / time.
    many thanks
    Rod

    • Hi, Rod.

      Yes, this will work in Outlook 2016. However, this doesn’t work against items in a folder. It works as you send items and it adds a specific amount of delay to each item you send rather than delaying all items to a specific date/time. In order to delay sending a group of messages to a specific date/time, you want something like this.

      Sub SendAtSpecificTime()
          Const SCRIPT_NAME = "Send at Specific Time"
          Dim olkMsg As Outlook.MailItem, strSnd As String, datSnd As Date, intCnt As Integer
          strSnd = InputBox("Enter the date and time you want the messages sent.", SCRIPT_NAME)
          If IsDate(strSnd) Then
              datSnd = strSnd
              For intCnt = Application.ActiveExplorer.Selection.Count To 1 Step -1
                  Set olkMsg = Application.ActiveExplorer.Selection.Item(intCnt)
                  olkMsg.DeferredDeliveryTime = datSnd
                  olkMsg.Send
              Next
          Else
              MsgBox "You did not enter a valid date/time.  Operation cancelled.", vbExclamation + vbOKOnly, SCRIPT_NAME
          End If
          Set olkMsg = Nothing
      End Sub
      

      This macro will delay sending the selected messages until a specific date/time. To use this

      1. Select the messages you want to act on
      2. Run the macro
      3. Enter the date/time you want the messages to send on

  2. I spoke too soon. The delay for X seconds works great but, it doesn’t apply the delay between messages. Meaning after X seconds all the emails on your outbox will be sent. It doesn’t add an X second delay to the next message.

    All I’m trying to do is delay each email from a mail merge for x seconds (relative to one another. To dumb it down. Send 1 email, then wait X seconds to send next email, then wait again X seconds for the next email.

    Your macro simply delays all the messages ready to go out at the same time, it should add x + x to the next email. And x + x + x to the third and so on. The delay you have in the macro can already be applied in outlook rules.

    Would greatly appreciate your feedback.
    Thanks

    • It wasn’t intended to apply the delay between messages. Yes, you can apply a set delay to all messages using rules. But, you can’t easily toggle that delay off and on, you can’t change the delay as easily, and a rules based delay is set to a number of minutes whereas this code can set the delay to a particular date and time. What you want is a progressive delay. That’s a different requirement from the one that caused me to write the original code.

      Here is a revised version tat implements a progressive delay. If the delay was set to 10 seconds, then the first message would be delayed by 10 seconds, the second by 20 seconds, the third by 30 seconds, and so on. Toggling the delay on/off resets the progressive counter to 0. Note that I wrote this off the top of my head and have not tested it.

      Private bolBulkDelay As Boolean, _
              datBulkDelaySendAt As Date, _
              intDelay As Integer, _
              lngCurrentDelay As Long
      
      Private WithEvents olkApp As Outlook.Application
       
      Private Sub Class_Initialize()
          'On the next line enter the number of seconds to delay each message for if you want all messages to be delayed for a progressively fixed amount of time.  Enter 0 if you want to be prompted for the date/time to delay until.'
          intDelay = 0
          bolBulkDelay = False
          Set olkApp = Outlook.Application
      End Sub
       
      Private Sub Class_Terminate()
          Set olkApp = Nothing
      End Sub
       
      Public Sub Toggle()
          bolBulkDelay = Not bolBulkDelay
          If intDelay = 0 Then
              If bolBulkDelay Then
                  datBulkDelaySendAt = InputBox("Enter the date/time that messages will be delayed until.", "Set Bulk Delay Time", Format(Now(), "mm/dd/yy hh:nn AMPM"))
                  If Not IsDate(datBulkDelaySendAt) Then
                      bolBulkDelay = False
                  End If
              End If
          Else
              lngCurrentDelay = 0
          End If
          msgbox "Bulk Delaying is now " & IIf(bolBulkDelay, " on.", " off."), vbInformation + vbOKOnly, "Bulk Delay Manager"
      End Sub
       
      Private Sub olkApp_ItemSend(ByVal Item As Object, Cancel As Boolean)
          If bolBulkDelay Then
              If intDelay = 0 Then
                  Item.DeferredDeliveryTime = datBulkDelaySendAt
              Else
                  lngCurrentDelay = lngCurrentDelay + intDelay
                  Item.DeferredDeliveryTime = DateAdd("s", lngCurrentDelay, Now)
              End If
              Item.Save
          End If
      End Sub
      
  3. Saved my day!!!
    All I needed was to delay all messages with X seconds.
    This is incredibly useful for spam flag prevention.

  4. HI David – I’ve used this post in the past with much success. But today I”m trying to set it up on Outlook 2016 and I’m getting a Compile error: User-defined tuype not defined and it has the “Dim clsBDM As BulkDelayManager” highlighted. What are your thoughts on fixing this?

    • Nevermind – I made the same mistake as a previous post of not changing the name of the class. Thanks again for posting this.

  5. This is a great time save and works perfectly on Outlook 2013. Thank you!
    I don’t suppose there is a way of either merging with another contact in CC? Or adding attachments to all emails? thanks

    • Hi, Nick.

      Thanks!

      I’m not clear on what you have in mind when you say “merging”. If that means to add an addressee, then yes that’s possible. Ditto for adding an attachment.

  6. sir i am continuously facing a error (object variable or with block variable not set)
    please teach me how i fixed this error

    • Hi, Jennifer.

      The error message suggests one of two problems.

      1. The code from part 1 isn’t in a class module.
      2. The code from part 1 is in a class module but the class module isn’t named BulkDelayManager.

      Please double-check to make sure that the code from part 1 is in a class module and that the module is named BulkDelayManager.

  7. Dear David.
    Macro is finally working for me.
    I had a mistake in Names.
    I named project as BulkDelayManager instead of Class.
    So I had project with name BulkDelayManager and Class1.
    Now I changed it to correct names:
    – Project1 stays as Project1
    – Class1 renamed to BulkDelayManager
    Macro works now.

    BR, Paul.

  8. (somehow the comment feed doesn’t let me post any reply to my own comment)
    Hi David, I can’t really tell which line, as the error does not mark any of them.

  9. Hi, I tried to use your macro, but I received this error message: “Object variable or With block variable not set”

    (when I tried to run the macro from the quick access toolbar, nothing happened, and I received this message while trying to run it from the VBA Editor)

    Could you please help me how to fix this issue?

    • Hi, Paul.

      The screenshot doesn’t show whether you added the code from Part 1 in a classmodule named BulkDelayManager. Does that module exist and is the code from part #1 in it?

    • Hi, Michelle.

      The delay can be anything you want i to be. If you want the standard delay to be three days, then you’ll want to modify the code to use days instead of seconds. The only line that must be be changed is line 35. Change that line to this line

      Item.DeferredDeliveryTime = DateAdd("d", intDelay, Now)
      

      Then on line 8 set the number of days to delay instead of the number of seconds.

  10. This is brilliant. I have never programmed a macro, and am using Word/Outlook 2013, but found the instructions excellent, and I’ll use this again and again. Thank you David!

  11. Hi David,

    How can we do this, say from the que of 5k messages in the outbox just need to send first 1400 then make a pause of 5 minutes then again send another 1400 message then a pause of 5 mins and on & on. I am using outlook 2007

    • Hi, Abhivandan.

      I’m not sure that’s possible, at least not in the way you described. Once an item is in the outbox you’ve lost control of when it’s sent. I don’t remember there being a way to limit a send to a certain number of items. Even if there is a way to control that, the only way to prevent Outlook from sending the remaining items would be to disable send/receive until the next send period. Fortunately, there’s a better way to do this that doesn’t require any workarounds, setting timers, etc. Outlook supports setting the date/time a message is to be sent. Rather than dumping all the messages in the Outbox and then trying to control when they’re sent, set the send date/time when the messages are sent. In other words, set the first 1,400 messages to go 5 minutes from now, the next 1,400 messages to go 5 minutes after that, and so on until you run out of messages. There are two ways to do this. First, create the messages and save them to a folder. Use a macro to process all the messages in that folder doing what I just described. Or, use a macro to create and send the messages as I described. Would that work for what you need?

  12. I have been searching or somthing similar, to help automate periodic emails to customers. I was looking to do a mail-merge in Word that would attach specific files, and specify a delay before sending (wanted to send 25 emails every 15 minutes). That quantity and delay time would vary. This looks like with modifications may be part of a final solution. THANK YOU

  13. Dave,

    Just did all instructed using Outlook 2003 and got an error. Does it work with outlook 2003?

    Henry

    • David, I got rid of the ‘invalid outside procedure’ error in line 1 by eliminating the line numbers. Now after clicking the new created button an input frame comes up where I can enter the needed date and time, yet the message still goes out instantly.

    • David,

      Just played with the seconds and the macro will allow my to input up to 9,999 seconds delay for which the message will just sit in the outbox, yet what I need is 20-24 hours – over 72,000 seconds to which the macro will respond a overflow ‘6’

    • I was hoping for the messages to sit in my outbox this was the reason I looked up and used your macro, but the messages are sent out instantly instead.

    • I wanted to correct myself the largest seconds value I could get the macro to work with is 37,767 I still need double than that. Any advice?

    • I’m a little confused. If you enter a date/time as the delay, then the messages should be delayed until that date/time without regard to how far in the future it is. If instead you enter a number of seconds, then there is a limit imposed by the fact that I chose to use an integer value. In your earlier post I think you said you were entering a date/time. If so, are you saying that it isn’t working but delaying for a number of seconds is?

    • This is correct, it will not work at all with the entered date and time, yet will work just fine up to 37767 seconds.

    • David,

      I got it to work by entering the needed date/time “mm/dd/yy hh:mm AM” manually in the macro.

      Thank you very much, Henry

    • It works and does exactly the way you wrote it, I tried it from within outlook and it woks fine. The reason I said it did not work was when I was using Word to send an email message via outlook, in this case the message will go out instantly disregarding Outlook macro restriction. Here was my problem, sorry for confusing you.

  14. Hi David. This is a great macro. Can it be customized? For example, let’s say I have 10 emails “parked” in the outbox queue (send/receive automatically has been disabled), and would like to send no more than 2 emails every 120 seconds. In a summary, would it possible to specify how many emails you want to send every X seconds? Even better, being able to delay delivery by X seconds in between each email that are stacked the outbox queue? Your inputs are appreciated.

    • Hi, Xavier.

      Thanks!

      I want to make sure I understand what you want. You want set a progressive delay on each message sent. If there are no messages in the Outbox, then delay the next message added by x seconds. If there are messages in the Outbox, then delay the next message x seconds longer than the delay on the last message. Does that sound like the right logic?

    • I am not following you. What do you mean by ”progressive delay”, or “added by x seconds”? Let me clarify, I use mail/merge option for my newsletter. I usually have 30 to 100 emails created and piled in the outbox. I do not want to send all emails at once, since it could red flagged my email address. What I am looking for is to be able to send X emails every Y seconds, until outbox is emptied… In this example, parameters could be set as “send no more than 2 emails every 120 seconds” or “send no more than 1 email every 60 seconds”, “or send one email at a time, and delay each email delivery by 30 seconds”… With the said parameters, and if I have 30 emails, it would take 15 minutes to complete the process.

    • “Even better, being able to delay delivery by X seconds in between each email that are stacked the outbox queue?”

      “Progressive delay” = Delaying the next message added to the Outbox by X * Y where X is the number of messages already in the Outbox and Y is the delay factor in seconds. For example, say that the Outbox already contains 3 messages and the delay factor is 10 seconds. If you add a 4th, then that message would be delayed for 40 seconds. An alternative would be to read the delay on the third message and add X seconds to that time (i.e. “added by x seconds”).

      There is no way I know of to limit the send process to some number of messages per send. The only way I know of to do this is to set a message delay. That will hold the messages in the Outbox until they are due to be sent.

  15. Hi David,

    I could able to copy the code and pasted to VB by pressing ALT F11 for outlook 2010…but still my mails are immidiatley sent from the outbox…and i have mentioned “intDelay = 1000” and so on for the rest of the other place…still no effect on mail’s…please advise what needs to be corrected… and am able to get the new icon on file tab…requirement little urgent pls help…

    • Hi, Nagendra.

      Are macros enabled? I don’t understand what you mean when you say “am able to get the new icon on file tab”. Can you clarify?

    • HI David,

      Yes macros enabled, i mean to say the icon on file tab appears as bulkdelaymanager toggle…since i have done the procedure as explained by you…i am missing semething i hope…the moment when i send electronic mail from word 2010…the email’s will just shoot from outbox.

    • I will test sending from Word to see what happens. In the meantime, does the code work when you send from Outlook?

    • Then I have to think that macros are not working. Are you familiar with setting a breakpoint in the VBA editor? If so, please set a breakpoint in the code and then send something. Let me know if the breakpoint is triggered.

    • Open the VB editor (ALT+F11), go to the module with the code, and select the first line inside of a subroutine. With a line selected press F9. The line should turn yellow. Now, send a message. If the code is active, then it will pause and open the VB editor when it gets to that line. If the code is not active, then nothing will happen. If nothing happens, then we know that macros are not working at all. If the code runs, then we know that macros are working and there’s a problem with the code.

  16. Hi David. Great code, and good idea.

    I wonder if you could suggest a modification that would make Outlook delay all messages by a settable number of seconds. This delay would be hard coded into the macro rather than Outlook prompting you each time. As we all know, you can’t undo message sending so delaying all messages by say 20 seconds could be really useful sometimes!

    I think loads of people would use a macro like that. I’ve searched and can’t find one.
    thanks 🙂

Leave a reply to John Cancel reply