       continue if dt_expires.isBefore() # skip expired
     continue if 'type' of params and params.type != e.type
     continue if 'search' of params and e.val.indexOf(params.search) == -1
+    if 'expire_notify' of params # if pre-expiration notify, only do it once
+      continue if 'expire_notified' of e and e.expire_notified
+      e.expire_notified = true
     reason = ''
     reason = e.reason if 'reason' of e
     if reason.indexOf("\n") > 0


  unless isAuthorized msg
    usermsg = "or specify `-r` to request listing"
    logmsg = "#{modulename}: #{who} listing failed: #{usermsg}"
    robot.logger.info logmsg
    return msg.send usermsg
  unless is2fa msg
    usermsg = "or specify `-r` to request listing"
    logmsg = "#{modulename}: #{who} listing failed: #{usermsg}"
    robot.logger.info logmsg
    return msg.send usermsg


  clientip = req.connection.remoteAddress || req.socket.remoteAddress ||
    req.connection.socket.remoteAddress

  logmsg = "#{modulename}_#{func_name}: web request from #{clientip}"
  robot.logger.info logmsg

  arr = ["<html>\n<body>\n<pre>\n"]
