Menu

#135 out-poll-run retry not working

v1.0 (example)
open
nobody
None
5
2026-05-20
2026-05-18
Jos A
No

Hello and thank you for your very useful software!

In the documentation in the section called Advanced set-up there is an option --out-poll-run retry:5
Whatever I try, I cannot get it to work. The version I have is 2.6.1 for Windows, downloaded and installed about two months ago, I think it's still the latest (or maybe you did a commit in the meantime but kept the same version number?).

I tried both command line and setting it in the cfg-file. However I try E-MailRelay simply refuses to start when I use this option (using cfg: invalid option "out-poll-run", using cmd: too many non-option arguments).

Is there extra information available about this particular option? I looked in the doc folder but didn't see anything relevant.

Somehow I got the impression that this is a "coming soon"-feature but I'm not sure where I got it from. Is this feature simply not released yet but somehow it ended up in the docs early?

I saw the provided example script emailrelay-resubmit.js but if this feature is available built-in I'd much prefer using that rather than setup a separate scheduled task to run that script in combination with --poll.

Kind regards

Discussion

  • Graeme Walker

    Graeme Walker - 2026-05-18

    Sorry, that's my mistake. As you guessed, the online documentation was generated from un-released code, so there is no "--poll-run" in v2.6.x. There was a support ticket several years ago where I floated the idea and I have implemented it ready for v2.7, but it is not yet released.

     
  • Jos A

    Jos A - 2026-05-18

    Ok thanks for responding so fast! From the tone of your response I gather that v2.7 will still take a while to be released and that I should just setup a scheduled task using the example script.

    As a kind of feedback for you I ran the example script through LLM (sorry!) and it warned me that if there were many bad files it would read them all every time doing unnecessary repeated work. It suggested doing a check against file.DateLastModified as a safeguard. Something like this:

    var cfg_min_age_seconds = 30 ;   // NEW
    ...
        if( path.match(re_bad) )
        {
            // ---- NEW: age check ----
            var age_seconds = (now - file.DateLastModified) / 1000 ;
            debug( "age_seconds: " + age_seconds ) ;
    
            if( age_seconds < cfg_min_age_seconds )
            {
                debug( "skip (too new)" ) ;
                continue ;
            }
    ...
    

    Again, thank you!

     
  • Jos A

    Jos A - 2026-05-20

    I made some changes to the example script, I thought I'd share for anyone interested. This version adds some safety and control features like skipping files that are too new or too old, limiting how many emails it processes at once and avoiding overwriting existing files. It includes some error handling and reporting, a bit more reliability, a summary, and I tried to minimize impact on system performance.

    I tested it a little already (works so far) and will be testing it more in the coming days. Don't hesitate to tell me if you spot anything.

    Edit: this is meant for Windows.

    Here is a link to the original script if you want to compare.

    //
    // Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
    //
    // Copying and distribution of this file, with or without modification,
    // are permitted in any medium without royalty provided the copyright
    // notice and this notice are preserved. This file is offered as-is,
    // without any warranty.
    // ===
    //
    // emailrelay-resubmit.js
    //
    // A utility script for Windows that looks for all failed e-mails in the
    // E-MailRelay spool directory and resubmits them. However, if an e-mail has
    // been retried five* times already then it is not submitted again.
    //
    // *: amount of retries is configurable
    //
    // usage: cscript //nologo emailrelay-resubmit.js [optional:<spool-dir>]
    // example: cscript //nologo emailrelay-resubmit.js "C:\ProgramData\E-MailRelay\spool"
    // 
    // Important: do not run multiple instances of this script at the same time.
    //
    // Script modified by Jos on 19/5/2026
    //
    
    // ---------------------
    // Configuration section
    // ---------------------
    
    // If no spool-dir is specified in command line the script will use this value
    // Here use double \\ or linux style / between folders
    var cfg_spooldir = "C:\\ProgramData\\E-MailRelay\\Spool" ;
    
    // Amount of times to retry the same envelope by removing the .bad extension
    var cfg_retry_limit = 5 ;
    
    // Show Debug output in console
    var cfg_debug = false ;
    
    // skip .bad files younger than this many seconds
    // avoids processing files still being written by EmailRelay
    var cfg_min_age_seconds = 5 ;
    
    // skip .bad files older than this many hours (0 = no filtering)
    // prevents endless opening and parsing of old files
    var cfg_max_age_hours = 24 ;
    
    // Safety: max total bad-files to process limit for one run (0 = no limit)
    // remaining files will be processed on next run
    var cfg_max_resubmits = 500 ;
    
    // ---------
    // Constants
    // ---------
    var BAD_SUFFIX = ".bad" ;
    var REASON_MARKER = "MailRelay-Reason: " ;
    
    // ---------------
    // Statistics init
    // ---------------
    var stat_processed = 0 ;
    var stat_retried = 0 ;
    var stat_skipped = 0 ;
    var stat_errors = 0 ;
    var stat_too_old = 0 ;
    var stat_too_young = 0 ;
    var stat_limit_reached = 0 ;
    
    // ---------
    // Functions
    // ---------
    
    // debug output to console
    function debug( line )
    {
        if( cfg_debug )
        {
            WScript.StdOut.WriteLine( "debug: " + line ) ;
        }
    }
    
    // ---------------------
    // Retry envelopes logic
    // ---------------------
    
    // parse the command line
    var args = WScript.Arguments ;
    
    if( args.length >= 1 )
    {
        cfg_spooldir = args(0) ;
    }
    
    // check the spool directory
    var fso = WScript.CreateObject( "Scripting.FileSystemObject" ) ;
    
    if( !fso.FolderExists( cfg_spooldir ) )
    {
        WScript.Echo( "invalid spool directory: \"" + cfg_spooldir + "\"" ) ;
        WScript.Quit( 1 ) ;
    }
    
    // process files
    var folder = fso.GetFolder( cfg_spooldir ) ;
    var iter = new Enumerator( folder.Files ) ;
    var starttime = new Date() ;
    
    for( ; !iter.atEnd() ; iter.moveNext() )
    {
        // stop script when resubmit limit reached
        if( cfg_max_resubmits > 0 &&
            stat_retried >= cfg_max_resubmits )
        {
            debug( "maximum resubmit limit reached" ) ;
            break ;
        }
    
        var stream = null ;
        var path = null ;
    
        try
        {
            var file = iter.item() ;
            path = file.Path ;        
    
            // only process .bad files
            //
            if( path.length < BAD_SUFFIX.length ||
                path.substr(
                    path.length - BAD_SUFFIX.length
                ).toLowerCase() != BAD_SUFFIX )
            {
                debug( "ignoring: " + path ) ;
    
                continue ;
            }
    
            debug( "found: " + path ) ;
            stat_processed++ ;
    
            // skip empty files
            if( file.Size <= 0 )
            {
                debug( "skipping empty file!" ) ;
    
                stat_skipped++ ;
                continue ;
            }
    
            // compute age once
            var age_seconds =
                ( starttime - file.DateLastModified ) / 1000 ;
    
            var age_hours = age_seconds / 3600 ;
    
            // skip too young files
            if( age_seconds < cfg_min_age_seconds )
            {
                debug( "skipping new file (" +
                    Math.round(age_seconds) + " sec old)" ) ;
    
                stat_too_young++ ;
                continue ;
            }
    
            // skip old files if configured
            if( cfg_max_age_hours > 0 &&
                age_hours > cfg_max_age_hours )
            {
                debug( "skipping old file (" +
                    age_hours.toFixed(2) + " hours old)" ) ;
    
                stat_too_old++ ;
                continue ;
            }
    
            // count failure lines
            stream = fso.OpenTextFile( path , 1 ) ;
    
            var failures = 0 ;
    
            while( !stream.AtEndOfStream )
            {
                var line = stream.ReadLine() ;
    
                if( line.indexOf( REASON_MARKER ) >= 0 )
                {
                    failures++ ;
    
                    // no need to continue once limit reached
                    if( failures >= cfg_retry_limit )
                    {
                        stat_limit_reached++ ;
                        break ;
                    }
                }
            }
    
            debug( "failures: " + failures ) ;
    
            // close stream before rename attempt
            stream.Close() ;
            stream = null ;
    
            // resubmit if under retry limit
            if( failures < cfg_retry_limit )
            {
                var new_path =
                    path.substr(
                        0 ,
                        path.length - BAD_SUFFIX.length
                    ) ;
    
                // avoid overwriting existing file
                if( fso.FileExists( new_path ) )
                {
                    debug( "destination already exists: " + new_path ) ;
                    stat_skipped++ ;
                    continue ;
                }
    
                debug( "rename: " + path + " -> " + new_path ) ;
    
                fso.MoveFile( path , new_path ) ;
    
                stat_retried++ ;
            }
            else
            {
                stat_skipped++ ;
            }
        }
        catch( e )
        {
            stat_errors++ ;
    
            if( path )
            {
                WScript.Echo(
                    "error processing file: " + path + "\n" +
                    "reason: " + e.message
                ) ;
            }
            else
            {
                WScript.Echo(
                    "error processing unknown file: " + e.message
                ) ;
            }
        }
        finally
        {
            if( stream != null )
            {
                try
                {
                    stream.Close() ;
                }
                catch( close_error )
                {
                    // ignore close errors
                }
            }
        }
    }
    
    if( cfg_debug )
    {
        // summary
        WScript.Echo(
            "processed=" + stat_processed +
            " retried=" + stat_retried +
            " skipped=" + stat_skipped +
            " too_young=" + stat_too_young +
            " too_old=" + stat_too_old +
            " limit_reached=" + stat_limit_reached +
            " errors=" + stat_errors
        ) ;
    }
    
    WScript.Quit( 0 ) ;
    
     

    Last edit: Jos A 2026-05-20

Log in to post a comment.

Monday.com Logo