diff --git a/README.md b/README.md index 3dd3afe..485ce97 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Once everything is setup, you'll use `neomutt` to access your mail. - `mw ls` -- list existing accounts - `mw pass` -- revise an account's password - `mw delete` -- deleted an added account -- `mw purge` -- delete all accounts and settings +- `mw purge` -- delete all accounts and settings (**DANGER**) - `mw cron` -- toggle/configure a cronjob to sync mail ## Dependencies diff --git a/bin/mailsync b/bin/mailsync index 7209447..f9c3610 100755 --- a/bin/mailsync +++ b/bin/mailsync @@ -15,11 +15,7 @@ fi configdir=${XDG_CONFIG_HOME:-$HOME/.config} maildir="${MAILDIR:-$HOME/Mail}" lastrun=${XDG_CACHE_HOME:-$HOME/.cache}/.mailsynclastrun -if [[ -f $configdir/isync/mbsyncrc ]]; then - mbsyncrc="$configdir/isync/mbsyncrc" -else - mbsyncrc="$HOME/.mbsyncrc" -fi +mbsyncrc="$configdir/isync/mbsyncrc" mbsyncbin="$prefix/bin/mbsync -c $mbsyncrc" # Run only if user logged in (prevent cron errors) diff --git a/bin/mw b/bin/mw index ec0b300..942f9e6 100755 --- a/bin/mw +++ b/bin/mw @@ -1,23 +1,23 @@ #!/bin/sh if [ "$#" -gt 1 ]; then - echo "To many arguments. You will be asked." - exit + echo "To many arguments. You will be asked." + exit fi if [ -z "$prefix" ]; then - case "$(uname)" in - Linux) prefix="/usr" ;; - *) prefix="/usr/local" ;; - esac + case "$(uname)" in + Linux) prefix="/usr" ;; + *) prefix="/usr/local" ;; + esac fi command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2" [ -z "$PASSWORD_STORE_DIR" ] && PASSWORD_STORE_DIR="$HOME/.password-store" [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] && - "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || { - printf "\`pass\` must be installed and initialized to encrypt passwords.\\nBe sure it is installed and run \`pass init \`.\\nIf you don't have a GPG public private key pair, run \`$GPG --full-gen-key\` first.\\n" - exit + "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || { + printf "\`pass\` must be installed and initialized to encrypt passwords.\\nBe sure it is installed and run \`pass init \`.\\nIf you don't have a GPG public private key pair, run \`$GPG --full-gen-key\` first.\\n" + exit } ! command -v "$prefix/bin/mbsync" >/dev/null && printf "\`mbsync\` must be installed to run mutt-wizard.\\n" && exit ! command -v "$prefix/bin/msmtp" >/dev/null && printf "\`msmtp\` must be installed.\\n" && exit @@ -27,72 +27,71 @@ mwconfigdir=${XDG_CONFIG_HOME:-$HOME/.config} # Main mutt config location mwmuttdir="$mwconfigdir/mutt" # Directory for account settings -mwaccrcdir="$mwmuttdir/accounts" +mwaccmuttdir="$mwmuttdir/accounts" # Location of mail storage mwmaildir="${MAILDIR:-$HOME/mail}" # Regex to confirm valid email address mwemailre=".\+@.\+\\..\+" mwshare="$prefix/share/mutt-wizard" -if [ -n "$XDG_CONFIG_HOME" ]; then - mwmbsyncrc="$mwconfigdir/isync/mbsyncrc" -else - mwmbsyncrc="$HOME/.mbsyncrc" -fi -mwsharerc="$mwshare/mutt-wizard.muttrc" -mwcachedir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard" mwmuttrc="$mwmuttdir/muttrc" +mwmbsyncrc="$mwconfigdir/isync/mbsyncrc" mwmsmtprc="$mwconfigdir/msmtp/config" +mwsharerc="$mwshare/mutt-wizard.muttrc" +mwcachedir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard" mwssltype="IMAPS" mbsyncbin="$prefix/bin/mbsync -c $mwmbsyncrc" msmtpbin="$prefix/bin/msmtp" -takemwaddr(){ +_mwaddrmwtype(){ mwacc="$mwaddr" # let the user always just deal with his email mwaccmutt="${mwaddr//[.@]/_}" # but mutt would not show it with an @ or . mwacccachedir=$mwcachedir/${mwaddr//[.@]/_} # @ cannot stay because of mutt, . could mwaccmaildir="$mwmaildir/$mwaccmutt" # folder name as shown by mutt and opens with gf in vim + mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwacc.mwonofftype.$mwtype.muttrc" + mwpass=mutt-wizard-$mwaddr + [ -n "$mwidnum" ] && mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwacc.mwonofftype.$mwtype.muttrc" } -for x in "/etc/ssl/certs/ca-certificates.crt" "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/ca-bundle.pem" "/etc/pki/tls/cacert.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/ssl/cert.pem" "/usr/local/share/ca-certificates/" +for mwcrt in "/etc/ssl/certs/ca-certificates.crt" "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/ca-bundle.pem" "/etc/pki/tls/cacert.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/ssl/cert.pem" "/usr/local/share/ca-certificates/" do - [ -f "$x" ] && sslcert="$x" && break + [ -f "$mwcrt" ] && mwsslcert="$mwcrt" && break done || { echo "CA Certificate not found. Please install one or link it to /etc/ssl/certs/ca-certificates.crt" && exit 1 ;} -getaccounts() { - accounts="$(find "$mwaccrcdir" -type f | grep -o "[0-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc//" | sort -n)" +_mwgetaccounts() { + mwaccounts="$(find "$mwaccmuttdir" -type f | grep -o "[1-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc//" | sort -n)" } -mwlist() { - getaccounts && [ -n "$accounts" ] && echo "$accounts" +_mwlist() { + _mwgetaccounts && [ -n "$mwaccounts" ] && echo "${mwaccounts//.mwonofftype./ }" } -mwadd() { - asktype && askinfo && tryconnect && finalize || mwdelete +_mwadd() { + _mwasktype && _mwaskinfo && _mwtryconnect && _mwfinalize || _mwdelete } -getprofiles() { - unset msmtp_header msmtp_profile mutt_profile mbsync_profile +_mwgetprofiles() { + unset mwmsmtpheader mwmsmtpprofile mwmuttprofile mwmbsyncprofile printf "Creating profiles for \`%s\`..." "$mwaddr" -msmtp_header="defaults +mwmsmtpheader="defaults auth on tls on -tls_trust_file $sslcert +tls_trust_file $mwsslcert logfile ${XDG_LOG_HOME:-$HOME}/msmtp.log " -msmtp_profile="account $mwacc +mwmsmtpprofile="account $mwacc host $mwsmtp port $mwsport from $mwaddr user $mwlogin passwordeval \"pass $mwpass\" -$starttlsoff +$mwstarttlsoff " -mbsync_profile="IMAPStore $mwacc-remote +mwmbsyncprofile="IMAPStore $mwacc-remote Host $mwimap Port $mwiport User $mwlogin PassCmd \"pass $mwpass\" SSLType $mwssltype -CertificateFile $sslcert +CertificateFile $mwsslcert MaildirStore $mwacc-local Subfolders Verbatim @@ -112,7 +111,7 @@ MaxMessages 0 " if [ "$mwtype" = "offline" ]; then -mutt_profile="# vim: filetype=neomuttrc +mwmuttprofile="# vim: filetype=neomuttrc # muttrc file for account $mwaddr set realname = \"$mwname\" set from = \"$mwaddr\" @@ -126,7 +125,7 @@ macro index gm \"mailsync $mwacc\" \"sync mail $mwaddr\" unmailboxes * " else -mutt_profile="# vim: filetype=neomuttrc +mwmuttprofile="# vim: filetype=neomuttrc # muttrc file for account $mwaddr set realname = \"$mwname\" set from = \"$mwaddr\" @@ -149,16 +148,16 @@ fi printf "DONE.\\n" } -askinfo() { +_mwaskinfo() { if [ -z "$mwaddr" ]; then - printf "Type the \033[31memail address\033[0m\\n\t\033[36m" - read -r mwaddr - printf "\033[0m" - while ! echo "$mwaddr" | grep "$mwemailre" >/dev/null; do - printf "That is not a valid \033[31memail address\033[0m, please retype\\n\t\033[36m" - read -r mwaddr - printf "\033[0m" - done + printf "Type the \033[31memail address\033[0m\\n\t\033[36m" + read -r mwaddr + printf "\033[0m" + while ! echo "$mwaddr" | grep "$mwemailre" >/dev/null; do + printf "That is not a valid \033[31memail address\033[0m, please retype\\n\t\033[36m" + read -r mwaddr + printf "\033[0m" + done fi mwdomain="$(echo "$mwaddr" | sed "s/.*@//")" printf "\\nSearching for \033[32m%s\033[0m in \033[34m\`domains.csv\`\033[0m..." "$mwdomain" @@ -183,74 +182,92 @@ EOF gmail.com) printf "\033[31mGmail: \"less secure\" must be enabled before you continue.\\nDo it now, if you have not done it already:\\nhttps://support.google.com/accounts/answer/6010255\\n\033[0m" ;; protonmail.ch|protonmail.com|pm.me) printf "\033[31mProtonmail: Users must install and configure Protonmail Bridge for the sync to work:\\nhttps://protonmail.com/bridge/\\n\033[0m" && ssltype="None" ;; esac - [ "$mwsport" = 465 ] && starttlsoff="tls_starttls off" + [ "$mwsport" = 465 ] && mwstarttlsoff="tls_starttls off" fi if [ -z "$mwname" ]; then - printf "Name to associate to email.\\n\t" - read -r mwname + printf "Name to associate to email.\\n\t" + read -r mwname fi - takemwaddr if [ -z "$mwlogin" ]; then - printf "Type your account username if different from your email address.\\n\033[34mFor most accounts you can probably leave this blank.\033[0m\\n\tLogin(?): \033[36m" - read -r mwlogin - printf "\033[0m" - [ -z "$mwlogin" ] && mwlogin="$mwaddr" + printf "Type your account username if different from your email address.\\n\033[34mFor most accounts you can probably leave this blank.\033[0m\\n\tLogin(?): \033[36m" + read -r mwlogin + printf "\033[0m" + [ -z "$mwlogin" ] && mwlogin="$mwaddr" fi # if the user has a pass entry he could provide it via mwpass if [ -z "$mwpass" ]; then - mwpass=mutt-wizard-$mwaddr - getpass + mwpass=mutt-wizard-$mwaddr + _mwgetpass + fi + unset mwidnum + _mwaddrmwtype + _mwgetprofiles + mkdir -p "$mwmuttdir" "$mwaccmuttdir" "${mwmsmtprc%/*}" "${mwmbsyncrc%/*}" + if [ ! -f "$mwmsmtprc" ]; then + echo "$mwmsmtpheader" > "$mwmsmtprc" + else + sed -i "/account $mwacc/,/^\(\s*$\|account\)/d" "$mwmsmtprc" fi - getprofiles - mkdir -p "$mwmuttdir" "$mwaccrcdir" "$mwconfigdir/msmtp" "${mwmbsyncrc%/*}" - [ ! -f "$mwmsmtprc" ] && echo "$msmtp_header" > "$mwmsmtprc" - echo "$msmtp_profile" >> "$mwmsmtprc" + echo "$mwmsmtpprofile" >> "$mwmsmtprc" case "$mwservice" in protonmail.ch|protonmail.com|pm.me) protonfinger || return 1 ;; esac - echo "$mbsync_profile" >> "$mwmbsyncrc" - # new idnum = first one missing - getaccounts - for x in $(seq 1 9); do echo "$accounts" | grep "$x": >/dev/null 2>&1 || { export idnum="$x"; break ;}; done - mwaccrc="$mwaccrcdir/$idnum-$mwacc.muttrc" - echo "$mutt_profile" > "$mwaccrc" + [ -f "$mwmbsyncrc" ] && sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc" + echo "$mwmbsyncprofile" >> "$mwmbsyncrc" + #mwaccmuttrc + mwaccmuttrc="$mwaccmuttdir/$(find "$mwaccmuttdir" -type f | grep -m 1 -o "[1-9]-$mwacc.mwonofftype.$mwtype.muttrc")" + if [[ ! -f "$mwaccmuttrc" ]]; then + # new mwidnum = first one missing + _mwgetaccounts + for mwx in $(seq 1 9); do echo "$mwaccounts" | grep "$mwx:" >/dev/null 2>&1 || { export mwidnum="$mwx"; break ;}; done + mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwacc.mwonofftype.$mwtype.muttrc" + else + mwidnum=${mwaccmuttrc%%-*} + mwidnum=${mwidnum##*/} + fi + echo "$mwmuttprofile" > "$mwaccmuttrc" [ ! -f "$mwmuttrc" ] && echo "# vim: filetype=neomuttrc" > "$mwmuttrc" && echo "muttrc created." - ! grep "source.*mutt-wizard.muttrc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc" + ! grep "source $mwsharerc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc" if [ "$mwtype" = "offline" ]; then - ! grep "^macro .* gM .*" "$mwmuttrc" >/dev/null && echo "macro index gM 'mailsync -Va' \"sync all mail\" # mw-autogenerated" >> "$mwmuttrc" + ! grep "^macro .* gM .*" "$mwmuttrc" >/dev/null && echo "macro index gM 'mailsync -Va' \"sync all mail\" # mw-autogenerated" >> "$mwmuttrc" fi - ! grep "^source.*$mwaccrc" "$mwmuttrc" >/dev/null && echo "source $mwaccrc # mw-autogenerated" >> "$mwmuttrc" + ! grep "^source.*$mwaccmuttrc" "$mwmuttrc" >/dev/null && echo "source $mwaccmuttrc # mw-autogenerated" >> "$mwmuttrc" return 0 } -protonfinger() { +_mwprotonfinger() { printf "Getting Protonmail bridge fingerprint...\\n" - fingerprint="$($msmtpbin --serverinfo --host=127.0.0.1 --port=1025 --tls --tls-certcheck=off)" || return 1 - sed -i "s/account $mwacc/&\ntls_trust_file\ntls_fingerprint $fingerprint/" "$mwmsmtprc" + mwfingerprint="$($msmtpbin --serverinfo --host=127.0.0.1 --port=1025 --tls --tls-certcheck=off)" || return 1 + sed -i "s/account $mwacc/&\ntls_trust_file\ntls_fingerprint $mwfingerprint/" "$mwmsmtprc" } -getpass() { +_mwgetpass() { while : ; do pass rm -f "$mwpass" >/dev/null 2>&1 pass insert "$mwpass" && break; done ;} -formatShortcut() { - while read -r data; do { echo "macro index,pager g$1 \"$data\" \"go to $2\" # mw-autogenerated" - echo "macro index,pager M$1 \"$data\" \"move mail to $2\" # mw-autogenerated" - echo "macro index,pager C$1 \"$data\" \"copy mail to $2\" # mw-autogenerated"; } >> "$mwaccrc" - done -} -tryconnect() { +_mwtryconnect() { + if [ ! -d "$mwaccmaildir" ]; then + mwaccmaildirWasThere="NO" # we need to remove again for "online" + mkdir -p "$mwaccmaildir" + fi if [ -z "$mailboxes" ]; then - if [ ! -d "$mwaccmaildir" ]; then - mwaccmaildirWasThere="NO" # we need to remove again for "online" - mkdir -p "$mwaccmaildir" - fi mailboxes="$($mbsyncbin -l $mwacc | sed 's/\//./')" >/dev/null 2>&1 fi if [ -n "$mailboxes" ]; then + mwspoolfile=$(echo "$mailboxes" | grep -i -m 1 inbox | sed -ne 's/.*/+\0/p') + [ -z "$mwspoolfile" ] && return 1 + + #make directories printf "\033[32mMailboxes detected.\033[0m\\n" - echo "$mailboxes" | xargs -I {} mkdir -p "$mwaccmaildir/{}" + echo "$mailboxes" | xargs -I {} mkdir -p "$mwaccmaildir/{}/"{cur,new,tmp} + record=$(echo "$mailboxes" | grep -i -m 1 sent | sed -ne 's/.*/+\0/p') + [ -z "$mwrecord" ] && mkdir -p "$mwaccmaildir/Sent/"{cur,new,tmp} && record="Sent" + postponed=$(echo "$mailboxes" | grep -i -m 1 draft | sed -ne 's/.*/+\0/p') + [ -z "$mwpostponed" ] && mkdir -p "$mwaccmaildir/Drafts/"{cur,new,tmp} && postponed="Drafts" + trash=$(echo "$mailboxes" | grep -i -m 1 trash | sed -ne 's/.*/+\0/p') + [ -z "$mwtrash" ] && mkdir -p "$mwaccmaildir/Trash/"{cur,new,tmp} && trash="Trash" + return 0 else printf "\033[31m\033[31mLog-on not successful.\033[0m\\nIt seems that either you inputted the wrong password or server settings, or there are other requirements for your account out of the control of mutt-wizard.\\n" @@ -258,125 +275,128 @@ tryconnect() { fi } -finalize() { - sed -i "/# mw-autogenerated/d" "$mwaccrc" - sed -i "/^mailboxes\|^set record\|^set postponed\|^set trash\|^set spoolfile/d" "$mwaccrc" - idnum=${mwaccrc%%-*} - idnum=${idnum##*/} - muttsync=$(printf 'source %s!;' $mwaccrc) - echo "macro index,pager i$idnum '$muttsync' \"switch to $mwaddr\" # mw-autogenerated" >> "$mwaccrc" - command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" > "$HOME/.urlview" - - echo "folder-hook \$folder '$muttsync' # mw-autogenerated" >> "$mwaccrc" - boxes="$(find "$mwaccmaildir/" -mindepth 1 -maxdepth 1 | sed "s/\ /\\\ /g;s/^.*\//=/")" - if [ "$boxes" = "" ]; then + +_mwfinalize() { # new mwaccmuttrc + mwboxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")" + if [[ "$mwboxes" =~ ^[[:space:]]*$ ]]; then printf "\033[31mNo local mailboxes have been detected for %s.\033[0m\\nThis means that mbsync has not been successfully run.\\nRun mbsync, and if it has an error, be sure to check your password and server settings manually if needbe.\\n" "$mwacc" return fi - printf "Setting default mailboxes for your Inbox, Sent, Drafts and Trash in mutt...\\n" - spoolfile=$(echo "$boxes" | grep -i -m 1 inbox | sed 's/=/+/g') - record=$(echo "$boxes" | grep -i -m 1 sent | sed 's/=/+/g') - postponed=$(echo "$boxes" | grep -i -m 1 draft | sed 's/=/+/g') - trash=$(echo "$boxes" | grep -i -m 1 trash | sed 's/=/+/g') - cat >> "$mwaccrc" <source %s!;' $mwaccmuttrc) + cat >> "$mwaccmuttrc" <> "$mwaccrc" - printf "Setting up your keyboard shortcuts for jumping between mailboxes...\\n" - echo "$boxes" | grep -i inbox | head -n 1 | formatShortcut i inbox - echo "$boxes" | grep -i sent | head -n 1 | formatShortcut s sent - echo "$boxes" | grep -i draft | head -n 1 | formatShortcut d drafts - echo "$boxes" | grep -i trash | head -n 1 | formatShortcut t trash - echo "$boxes" | grep -i spam | head -n 1 | formatShortcut S spam - echo "$boxes" | grep -i junk | head -n 1 | formatShortcut j junk - echo "$boxes" | grep -i archive | head -n 1 | formatShortcut a archive + for mwabox in $mwboxes; do + mwbox=${mwabox##*/} + mwbox=${mwbox##*.} + mwboxi=${mwbox::2} + mwboxi=${mwboxi,,} + cat >> $mwaccmuttrc <=$mwabox" "go to $mwbox" +macro index,pager M$mwboxi "=$mwabox" "move mail to $mwbox" +macro index,pager C$mwboxi "=$mwabox" "copy mail to $mwbox" +EOF + done if [ "$mwtype" = "offline" ]; then - notmuchauto + _mwnotmuchauto printf "All done.\\n\033[33mYou can now run \`\033[32mmailsync [%s]\033[33m\` to sync your mail.\033[0m\\n" "$mwacc" else mkdir -p "$mwacccachedir" sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc" - [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir/" + [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir" fi return 0 } -confirm() { - printf "[y/N]: Do you want to %s?\\n\t" "$@" && read -r input && ! echo "$input" | grep -i "^y$\|^yes$" >/dev/null && printf "That doesn't seem like a yes to me.\\n\\n" && return 1 +_mwconfirm() { + printf "[y/N]: Do you want to %s?\\n\t" "$@" && read -r mwinput && ! echo "$mwinput" | grep -i "^y$\|^yes$" >/dev/null && printf "That doesn't seem like a yes to me.\\n\\n" && return 1 return 0 ; } -mwpick() { +_mwpick() { printf "Select an accounts to %s:\\n" "$1" - mwlist - read -r input - [ -z "$input" ] && return 1 - mwaddr="$(echo "$accounts" | grep "$input": | awk '{print $2}')" - takemwaddr + _mwlist + [ -z "$mwpick" ] && read -r mwpick + mwidnum="$mwpick" + [ -z "$mwidnum" ] && return 1 + mwaddr="$(echo "$mwaccounts" | grep "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $2}')" + mwtype="$(echo "$mwaccounts" | grep "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $3}')" + _mwaddrmwtype [ -z "$mwacc" ] && printf "Invalid response." && return 1 return 0 ; } -mwdelete() { - sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc" - rm -rf "$mwacccachedir" - rm -rf "$mwaccrcdir/"[1-9]"-$mwacc.muttrc" - sed -i "/[0-9]-$mwacc.muttrc/d" "$mwmuttrc" - sed -i "/account $mwacc/,/^\(\s*$\|account\)/d" "$mwmsmtprc" +_mwdelete() { + rm -f "$mwaccmuttrc" + sed -i "/$mwaccmuttrc/d" "$mwmuttrc" + if [ "$mwtype" = "offline" ]; then + sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc" + sed -i "/account $mwacc/,/^\(\s*$\|account\)/d" "$mwmsmtprc" + else + rm -rf "$mwacccachedir" + fi } -mwcron() { +_mwcron() { ! pgrep cron >/dev/null && echo "No cron manager running. Install/enable one and then select this option again." && return 1 if crontab -l | grep mailsync >/dev/null; then echo "Active mail sync cronjob detected. Do you want to remove it?" printf "\033[36m\t" - read -r rmyn + [ -z "$mwcronremove" ] && read -r mwcronremove printf "\033[0m" - echo "$rmyn" | grep -i "^y\(es\)*$" >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null && echo "Mail sync turned off." + echo "$mwcronremove" | grep -i "^y\(es\)*$" >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null && echo "Mail sync turned off." else echo "How many minutes between each mail sync?" printf "\033[36m\t" - read -r minnum + [ -z $mwcronminutes ] && read -r mwcronminutes printf "\033[0m" - while ! echo "$minnum" | grep "^[0-9]\+$" >/dev/null; do + while ! echo "$mwcronminutes" | grep "^[1-9]\+$" >/dev/null; do printf "That doesn't look like a number. How many minutes between each mail sync?\\n\033[36m\t" - read -r minnum + read -r mwcronminutes printf "\033[0m" done - (crontab -l; echo "*/$minnum * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; export DISPLAY=:0; $(type mailsync | cut -d' ' -f3)") | crontab - && - echo "Cronjob added. Mail will sync every $minnum minutes. Be sure you have your cron manager running." + (crontab -l; echo "*/$mwcronminutes * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; export DISPLAY=:0; $(type mailsync | cut -d' ' -f3)") | crontab - && + echo "Cronjob added. Mail will sync every $mwcronminutes minutes. Be sure you have your cron manager running." fi } -asktype() { - if [ -z "$mwtype" ]; then - while : ; do - printf "[yes/no]: Local mail via mbsync? No: Mutt remotes (slower)\\n\t" - read -r offnot - case "$offnot" in - [Yy][Ee][Ss]) mwtype="offline" && break ;; - [Nn][Oo]) mwtype="online" && break ;; - *) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;; - esac - done - fi +_mwasktype() { + if [ -z "$mwtype" ]; then + while : ; do + printf "[yes/no]: Local mail via mbsync? No: Mutt remotes (slower)\\n\t" + read -r mwoffline + case "$mwoffline" in + [Yy][Ee][Ss]) mwtype="offline" && break ;; + [Nn][Oo]) mwtype="online" && break ;; + *) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;; + esac + done + fi } -mwpurge() { - confirm "delete all account data" || exit - rm -rf "$mwmbsyncrc" "$mwaccrcdir" "$mwconfigdir/msmtp" "${mwmbsyncrc%/*}" "$mwcachedir" - pgrep cron >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null +_mwpurge() { + _mwconfirm "delete all account data" || exit + rm -rf "$mwaccmuttdir" "${mwmsmtprc%/*}" "${mwmbsyncrc%/*}" "$mwcachedir" sed -i "/\# mw-autogenerated/d" "$mwmuttrc" + pgrep cron >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null echo "All configs and account settings have been purged." } -notmuchauto() { +_mwnotmuchauto() { [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config" [ -f "$NOTMUCH_CONFIG" ] && return 0 - nmbasic="[database] + mwnmbasic="[database] path=$mwmaildir [user] name=$mwname @@ -391,19 +411,19 @@ synchronize_flags=true [crypto] gpg_path=$GPG" mkdir -p "${NOTMUCH_CONFIG%/*}" - echo "$nmbasic" > "$NOTMUCH_CONFIG" + echo "$mwnmbasic" > "$NOTMUCH_CONFIG" } trap 'echo -e "\033[0m\n"; exit' STOP INT ABRT KILL if [ "${BASH_SOURCE[0]}" = "${0}" ]; then case "$1" in - ls) mwlist ;; - add) mwadd ;; - pass) mwpick "change the password of" && getpass ;; - delete) mwpick delete && confirm "delete the \`$mwacc\` profile" && mwdelete ;; - purge) mwpurge ;; - cron) mwcron ;; + ls) _mwlist ;; + add) _mwadd ;; + pass) _mwpick "change the password of" && _mwgetpass ;; + delete) _mwpick delete && _mwconfirm "delete the \`$mwacc\` profile" && _mwdelete ;; + purge) _mwpurge ;; + cron) _mwcron ;; *) cat << EOF mw: mutt-wizard, auto-configure email accounts for mutt including downloadable mail with \`isync\`. diff --git a/mw.1 b/mw.1 index 5508d93..08e5a24 100644 --- a/mw.1 +++ b/mw.1 @@ -26,12 +26,18 @@ list all email accounts configured by mutt-wizard delete the configuration files for an already configured email account .TP .B purge -totally purge all local mutt-wizard/mbync/msmtp settings +.I totally +purges all local +.I .config/mutt/accounts/1-* +.I mbsyncrc +and +.I .config/msmtp/config +settings. .TP .B cron -toggle a cronjob that will automatically sync mail with -.B mailsync -as often as you wish +toggle a cronjob that will periodically sync mail with +.B mailsync. +Use mailsync instead of mbsync, also manually. .SH DETAILS .TP .B Mail location @@ -65,14 +71,11 @@ will delete downloaded mail for for safety (and time)'s sake. If you want to del mutt-wizard has many default settings that focus on making it aesthetically pleasing and supplying more vim-like bindings. These can be found in .I /usr/share/mutt-wizard/mutt-wizard.muttrc and the default mailcap file can be found in -.I -/usr/share/mutt-wizard/mailcap. -Any of these settings can be overwritten in +.I /usr/share/mutt-wizard/mailcap. +After the line sourcing the mutt-wizard default, you can overwrite settings in your .I $XDG_CONFIG_HOME/mutt/muttrc, -but be mindful that your overriding binds should appear after the -.I -mutt-wizard.muttrc -file is sourced. +Else you can keep mutt-wizard from adding a sourcing line, if you have the following comment in your muttrc: +.B # source /usr/share/mutt-wizard/mutt-wizard.muttrc .TP .B Detecting server settings mutt-wizard has a repository of email services and their server information kept in diff --git a/test/dotests b/test/dotests index 138ee92..920a39b 100755 --- a/test/dotests +++ b/test/dotests @@ -5,10 +5,6 @@ echo Unit Test: echo bats --tap test_mw.bats -echo -echo Integration tests with a working email: -echo - #modify if [[ -z $MAILDIR ]] || [[ -z $mwaddr ]]; then echo "First do:" @@ -17,6 +13,10 @@ if [[ -z $MAILDIR ]] || [[ -z $mwaddr ]]; then exit fi +echo +echo "Integration tests need working email $mwaddr" +echo "CTRL-C to skip" + cd .. && sudo make install && OK="OK" if [[ "$OK" == "OK" ]]; then @@ -31,25 +31,24 @@ if [[ "$OK" == "OK" ]]; then rm -rf $mwaccmaildir - [ -f "${PASSWORD_STORE_DIR:-~/.password-store}/$mwpass.gpg" ] || pass insert $mwpass - echo "= manual test 1 =" + echo "= Test 1 =" mwtype=online mw add echo "=> In another window, start mutt and verify that mails are shown" echo "=> Then anwer with N" mw purge rm -rf $mwaccmaildir - echo "= manual test 2 =" + echo "= Test 2 =" mwtype=offline mw add mailsync echo "=> In another window, start mutt and verify that mails are shown" echo "=> Press i1, wait, press i2. Verify that mutt is fast again after i2." echo "=> Press gm and gM, to start mailsync." - echo "=> Anwer with y." + echo "=> Anwer with Y and check that mbsyncrc, msmtp/config and mutt/accounts are gone." mw purge - rm -rf $mwaccmaildir + fi cd $CD diff --git a/test/test_mw.bats b/test/test_mw.bats index 3100cb0..cf5b508 100644 --- a/test/test_mw.bats +++ b/test/test_mw.bats @@ -12,9 +12,11 @@ run_only_test() { fi } +#these are called for every test setup() { - #run_only_test 4 + run_only_test 6 + rm -rf mwtesttmp XDG_CONFIG_HOME=mwtesttmp/config \ MAILDIR=mwtesttmp/share/mail \ XDG_CACHE_HOME=mwtesttmp/cache \ @@ -23,11 +25,11 @@ setup() export mwname="real name" export mwaddr="full.addr@gmail.com" export mwlogin="$mwaddr" + export mailboxes="[Gmail]/INBOX" export mwshare=$PWD/../share function pass() { return 0; } export pass } - teardown() { if [ -z "$TEST_FUNCTION" ] @@ -44,12 +46,9 @@ teardown() #2 @test "add online" { - export mwtype=online - rm -rf mwtesttmp - export mailboxes="[Gmail]/Drafts" - run mwadd + mwtype="online" run _mwadd [ -f mwtesttmp/config/mutt/muttrc ] - [ -f mwtesttmp/config/mutt/accounts/1-$mwaddr.muttrc ] + [ -f mwtesttmp/config/mutt/accounts/1-$mwaddr.mwonofftype.online.muttrc ] [ "$(cat mwtesttmp/config/isync/mbsyncrc | sed -ne '/^\s*\w/p')" = "" ] [ ! "$(cat mwtesttmp/config/msmtp/config | sed -ne '/^account/p')" = "" ] [ ! -f mwtesttmp/config/notmuch-config ] @@ -57,12 +56,11 @@ teardown() #3 @test "add offline unsuccessful" { - export mwtype=offline - rm -rf mwtesttmp - run mwadd + export mailboxes="[Gmail]/OTHER" + mwtype="offline" run _mwadd [ -f mwtesttmp/config/mutt/muttrc ] [ -d mwtesttmp/config/mutt/accounts ] - [ ! -f mwtesttmp/config/mutt/accounts/1-$mwaddr.muttrc ] + [ ! -f mwtesttmp/config/mutt/accounts/1-$mwaddr.mwonofftype.offline.muttrc ] [ "$(cat mwtesttmp/config/isync/mbsyncrc | sed -ne '/^\s*\w/p')" = "" ] [ "$(cat mwtesttmp/config/msmtp/config | sed -ne '/^account/p')" = "" ] [ ! -f mwtesttmp/config/notmuch-config ] @@ -70,18 +68,42 @@ teardown() #4 @test "add offline successfully" { - export mwtype=offline - export mailboxes="[Gmail]/Drafts" - rm -rf mwtesttmp - run mwadd + mwtype="offline" run _mwadd [ -f mwtesttmp/config/mutt/muttrc ] [ -d mwtesttmp/config/mutt/accounts ] - [ -f mwtesttmp/config/mutt/accounts/1-$mwaddr.muttrc ] + [ -f mwtesttmp/config/mutt/accounts/1-$mwaddr.mwonofftype.offline.muttrc ] [ -f mwtesttmp/config/notmuch-config ] cat mwtesttmp/config/isync/mbsyncrc | sed -ne '/^\s*\w/p' [ ! "$(cat mwtesttmp/config/isync/mbsyncrc | sed -ne '/^\s*\w/p')" = "" ] [ ! "$(cat mwtesttmp/config/msmtp/config | sed -ne '/^account/p')" = "" ] - run mwlist + run _mwlist [ "$(echo $lines | awk '{print $2}')" = "$mwaddr" ] } +#5 +@test "delete account" { + mwtype="online" run _mwadd + mwtype="offline" run _mwadd + mwpick="1" _mwpick delete && _mwdelete + [ ! -f mwtesttmp/config/mutt/accounts/1-$mwaddr.mwonofftype.online.muttrc ] + [ ! "$(cat mwtesttmp/config/isync/mbsyncrc | sed -ne '/^\s*\w/p')" = "" ] + [ ! "$(cat mwtesttmp/config/msmtp/config | sed -ne '/^account/p')" = "" ] +} + +#6 +@test "cron" { + mwtype="online" run _mwadd + function pgrep() { return 0; } + export pgrep + function crontab() { echo 'none'; } + export crontab + mwcronminutes=99 run _mwcron + chkline="${lines[2]}" + [ "${chkline::14}" = "Cronjob added." ] + function crontab() { echo 'mailsync'; } + export crontab + mwcronremove=y run _mwcron + chkline="${lines[1]}" + [ "${chkline#*turned}" = " off." ] +} +