From 6ef42d0127fdf4193c0d377c6c4e0d89426030fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 13:19:48 +0200 Subject: [PATCH 01/12] ... --- debian/control | 1 + msmtp-yaqi | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 6ca8a1c..35ed8e2 100644 --- a/debian/control +++ b/debian/control @@ -11,4 +11,5 @@ Architecture: all Multi-Arch: foreign Provides: msmtpq, msmtp-queue Depends: ${misc:Depends}, ${shlibs:Depends}, msmtp +Suggests: inotify-tools Description: Yet Another Queue Implementation for MSMTP diff --git a/msmtp-yaqi b/msmtp-yaqi index aa213c4..c4955b8 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -3,7 +3,7 @@ # # # msmtp-yaqi: Yet Another Queue Implementation for MSMTP # # --------------------------------------------------------------------- # -# Version 0.1.1 by Christian Schrötter # +# Version DEV by Christian Schrötter # # # # Inspired by msmtpq (Chris Gianniotis) and msmtpqueue (Martin Lambers) # # # @@ -641,6 +641,16 @@ if [[ "${1:-}" == '--q-mgmt' ]] then BASECMD=msmtp-queue shift +# daemon mode +elif [[ "${1:-}" == '--daemon' ]] +then + echo "daemon mode" + exit 1 + + # inotifywait --monitor --include '^.+-.+-.+,[^-]+$' --format '%T' --timefmt '%s' --event moved_to ... \ + # | msmtp-yaqi --daemon-events &[disown] (read stdin line by line, sleep 1s, check last timestamp of event) + + # fallback loop: run queue after ~60s fi # msmtp-queue - queue management mode @@ -723,6 +733,7 @@ then h) stderr "Usage: msmtpq [sendmail options]" stderr + stderr " or msmtpq --daemon" stderr " or msmtpq --q-mgmt [ ...]" stderr " or msmtp-queue [ ...]" stderr @@ -777,6 +788,7 @@ then esac lock_queue -u +# sendmail mode else enqueue_mail "$@" fi From 0cab72099eb03a832664e884a153b780ae493aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 20:29:14 +0200 Subject: [PATCH 02/12] ... --- debian/control | 2 +- debian/postinst | 5 +++-- msmtp-daemon | 1 + msmtp-yaqi | 45 ++++++++++++++++++++++++++++++++------------- 4 files changed, 37 insertions(+), 16 deletions(-) create mode 120000 msmtp-daemon diff --git a/debian/control b/debian/control index 35ed8e2..185d19f 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Homepage: https://github.com/froonix/msmtp-yaqi Package: msmtp-yaqi Architecture: all Multi-Arch: foreign -Provides: msmtpq, msmtp-queue +Provides: msmtpq, msmtp-queue, msmtp-daemon Depends: ${misc:Depends}, ${shlibs:Depends}, msmtp Suggests: inotify-tools Description: Yet Another Queue Implementation for MSMTP diff --git a/debian/postinst b/debian/postinst index 639c6d6..3a85508 100755 --- a/debian/postinst +++ b/debian/postinst @@ -6,8 +6,9 @@ case "${1}" in ;; configure) - update-alternatives --install /usr/bin/msmtpq msmtpq /usr/bin/msmtp-yaqi 100 - update-alternatives --install /usr/bin/msmtp-queue msmtp-queue /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtpq msmtpq /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtp-queue msmtp-queue /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtp-daemon msmtp-daemon /usr/bin/msmtp-yaqi 100 ;; *) diff --git a/msmtp-daemon b/msmtp-daemon new file mode 120000 index 0000000..dc82fad --- /dev/null +++ b/msmtp-daemon @@ -0,0 +1 @@ +msmtp-yaqi \ No newline at end of file diff --git a/msmtp-yaqi b/msmtp-yaqi index c4955b8..90c15c2 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -637,20 +637,26 @@ read_config ~/.msmtpq.conf # and delete $queue_file trap cleanup EXIT +# todo: move to the top! +function daemon_events +{ + while IFS=$'\n' read -r timestamp + do + echo "event received: $timestamp" + + # (read stdin line by line, sleep 1s, check last timestamp of event) + # ... + done +} + if [[ "${1:-}" == '--q-mgmt' ]] then BASECMD=msmtp-queue shift -# daemon mode elif [[ "${1:-}" == '--daemon' ]] then - echo "daemon mode" - exit 1 - - # inotifywait --monitor --include '^.+-.+-.+,[^-]+$' --format '%T' --timefmt '%s' --event moved_to ... \ - # | msmtp-yaqi --daemon-events &[disown] (read stdin line by line, sleep 1s, check last timestamp of event) - - # fallback loop: run queue after ~60s + BASECMD=msmtp-daemon + shift fi # msmtp-queue - queue management mode @@ -733,18 +739,23 @@ then h) stderr "Usage: msmtpq [sendmail options]" stderr - stderr " or msmtpq --daemon" stderr " or msmtpq --q-mgmt [ ...]" stderr " or msmtp-queue [ ...]" stderr + stderr " or msmtpq --daemon" + stderr " or msmtp-daemon" + stderr stderr "Yet Another Queue Implementation for MSMTP" stderr stderr "Sendmail mode:" stderr - stderr " Just send your mail content to STDIN." - stderr " Your message will be added to the queue." - stderr " Don't forget to setup a queue-run cronjob!" - stderr " Otherwise it'll be held forever in queue." + stderr " Just send your mail content to STDIN. Your message will be added to the queue." + stderr " Don't forget to setup a queue-run cronjob! Otherwise it'll be held forever in queue." + stderr + stderr "Daemon mode:" + stderr + stderr " Runs the mail queue every 90 seconds and when new messages are queued." + stderr " Alternatively use a regular cronjob or Systemd timer: msmtp-queue -r" stderr stderr "Queue management options:" stderr @@ -788,6 +799,14 @@ then esac lock_queue -u +# daemon mode (inotifywait) +elif [[ "$BASECMD" == 'msmtp-daemon' ]] +then + [[ -n "$*" ]] && error "Options not supported at daemon mode!" + command -v inotifywait &>/dev/null || error "inotifywait is required for daemon mode!" + inotifywait -q -m -e moved_to --include '^.+-.+-.+,[^-]+$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & + while true; do sleep 90; echo run_queue; done + exit 1 # sendmail mode else enqueue_mail "$@" From a902ad51174c7be50a407f1bdb2656e2a8e1ce18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 21:04:00 +0200 Subject: [PATCH 03/12] ... --- debian/control | 2 +- msmtp-yaqi | 61 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/debian/control b/debian/control index 185d19f..f5f85f2 100644 --- a/debian/control +++ b/debian/control @@ -11,5 +11,5 @@ Architecture: all Multi-Arch: foreign Provides: msmtpq, msmtp-queue, msmtp-daemon Depends: ${misc:Depends}, ${shlibs:Depends}, msmtp -Suggests: inotify-tools +Recommends: inotify-tools Description: Yet Another Queue Implementation for MSMTP diff --git a/msmtp-yaqi b/msmtp-yaqi index 90c15c2..12ee325 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -271,7 +271,7 @@ function run_queue } # send_mails ... -send_mails() +function send_mails() { local q h='' f file local -i state=0 @@ -344,7 +344,7 @@ send_mails() } # purge_mails ... -purge_mails() +function purge_mails() { local q f file local -i state=0 @@ -378,7 +378,7 @@ purge_mails() } # Display queue contents. -display_queue() +function display_queue() { local -i i=0 local -i current @@ -458,7 +458,7 @@ function get_details } # Get msmtp argument list from queue file. -get_header() +function get_header() { declare -g queue_header queue_header=$(head -n 1 "$1" 2>/dev/null) @@ -466,7 +466,7 @@ get_header() } # Get real mail content from queue file. -get_content() +function get_content() { declare -g queue_content queue_content=$(tail -n +2 "$1" 2>/dev/null) @@ -561,7 +561,7 @@ function holding } # hold_mails [-u] ... -hold_mails() +function hold_mails() { local q n f file local -i state=0 @@ -607,6 +607,36 @@ hold_mails() return "$state" } +# inotifywait worker +function daemon_events +{ + local last=0 + while IFS=$'\n' read -r timestamp + do + [[ "$last" == "$timestamp" ]] && continue + log -d "New event received: $timestamp" + last=$timestamp + sleep 1 + + lock_queue + run_queue + lock_queue -u + done +} + +function daemon_fallback +{ + BASECMD+=" (fallback)" + while true + do + lock_queue + run_queue + lock_queue -u + + sleep 90 + done +} + # Trap callback. function cleanup { @@ -637,18 +667,6 @@ read_config ~/.msmtpq.conf # and delete $queue_file trap cleanup EXIT -# todo: move to the top! -function daemon_events -{ - while IFS=$'\n' read -r timestamp - do - echo "event received: $timestamp" - - # (read stdin line by line, sleep 1s, check last timestamp of event) - # ... - done -} - if [[ "${1:-}" == '--q-mgmt' ]] then BASECMD=msmtp-queue @@ -803,9 +821,10 @@ then elif [[ "$BASECMD" == 'msmtp-daemon' ]] then [[ -n "$*" ]] && error "Options not supported at daemon mode!" - command -v inotifywait &>/dev/null || error "inotifywait is required for daemon mode!" - inotifywait -q -m -e moved_to --include '^.+-.+-.+,[^-]+$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & - while true; do sleep 90; echo run_queue; done + command -v inotifywait &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" + command -v "${cfg[MSMTP]}" &>/dev/null || error "${cfg[MSMTP]} binary not found! Install it or change MSMTP config variable." + inotifywait -q -m -e moved_to --include '^.+-.+-.+,0$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & + daemon_fallback exit 1 # sendmail mode else From d5c244efd19323bab625994ef04d6e194886d6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 21:28:04 +0200 Subject: [PATCH 04/12] ... --- msmtp-yaqi | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/msmtp-yaqi b/msmtp-yaqi index 12ee325..5301902 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2320 ######################################################################### # # # msmtp-yaqi: Yet Another Queue Implementation for MSMTP # @@ -462,7 +463,7 @@ function get_header() { declare -g queue_header queue_header=$(head -n 1 "$1" 2>/dev/null) - [[ -z "$queue_header" ]] && log -e "$?" "Could not read header from queue file $1" + [[ -z "$queue_header" ]] && log -e 74 "Could not read header from queue file $1" } # Get real mail content from queue file. @@ -470,7 +471,7 @@ function get_content() { declare -g queue_content queue_content=$(tail -n +2 "$1" 2>/dev/null) - [[ -z "$queue_content" ]] && log -e "$?" "Could not read content from queue file $1" + [[ -z "$queue_content" ]] && log -e 74 "Could not read content from queue file $1" } # Insert mail from STDIN into queue. @@ -492,11 +493,12 @@ function enqueue_mail # changing existing files. Theoretical it's not required to do # the following check, because race-conditions are impossible, # as long there's only one host writing to this queue directory. - [[ -f "$queue_file" ]] || ls "$queue_file",* &>/dev/null \ - && log -e 1 "Queue file already exists: ID $queue_id" + [[ -f "$queue_file" ]] || ls -- "$queue_file",* &>/dev/null \ + && log -e 74 "Queue file already exists: ID $queue_id" # Write escaped arguments to temporary queue file. - cat <<< "$(printf '%q\n' "$@" | tr '\n' ' ')" > "$queue_file" || log -e "$?" "Queue header write failed: ID $queue_id" + cat <<< "$(printf '%q\n' "$@" | tr '\n' ' ')" > "$queue_file" \ + || log -e "$?" "Queue header write failed: ID $queue_id" if [[ "${cfg[HEADER]}" -eq 1 ]] then @@ -638,6 +640,7 @@ function daemon_fallback } # Trap callback. +# shellcheck disable=SC2317 function cleanup { declare -g locked From 5f761df3a33ed5fb4978eb0ec47236aed95b0e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 21:36:23 +0200 Subject: [PATCH 05/12] ... --- debian/changelog | 7 +++++++ msmtp-yaqi | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index d930324..1c6a303 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +msmtp-yaqi (0.2.0-1) UNRELEASED; urgency=medium + + * Implement daemon mode. + * Fix various bugs. + + -- Christian Schrötter Tue, 16 Apr 2024 21:34:34 +0200 + msmtp-yaqi (0.1.1-1) experimental; urgency=medium * Hotfix: Hold mails with retry-counter 0. diff --git a/msmtp-yaqi b/msmtp-yaqi index 5301902..372a03d 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -4,7 +4,7 @@ # # # msmtp-yaqi: Yet Another Queue Implementation for MSMTP # # --------------------------------------------------------------------- # -# Version DEV by Christian Schrötter # +# Version 0.2.0 by Christian Schrötter # # # # Inspired by msmtpq (Chris Gianniotis) and msmtpqueue (Martin Lambers) # # # From ace5d0f02f22a79f28fc5799cdd54af915966ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Tue, 16 Apr 2024 21:44:48 +0200 Subject: [PATCH 06/12] ... --- msmtp-yaqi | 199 ++++++++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 94 deletions(-) diff --git a/msmtp-yaqi b/msmtp-yaqi index 372a03d..8b554b5 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -639,6 +639,107 @@ function daemon_fallback done } +function example_config +{ + echo '############################################################' + echo '# msmtp-yaqi example configuration file: ~/.msmtpq.conf #' + echo '# Looks like Bash but it is a simple plaintext format! #' + echo '############################################################' + echo + echo '## Path to msmtp binary' + echo '#MSMTP=msmtp' + echo + echo '## Path to queue directory. Relative to $''HOME path!' + echo '## mkdir -v ~/.msmtpq && chmod -c 0700 ~/.msmtpq' + echo '#QUEUE=.msmtpq' + echo + echo '## Path to logfile.' + echo '## Relative to $''HOME!' + echo '## Disabled by default.' + echo '#LOGFILE=' + echo + echo '## Prefixed timestamp format for logfile.' + echo '#LOGFILE_TIME_FORMAT=%Y-%m-%d %H:%M:%S' + echo + echo '## Log to syslog?' + echo '## Facility mail.*' + echo '#SYSLOG=off' + echo + echo '## Output log messages to STDERR too?' + echo '## Facility: mail.{debug,info,warn,err}' + echo '#QUIET=off' + echo + echo '## Enable all debug messages? (Only for development!)' + echo '## Will be logged to file and syslog too if enabled.' + echo '#DEBUG=off' + echo + echo '## Add additional headers at enqueue and while sending?' + echo '## Contains enqueue timestamp and internal retry counter.' + echo '#HEADER=off' + echo + echo '## Sent mails archive directory.' + echo '## Relative to $''HOME path!' + echo '#ARCHIVE=' + echo + echo '## Wait time after failed delivery tries.' + echo '## Will be doubled after each failed retry!' + echo '## State estimated per message, not globally.' + echo '## Always and only calculated by enqueue time.' + echo '## Time in seconds. Use "0" to disable it.' + echo '#DEFER=300' + echo + echo '## Count message as undeliverable after retries.' + echo '## The message will be deleted from queue and is lost.' + echo '## Use "0" to disable this feature. (Not recommended!)' + echo '## Estimate your best value: $''((2 ** ( - 1) * DEFER))' + echo '#UNDEV=12' + echo + echo '## Maximum elements per run with -r.' + echo '## Works only, when DEFER is enabled.' + echo '## This feature is disabled by default.' + echo '#LIMIT=0' + exit 0 +} + +function usage_msg +{ + stderr "Usage: msmtpq [sendmail options]" + stderr + stderr " or msmtpq --q-mgmt [ ...]" + stderr " or msmtp-queue [ ...]" + stderr + stderr " or msmtpq --daemon [-h]" + stderr " or msmtp-daemon [-h]" + stderr + stderr "Yet Another Queue Implementation for MSMTP" + stderr + stderr "Sendmail mode:" + stderr + stderr " Just send your mail content to STDIN. Your message will be added to the queue." + stderr " Don't forget to setup a queue-run cronjob! Otherwise it'll be held forever in queue." + stderr + stderr "Daemon mode:" + stderr + stderr " Runs the mail queue every 90 seconds and when new messages are queued." + stderr " Alternatively use a regular cronjob or Systemd timer: msmtp-queue -r" + stderr + stderr "Queue management options:" + stderr + stderr " -f flush mail queue (force delivery)" + stderr " -r run mail queue (honor wait times)" + stderr " -R [ ...] send selected mail(s) from queue" + stderr " -H [ ...] hold selected mail(s) in queue (do not deliver)" + stderr " -U [ ...] release selected mail(s) from hold (deliver again)" + stderr " -p [ ...] purge selected mail(s) from queue" + stderr " -a purge all mails from queue" + stderr " -n hold all mails at queue" + stderr " -N unhold all mails at queue" + stderr " -d display mails in queue" + stderr " -e show example config" + stderr " -h show help message" + exit 0 +} + # Trap callback. # shellcheck disable=SC2317 function cleanup @@ -697,102 +798,11 @@ then ;; e) - echo '############################################################' - echo '# msmtp-yaqi example configuration file: ~/.msmtpq.conf #' - echo '# Looks like Bash but it is a simple plaintext format! #' - echo '############################################################' - echo - echo '## Path to msmtp binary' - echo '#MSMTP=msmtp' - echo - echo '## Path to queue directory. Relative to $''HOME path!' - echo '## mkdir -v ~/.msmtpq && chmod -c 0700 ~/.msmtpq' - echo '#QUEUE=.msmtpq' - echo - echo '## Path to logfile.' - echo '## Relative to $''HOME!' - echo '## Disabled by default.' - echo '#LOGFILE=' - echo - echo '## Prefixed timestamp format for logfile.' - echo '#LOGFILE_TIME_FORMAT=%Y-%m-%d %H:%M:%S' - echo - echo '## Log to syslog?' - echo '## Facility mail.*' - echo '#SYSLOG=off' - echo - echo '## Output log messages to STDERR too?' - echo '## Facility: mail.{debug,info,warn,err}' - echo '#QUIET=off' - echo - echo '## Enable all debug messages? (Only for development!)' - echo '## Will be logged to file and syslog too if enabled.' - echo '#DEBUG=off' - echo - echo '## Add additional headers at enqueue and while sending?' - echo '## Contains enqueue timestamp and internal retry counter.' - echo '#HEADER=off' - echo - echo '## Sent mails archive directory.' - echo '## Relative to $''HOME path!' - echo '#ARCHIVE=' - echo - echo '## Wait time after failed delivery tries.' - echo '## Will be doubled after each failed retry!' - echo '## State estimated per message, not globally.' - echo '## Always and only calculated by enqueue time.' - echo '## Time in seconds. Use "0" to disable it.' - echo '#DEFER=300' - echo - echo '## Count message as undeliverable after retries.' - echo '## The message will be deleted from queue and is lost.' - echo '## Use "0" to disable this feature. (Not recommended!)' - echo '## Estimate your best value: $''((2 ** ( - 1) * DEFER))' - echo '#UNDEV=12' - echo - echo '## Maximum elements per run with -r.' - echo '## Works only, when DEFER is enabled.' - echo '## This feature is disabled by default.' - echo '#LIMIT=0' - exit 0 + example_config ;; h) - stderr "Usage: msmtpq [sendmail options]" - stderr - stderr " or msmtpq --q-mgmt [ ...]" - stderr " or msmtp-queue [ ...]" - stderr - stderr " or msmtpq --daemon" - stderr " or msmtp-daemon" - stderr - stderr "Yet Another Queue Implementation for MSMTP" - stderr - stderr "Sendmail mode:" - stderr - stderr " Just send your mail content to STDIN. Your message will be added to the queue." - stderr " Don't forget to setup a queue-run cronjob! Otherwise it'll be held forever in queue." - stderr - stderr "Daemon mode:" - stderr - stderr " Runs the mail queue every 90 seconds and when new messages are queued." - stderr " Alternatively use a regular cronjob or Systemd timer: msmtp-queue -r" - stderr - stderr "Queue management options:" - stderr - stderr " -f flush mail queue (force delivery)" - stderr " -r run mail queue (honor wait times)" - stderr " -R [ ...] send selected mail(s) from queue" - stderr " -H [ ...] hold selected mail(s) in queue (do not deliver)" - stderr " -U [ ...] release selected mail(s) from hold (deliver again)" - stderr " -p [ ...] purge selected mail(s) from queue" - stderr " -a purge all mails from queue" - stderr " -n hold all mails at queue" - stderr " -N unhold all mails at queue" - stderr " -d display mails in queue" - stderr " -e show example config" - stderr " -h show help message" - exit 0 + usage_msg ;; *) @@ -823,7 +833,8 @@ then # daemon mode (inotifywait) elif [[ "$BASECMD" == 'msmtp-daemon' ]] then - [[ -n "$*" ]] && error "Options not supported at daemon mode!" + [[ "${1:-}" == "-h" ]] && usage_msg + [[ -n "$*" ]] && error "Option not supported at daemon mode!" "Try '-h' for more information." command -v inotifywait &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" command -v "${cfg[MSMTP]}" &>/dev/null || error "${cfg[MSMTP]} binary not found! Install it or change MSMTP config variable." inotifywait -q -m -e moved_to --include '^.+-.+-.+,0$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & From d3291d869c0d26ad42c3230496be3a1cbd9e85c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Wed, 17 Apr 2024 11:38:58 +0200 Subject: [PATCH 07/12] ... --- msmtp-yaqi | 58 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/msmtp-yaqi b/msmtp-yaqi index 8b554b5..7c2e09f 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -613,6 +613,8 @@ function hold_mails() function daemon_events { local last=0 + cfg[LIMIT]=0 + while IFS=$'\n' read -r timestamp do [[ "$last" == "$timestamp" ]] && continue @@ -620,9 +622,8 @@ function daemon_events last=$timestamp sleep 1 - lock_queue - run_queue - lock_queue -u + # IMPORTANT: DO NOT REMOVE THIS SUBSHELL! + (lock_queue && run_queue; lock_queue -u) done } @@ -631,9 +632,8 @@ function daemon_fallback BASECMD+=" (fallback)" while true do - lock_queue - run_queue - lock_queue -u + # IMPORTANT: DO NOT REMOVE THIS SUBSHELL! + (lock_queue && run_queue; lock_queue -u) sleep 90 done @@ -695,6 +695,7 @@ function example_config echo '#UNDEV=12' echo echo '## Maximum elements per run with -r.' + echo '## This value is ignored in daemon mode!' echo '## Works only, when DEFER is enabled.' echo '## This feature is disabled by default.' echo '#LIMIT=0' @@ -703,27 +704,31 @@ function example_config function usage_msg { - stderr "Usage: msmtpq [sendmail options]" + stderr "Usage: msmtp-yaqi [sendmail options]" + stderr " or msmtpq [sendmail options]" stderr - stderr " or msmtpq --q-mgmt [ ...]" + stderr " or msmtp-yaqi --q-mgmt [ ...]" stderr " or msmtp-queue [ ...]" stderr - stderr " or msmtpq --daemon [-h]" + stderr " or msmtp-yaqi --daemon [-h]" stderr " or msmtp-daemon [-h]" stderr stderr "Yet Another Queue Implementation for MSMTP" stderr stderr "Sendmail mode:" stderr - stderr " Just send your mail content to STDIN. Your message will be added to the queue." - stderr " Don't forget to setup a queue-run cronjob! Otherwise it'll be held forever in queue." + stderr " Just send your mail content to STDIN. Your message will" + stderr " be added to the queue. Don't forget to setup a queue-run" + stderr " cronjob or start the built-in daemon! Otherwise your" + stderr " messages will be held forever in queue." stderr - stderr "Daemon mode:" + stderr "Daemon mode (--daemon):" stderr - stderr " Runs the mail queue every 90 seconds and when new messages are queued." - stderr " Alternatively use a regular cronjob or Systemd timer: msmtp-queue -r" + stderr " Runs the mail queue every 90 seconds and when new" + stderr " messages are queued. Alternatively use a regular" + stderr " queue-run cronjob: msmtp-yaqi --q-mgmt -r" stderr - stderr "Queue management options:" + stderr "Queue management options (--q-mgmt):" stderr stderr " -f flush mail queue (force delivery)" stderr " -r run mail queue (honor wait times)" @@ -771,14 +776,17 @@ read_config ~/.msmtpq.conf # and delete $queue_file trap cleanup EXIT -if [[ "${1:-}" == '--q-mgmt' ]] +if [[ "$BASECMD" != "msmtp-daemon" && "$BASECMD" != "msmtp-queue" ]] then - BASECMD=msmtp-queue - shift -elif [[ "${1:-}" == '--daemon' ]] -then - BASECMD=msmtp-daemon - shift + if [[ "${1:-}" == '--daemon' ]] + then + BASECMD=msmtp-daemon + shift + elif [[ "${1:-}" == '--q-mgmt' ]] + then + BASECMD=msmtp-queue + shift + fi fi # msmtp-queue - queue management mode @@ -830,14 +838,14 @@ then esac lock_queue -u -# daemon mode (inotifywait) +# msmtp-daemon - daemon mode (inotifywait) elif [[ "$BASECMD" == 'msmtp-daemon' ]] then [[ "${1:-}" == "-h" ]] && usage_msg [[ -n "$*" ]] && error "Option not supported at daemon mode!" "Try '-h' for more information." - command -v inotifywait &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" + command -v 'inotifywait' &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" command -v "${cfg[MSMTP]}" &>/dev/null || error "${cfg[MSMTP]} binary not found! Install it or change MSMTP config variable." - inotifywait -q -m -e moved_to --include '^.+-.+-.+,0$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & + inotifywait -q -m -e 'moved_to' --include '^.+-.+-.+,0$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & daemon_fallback exit 1 # sendmail mode From 92b5a58961487932bdf98d6306e91e95b1826628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Wed, 17 Apr 2024 11:40:22 +0200 Subject: [PATCH 08/12] ... --- debian/changelog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 1c6a303..d38f2de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -msmtp-yaqi (0.2.0-1) UNRELEASED; urgency=medium +msmtp-yaqi (0.2.0-1) experimental; urgency=medium * Implement daemon mode. - * Fix various bugs. + * Various small improvements. - -- Christian Schrötter Tue, 16 Apr 2024 21:34:34 +0200 + -- Christian Schrötter Tue, 17 Apr 2024 11:39:37 +0200 msmtp-yaqi (0.1.1-1) experimental; urgency=medium From 606422047840555414a7f07b4cc503a169797193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Wed, 17 Apr 2024 13:04:16 +0200 Subject: [PATCH 09/12] Hotfix for old inotifywait binaries --- debian/changelog | 4 ++-- msmtp-yaqi | 36 ++++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/debian/changelog b/debian/changelog index d38f2de..cfd6505 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -msmtp-yaqi (0.2.0-1) experimental; urgency=medium +msmtp-yaqi (0.2.0-2) experimental; urgency=medium * Implement daemon mode. * Various small improvements. - -- Christian Schrötter Tue, 17 Apr 2024 11:39:37 +0200 + -- Christian Schrötter Tue, 17 Apr 2024 13:03:51 +0200 msmtp-yaqi (0.1.1-1) experimental; urgency=medium diff --git a/msmtp-yaqi b/msmtp-yaqi index 7c2e09f..883935f 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -24,8 +24,7 @@ function stderr # Multi-line version of stderr(). # Adds the program basename as prefix. -# And exits after outputting all lines. -function error +function warning { local var @@ -33,7 +32,14 @@ function error do stderr "$BASECMD: $var" done +} +# Multi-line version of stderr(). +# Adds the program basename as prefix. +# And exits after outputting all lines. +function error +{ + warning "$@" exit 1 } @@ -550,7 +556,7 @@ function lock_queue elif [[ "$1" == '-u' && "${locked:-0}" -eq 1 ]] then - #log -d "Removing lockfile: $lock" + log -d "Removing lock..." rmdir "$lock"; locked=0 fi } @@ -612,28 +618,37 @@ function hold_mails() # inotifywait worker function daemon_events { - local last=0 - cfg[LIMIT]=0 + local -a event + local filename + local timestamp + local last='' - while IFS=$'\n' read -r timestamp + while IFS=$'\n' read -r line do + read -ra event <<< "$line" + timestamp=${event[0]} + filename=${event[1]} + + [[ "$filename" =~ ^.+-.+-.+,0$ ]] || continue [[ "$last" == "$timestamp" ]] && continue - log -d "New event received: $timestamp" + + log -d "New event received: $timestamp ($filename)" last=$timestamp sleep 1 # IMPORTANT: DO NOT REMOVE THIS SUBSHELL! - (lock_queue && run_queue; lock_queue -u) + lock_queue && { (run_queue); lock_queue -u; } done } function daemon_fallback { BASECMD+=" (fallback)" + while true do # IMPORTANT: DO NOT REMOVE THIS SUBSHELL! - (lock_queue && run_queue; lock_queue -u) + lock_queue && { (run_queue); lock_queue -u; } sleep 90 done @@ -843,9 +858,10 @@ elif [[ "$BASECMD" == 'msmtp-daemon' ]] then [[ "${1:-}" == "-h" ]] && usage_msg [[ -n "$*" ]] && error "Option not supported at daemon mode!" "Try '-h' for more information." + [[ "${cfg[LIMIT]}" -ne 0 ]] && { cfg[LIMIT]=0; warning "[WARNING] Configuration variable LIMIT is ignored at daemon mode."; } command -v 'inotifywait' &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" command -v "${cfg[MSMTP]}" &>/dev/null || error "${cfg[MSMTP]} binary not found! Install it or change MSMTP config variable." - inotifywait -q -m -e 'moved_to' --include '^.+-.+-.+,0$' --format '%T' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & + inotifywait -q -m -e 'moved_to' --format '%T %f' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & daemon_fallback exit 1 # sendmail mode From 3bcd9ac50ea6c0d5007ceb3e8b2b3fc22ee0c609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Wed, 17 Apr 2024 13:14:30 +0200 Subject: [PATCH 10/12] ... --- debian/changelog | 4 ++-- msmtp-yaqi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index cfd6505..432a3d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -msmtp-yaqi (0.2.0-2) experimental; urgency=medium +msmtp-yaqi (0.2.0-3) experimental; urgency=medium * Implement daemon mode. * Various small improvements. - -- Christian Schrötter Tue, 17 Apr 2024 13:03:51 +0200 + -- Christian Schrötter Tue, 17 Apr 2024 13:13:51 +0200 msmtp-yaqi (0.1.1-1) experimental; urgency=medium diff --git a/msmtp-yaqi b/msmtp-yaqi index 883935f..dd67913 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -643,7 +643,7 @@ function daemon_events function daemon_fallback { - BASECMD+=" (fallback)" + BASECMD+="-fallback" while true do From 9416c7a6475ac944e8a129367ce1a90cd18a5422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Thu, 18 Apr 2024 01:45:27 +0200 Subject: [PATCH 11/12] ... --- debian/changelog | 4 ++-- msmtp-yaqi | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 432a3d0..60ed541 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -msmtp-yaqi (0.2.0-3) experimental; urgency=medium +msmtp-yaqi (0.2.0-4) experimental; urgency=medium * Implement daemon mode. * Various small improvements. - -- Christian Schrötter Tue, 17 Apr 2024 13:13:51 +0200 + -- Christian Schrötter Tue, 18 Apr 2024 01:25:57 +0200 msmtp-yaqi (0.1.1-1) experimental; urgency=medium diff --git a/msmtp-yaqi b/msmtp-yaqi index dd67913..cc856cf 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -83,7 +83,7 @@ function log for msg in "$@" do # Output message to STDERR (if enabled) - [[ "${cfg[QUIET]}" -eq 0 ]] && stderr "$BASECMD: $msg" + [[ "${cfg[QUIET]}" -eq 0 ]] && warning "$msg" # Send message to syslog (if enabled) [[ "${cfg[SYSLOG]}" -eq 1 ]] && logger -t "${BASECMD}[$$]" -p "$facility" -- "$msg" @@ -615,7 +615,19 @@ function hold_mails() return "$state" } -# inotifywait worker +# Background process for inotifywait +function daemon_worker +{ + while true + do + log -d "Starting inotifywait for queue directory: ${cfg[QUEUE]}" + inotifywait -q -m -e 'moved_to' --format '%T %f' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events + log -w "inotifywait died with status $?! Restarting in 10 seconds..." + sleep 10 + done +} + +# inotifywait event processor function daemon_events { local -a event @@ -641,6 +653,8 @@ function daemon_events done } +# Periodical queue-run at daemon-mode. +# Required for further sending attempts. function daemon_fallback { BASECMD+="-fallback" @@ -861,9 +875,9 @@ then [[ "${cfg[LIMIT]}" -ne 0 ]] && { cfg[LIMIT]=0; warning "[WARNING] Configuration variable LIMIT is ignored at daemon mode."; } command -v 'inotifywait' &>/dev/null || error "inotifywait is required for daemon mode! (Maybe package inotify-tools missing?)" command -v "${cfg[MSMTP]}" &>/dev/null || error "${cfg[MSMTP]} binary not found! Install it or change MSMTP config variable." - inotifywait -q -m -e 'moved_to' --format '%T %f' --timefmt '%s' "${cfg[QUEUE]}" | daemon_events & + daemon_worker & daemon_fallback - exit 1 + ec=1 # sendmail mode else enqueue_mail "$@" From 41eb2268107aa93b07117a3d006a54c8ca6a2bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Schr=C3=B6tter?= Date: Mon, 29 Apr 2024 14:28:30 +0200 Subject: [PATCH 12/12] Rename daemon alias to avoid confusion with msmtpd --- debian/changelog | 4 ++-- debian/control | 5 ++--- debian/postinst | 6 +++--- msmtp-daemon => msmtp-queue-daemon | 0 msmtp-yaqi | 10 +++++----- 5 files changed, 12 insertions(+), 13 deletions(-) rename msmtp-daemon => msmtp-queue-daemon (100%) diff --git a/debian/changelog b/debian/changelog index 60ed541..bf4ef6a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,9 @@ -msmtp-yaqi (0.2.0-4) experimental; urgency=medium +msmtp-yaqi (0.2.0-5) experimental; urgency=medium * Implement daemon mode. * Various small improvements. - -- Christian Schrötter Tue, 18 Apr 2024 01:25:57 +0200 + -- Christian Schrötter Mon, 29 Apr 2024 14:23:51 +0200 msmtp-yaqi (0.1.1-1) experimental; urgency=medium diff --git a/debian/control b/debian/control index f5f85f2..1791eee 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,6 @@ Homepage: https://github.com/froonix/msmtp-yaqi Package: msmtp-yaqi Architecture: all Multi-Arch: foreign -Provides: msmtpq, msmtp-queue, msmtp-daemon -Depends: ${misc:Depends}, ${shlibs:Depends}, msmtp -Recommends: inotify-tools +Provides: msmtpq, msmtp-queue, msmtp-queue-daemon +Depends: ${misc:Depends}, ${shlibs:Depends}, msmtp, inotify-tools Description: Yet Another Queue Implementation for MSMTP diff --git a/debian/postinst b/debian/postinst index 3a85508..937befe 100755 --- a/debian/postinst +++ b/debian/postinst @@ -6,9 +6,9 @@ case "${1}" in ;; configure) - update-alternatives --install /usr/bin/msmtpq msmtpq /usr/bin/msmtp-yaqi 100 - update-alternatives --install /usr/bin/msmtp-queue msmtp-queue /usr/bin/msmtp-yaqi 100 - update-alternatives --install /usr/bin/msmtp-daemon msmtp-daemon /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtpq msmtpq /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtp-queue msmtp-queue /usr/bin/msmtp-yaqi 100 + update-alternatives --install /usr/bin/msmtp-queue-daemon msmtp-queue-daemon /usr/bin/msmtp-yaqi 100 ;; *) diff --git a/msmtp-daemon b/msmtp-queue-daemon similarity index 100% rename from msmtp-daemon rename to msmtp-queue-daemon diff --git a/msmtp-yaqi b/msmtp-yaqi index cc856cf..89ff3b4 100755 --- a/msmtp-yaqi +++ b/msmtp-yaqi @@ -740,7 +740,7 @@ function usage_msg stderr " or msmtp-queue [ ...]" stderr stderr " or msmtp-yaqi --daemon [-h]" - stderr " or msmtp-daemon [-h]" + stderr " or msmtp-queue-daemon [-h]" stderr stderr "Yet Another Queue Implementation for MSMTP" stderr @@ -805,11 +805,11 @@ read_config ~/.msmtpq.conf # and delete $queue_file trap cleanup EXIT -if [[ "$BASECMD" != "msmtp-daemon" && "$BASECMD" != "msmtp-queue" ]] +if [[ "$BASECMD" != "msmtp-queue-daemon" && "$BASECMD" != "msmtp-queue" ]] then if [[ "${1:-}" == '--daemon' ]] then - BASECMD=msmtp-daemon + BASECMD=msmtp-queue-daemon shift elif [[ "${1:-}" == '--q-mgmt' ]] then @@ -867,8 +867,8 @@ then esac lock_queue -u -# msmtp-daemon - daemon mode (inotifywait) -elif [[ "$BASECMD" == 'msmtp-daemon' ]] +# msmtp-queue-daemon - daemon mode (inotifywait) +elif [[ "$BASECMD" == 'msmtp-queue-daemon' ]] then [[ "${1:-}" == "-h" ]] && usage_msg [[ -n "$*" ]] && error "Option not supported at daemon mode!" "Try '-h' for more information."