Skip to content

Instantly share code, notes, and snippets.

@PyroLagus
Forked from eigengrau/mailmon
Created December 22, 2019 19:19
Show Gist options
  • Select an option

  • Save PyroLagus/c91abbc78eaa77445f72940e9ecf8c0f to your computer and use it in GitHub Desktop.

Select an option

Save PyroLagus/c91abbc78eaa77445f72940e9ecf8c0f to your computer and use it in GitHub Desktop.

Revisions

  1. @eigengrau eigengrau created this gist Aug 16, 2018.
    150 changes: 150 additions & 0 deletions mailmon
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,150 @@
    #!/bin/zsh
    #
    # Trigger a command when new mail arrives on the server, using IMAP IDLE. Cf.
    # <http://dwm.suckless.org/scripts/email_notifier_script>.
    #
    # Note that, theoretically, fetchmail can take a comma-separated list of
    # multiple folders, but IDLE will only poll the first one, so if you need to
    # monitor multiple mailboxes, you need to run multiple monitor instances.
    #
    # Passwords are read from the password store keyring by default.
    #
    # Requirements:
    #
    # - fetchmail
    # - docopts
    # - zsh
    #
    #
    # Copyright © 2018 Sebastian Reuße
    #
    # Permission is hereby granted, free of charge, to any person obtaining a copy
    # of this software and associated documentation files (the "Software"), to deal
    # in the Software without restriction, including without limitation the rights
    # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    # copies of the Software, and to permit persons to whom the Software is
    # furnished to do so, subject to the following conditions:
    #
    # The above copyright notice and this permission notice shall be included in all
    # copies or substantial portions of the Software.
    #
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    # SOFTWARE.

    ##############################
    ## Tweakables ##
    ##############################

    get_password() {
    local account=$1
    pass show mail/$account
    }

    notify() {
    local account=$1
    local mail_info=$2
    local mailbox=$3

    local message="$account: new mail ($mail_info)"
    notify-send $message
    xset led named "Scroll Lock"
    mbsync -V $account:$mailbox
    }


    ##############################
    ## Program ##
    ##############################

    setopt \
    nounset \
    pipefail \
    warncreateglobal

    program_name=$(basename $0)
    usage_text="$program_name
    Usage:
    $program_name -a ACCOUNT -r HOSTNAME -l USERNAME [options]
    Options:
    -h, --help Show this help.
    -a, --account ACCOUNT Read password from password store entry mail/ACCOUNT
    -b, --mailbox MAILBOX Monitor this mailbox [default: INBOX]
    -r, --host HOSTNAME Connect to HOST
    -l, --login USERNAME Login as USERNAME
    -p, --port PORT Connect to this port
    -x, --debug Enable debug output
    --caroot PATH Load TLS root certificates from here [default: /etc/ssl/cert.pem]
    --imaps Connect using IMAPS instead of STARTTLS"

    cleanup() {
    local statuscode=$?
    kill -- -$$
    rm -vr $FETCHMAILHOME
    exit $statuscode
    }

    main() {
    unsetopt warncreateglobal
    eval "$(docopts -h $usage_text : $*)"
    setopt warncreateglobal

    if [[ $debug == true ]]; then
    setopt xtrace
    fi

    local port sslopts
    if [[ $imaps == true ]]; then
    port=${port:-993}
    sslopts="ssl sslproto TLS1"
    else
    port=${port:-143}
    sslopts="sslproto TLS1"
    fi

    local password
    get_password $account | read password

    # Generate a fetchmail-config on the fly. This avoids storing the password
    # in the clear, since fetchmail doesn’t offer something like msmtp’s
    # password_cmd.
    local fetchmail_config="
    poll \"$host\" port $port proto IMAP \
    user \"$login\" there with password \"$password\" \
    keep idle $sslopts sslcertck sslcertfile \"$caroot\"
    folder \"$mailbox\""

    # Since IDLE only polls one folder, we will probably want to run multiple
    # instances of this script. However, fetchmail only allows one process at
    # the same time. We can circumvent this by setting FETCHMAILHOME uniquely.
    # Hopefully, this is okay, since we’re using fetchmail in a way that doesn’t
    # touch the remote mail storage. Cf.
    # <http://fnxweb.com/blog/2012/07/14/using-multiple-fetchmail-instances-for-instant-gratification/>
    export FETCHMAILHOME=$(mktemp -d)
    local input mail_info
    fetchmail --check -f - <<<$fetchmail_config \
    | while read input; do
    mail_info=$(
    sed 's/(//' <<<$input \
    | awk '{print $1-$3}'
    )
    if [[ $mail_info != 0 ]]; then
    notify $account $mail_info $mailbox
    fi
    done &

    # Unset sensitive information once fetchmail is running.
    unset fetchmail_config
    unset password

    trap cleanup INT TERM QUIT
    wait
    }

    main $*