|
- #!/bin/sh
-
- if [ "$#" -gt 1 ]; then
- echo "To many arguments. You will be asked."
- exit
- fi
-
- if [ -z "$prefix" ]; then
- 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 <yourgpgemail>\`.\\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
- ! ( command -v mutt >/dev/null || command -v neomutt >/dev/null ) && printf "\`mutt\` must be installed.\\n" && exit
-
- mwconfigdir=${XDG_CONFIG_HOME:-$HOME/.config}
- # Main mutt config location
- mwmuttdir="$mwconfigdir/mutt"
- # Directory for account settings
- mwaccmuttdir="$mwmuttdir/accounts"
- # Location of mail storage
- mwmaildir="${MAILDIR:-$HOME/mail}"
- # Regex to confirm valid email address
- mwemailre=".\+@.\+\\..\+"
- mwshare="$prefix/share/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"
- _mwaddrmwtype(){
- mwacc="$mwaddr" # let the user always just deal with his email
- mwaccmaildir="$mwmaildir/$mwacc" # mail dir is $MAILDIR/email
- mwacccachedir=$mwcachedir/${mwaddr//[.@]/_} # @ cannot stay because of mutt, . could
- mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwacc.mwonofftype.$mwtype.muttrc"
- mwpass=mutt-wizard-$mwaddr
- [ -n "$mwidnum" ] && mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwacc.mwonofftype.$mwtype.muttrc"
- }
-
- 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 "$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 ;}
-
- _mwgetaccounts() {
- mwaccounts="$(find "$mwaccmuttdir" -type f | grep -o "[1-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc//" | sort -n)"
- }
-
- _mwlist() {
- _mwgetaccounts && [ -n "$mwaccounts" ] && echo "${mwaccounts//.mwonofftype./ }"
- }
-
- _mwadd() {
- _mwasktype && _mwaskinfo && _mwtryconnect && _mwfinalize || _mwdelete
- }
-
- _mwgetprofiles() {
- unset mwmsmtpheader mwmsmtpprofile mwmuttprofile mwmbsyncprofile
- printf "Creating profiles for \`%s\`..." "$mwaddr"
- mwmsmtpheader="defaults
- auth on
- tls on
- tls_trust_file $mwsslcert
- logfile ${XDG_LOG_HOME:-$HOME}/msmtp.log
- "
- mwmsmtpprofile="account $mwacc
- host $mwsmtp
- port $mwsport
- from $mwaddr
- user $mwlogin
- passwordeval \"pass $mwpass\"
- $mwstarttlsoff
- "
- mwmbsyncprofile="IMAPStore $mwacc-remote
- Host $mwimap
- Port $mwiport
- User $mwlogin
- PassCmd \"pass $mwpass\"
- SSLType $mwssltype
- CertificateFile $mwsslcert
-
- MaildirStore $mwacc-local
- Subfolders Verbatim
- Path $mwaccmaildir/
- Inbox $mwaccmaildir/INBOX
- Flatten .
-
- Channel $mwacc
- Expunge Both
- Master :$mwacc-remote:
- Slave :$mwacc-local:
- Patterns * !\"[Gmail]/All Mail\"
- Create Both
- SyncState *
- MaxMessages 0
- # End profile
- "
-
- if [ "$mwtype" = "offline" ]; then
- mwmuttprofile="# vim: filetype=neomuttrc
- # muttrc file for account $mwaddr
- set realname = \"$mwname\"
- set from = \"$mwaddr\"
- set sendmail = \"$msmtpbin -a $mwacc\"
- alias me $mwname <$mwaddr>
- set folder = \"$mwaccmaildir\"
- set mbox_type = Maildir
-
- macro index gm \"<shell-escape>mailsync $mwacc<enter>\" \"sync mail $mwaddr\"
-
- unmailboxes *
- "
- else
- mwmuttprofile="# vim: filetype=neomuttrc
- # muttrc file for account $mwaddr
- set realname = \"$mwname\"
- set from = \"$mwaddr\"
- set sendmail = \"$msmtpbin -a $mwacc\"
- alias me $mwname <$mwaddr>
- set folder = \"imaps://$mwaddr@$mwimap:$mwiport\"
- set header_cache = \"$mwacccachedir\"
- set message_cachedir = \$header_cache
- set imap_user = \"$mwlogin\"
- set imap_pass = \"\`pass $mwpass\`\"
- account-hook \$folder 'set imap_user=\"$mwlogin\" imap_pass=\"\`pass $mwpass\`\"'
-
- set mbox_type = Maildir
- set ssl_starttls = yes
- set ssl_force_tls = yes
-
- unmailboxes *
- "
- fi
- printf "DONE.\\n"
- }
-
- _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
- fi
- mwdomain="$(echo "$mwaddr" | sed "s/.*@//")"
- printf "\\nSearching for \033[32m%s\033[0m in \033[34m\`domains.csv\`\033[0m..." "$mwdomain"
- mwserverinfo="$(grep "^$mwdomain" "$mwshare/domains.csv" 2>/dev/null)"
- if [ -z "$mwserverinfo" ]; then
- printf "Your email domain is not known to mutt-wizard.\\nType in your settings.\\nUsually you find them by an internet search.\\n"
- printf "Type the IMAP server (excluding the port number)\\n\033[36m\t"
- read -r mwimap
- printf "\033[0mIMAP port number (usually 993)\\n\033[36m\t"
- read -r mwiport
- printf "\033[0mSMTP server (excluding the port number)\\n\033[36m\t"
- read -r mwsmtp
- printf "\033[0mSMTP port number (usually 587 or 465)\\n\033[36m\t"
- read -r mwsport
- printf "\033[0m\\nIf you want, you can copy the line below and add it to the \`domains.csv\` file on Github, for others.\\n\\n%s,%s,%s,%s,%s\\n\\nBut be sure the setting works, first! ;-)\\n" "$mwdomain" "$mwimap" "$mwiport" "$mwsmtp" "$mwsport"
- else
- IFS=, read -r mwservice mwimap mwiport mwsmtp mwsport <<EOF
- $mwserverinfo
- EOF
- printf "\\n\033[3;33mCongrats!\033[0m Server info is known, so you don't need to look it up!\\n\t\033[1mIMAP server\033[0m: %s\\n\t\033[1mIMAP port\033[0m: %s\\n\t\033[1mSMTP server\033[0m: %s\\n\t\033[1mSMTP port\033[0m: %s\\n" "$mwimap" "$mwiport" "$mwsmtp" "$mwsport"
- case "$mwservice" in
- 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 ] && mwstarttlsoff="tls_starttls off"
- fi
- if [ -z "$mwname" ]; then
- printf "Name to associate to email.\\n\t"
- read -r mwname
- fi
- 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"
- fi
- # if the user has a pass entry he could provide it via mwpass
- if [ -z "$mwpass" ]; then
- 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
- echo "$mwmsmtpprofile" >> "$mwmsmtprc"
- case "$mwservice" in
- protonmail.ch|protonmail.com|pm.me) protonfinger || return 1 ;;
- esac
- [ -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 $mwsharerc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc"
- if [ "$mwtype" = "offline" ]; then
- ! grep "^macro .* gM .*" "$mwmuttrc" >/dev/null && echo "macro index gM '<shell-escape>mailsync -Va<enter>' \"sync all mail\" # mw-autogenerated" >> "$mwmuttrc"
- fi
- ! grep "^source.*$mwaccmuttrc" "$mwmuttrc" >/dev/null && echo "source $mwaccmuttrc # mw-autogenerated" >> "$mwmuttrc"
- return 0
- }
-
- _mwprotonfinger() {
- printf "Getting Protonmail bridge fingerprint...\\n"
- 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"
- }
-
- _mwgetpass() {
- while : ; do pass rm -f "$mwpass" >/dev/null 2>&1
- pass insert "$mwpass" && break; done ;}
-
-
- _mwtryconnect() {
- if [ ! -d "$mwaccmaildir" ]; then
- mwaccmaildirWasThere="NO" # we need to remove again for "online"
- mkdir -p "$mwaccmaildir"
- fi
- if [ -z "$mailboxes" ]; then
- 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/{}/"{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"
- return 1
- fi
- }
-
-
- _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
- mwaccmutt="${email//[.@]/_}"
- muttsync=$(printf '<sync-mailbox><enter-command>source %s<enter><change-folder>!<enter>;<check-stats>' $mwaccmuttrc)
- cat >> "$mwaccmuttrc" <<EOF
-
- set spoolfile = "$mwspoolfile"
- set record = "$mwrecord"
- set postponed = "$mwpostponed"
- set trash = "$mwtrash"
-
- folder-hook \$folder '$muttsync'
- macro index,pager i$mwidnum '$muttsync' "switch to $mwacc"
-
- mailboxes =$mwaccmutt ===================== $(echo "$mwboxes" | sed -e "s/ //g;s/.*/\"=\0\"/g" | tr "\n" " ")
- EOF
- for mwabox in $mwboxes; do
- mwbox=${mwabox##*/}
- mwbox=${mwbox##*.}
- mwboxi=${mwbox::2}
- mwboxi=${mwboxi,,}
- cat >> $mwaccmuttrc <<EOF
-
- macro index,pager i$mwboxi "<change-folder>=$mwabox<enter>" "go to $mwbox"
- macro index,pager M$mwboxi "<save-message>=$mwabox<enter>" "move mail to $mwbox"
- macro index,pager C$mwboxi "<copy-message>=$mwabox<enter>" "copy mail to $mwbox"
- EOF
- done
- if [ "$mwtype" = "offline" ]; then
- _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"
- fi
- return 0
- }
-
- _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() {
- printf "Select an accounts to %s:\\n" "$1"
- _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() {
- 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() {
- ! 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"
- [ -z "$mwcronremove" ] && read -r mwcronremove
- printf "\033[0m"
- 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"
- [ -z $mwcronminutes ] && read -r mwcronminutes
- printf "\033[0m"
- 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 mwcronminutes
- printf "\033[0m"
- done
- (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
- }
-
- _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() {
- _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."
- }
-
- _mwnotmuchauto() {
- [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
- [ -f "$NOTMUCH_CONFIG" ] && return 0
- mwnmbasic="[database]
- path=$mwmaildir
- [user]
- name=$mwname
- primary_email=$mwaddr
- [new]
- tags=unread;inbox;
- ignore=
- [search]
- exclude_tags=deleted;spam;
- [maildir]
- synchronize_flags=true
- [crypto]
- gpg_path=$GPG"
- mkdir -p "${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" && _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\`.
-
- Allowed options:
- add Add and autoconfigure an email address (9 max.)
- ls List configured accounts
- delete Pick an account to delete
- purge Delete all accounts and settings
- cron Enable or disable an autosync via cronjob
- all else Print this message
-
- NOTE: Once at least one account is added, you can run
- \`mailsync -a\` to begin downloading mail.
- EOF
- esac
- fi
|