c37a748227
If the password contains single quotes and is not surrounded by quotes, Mutt removes the single quotes, rendering an incorrect password.
344 lines
16 KiB
Bash
Executable File
344 lines
16 KiB
Bash
Executable File
#!/bin/sh
|
|
command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
|
|
[ -z ${PASSWORD_STORE_DIR+x} ] && 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 mbsync >/dev/null && printf "\`mbsync\` must be installed to run mutt-wizard.\\n" && exit
|
|
|
|
case "$(uname)" in
|
|
Linux) prefix="/usr" ;;
|
|
*) prefix="/usr/local" ;;
|
|
esac
|
|
|
|
muttdir="$HOME/.config/mutt" # Main mutt config location
|
|
accdir="$muttdir/accounts" # Directory for account settings
|
|
maildir="$HOME/.local/share/mail" # Location of mail storage
|
|
namere="^[a-z_][a-z0-9_-]*$" # Regex to ensure viable username
|
|
emailre=".\+@.\+\\..\+" # Regex to confirm valid email address
|
|
muttshare="$prefix/share/mutt-wizard"
|
|
mbsyncrc="$HOME/.mbsyncrc"
|
|
mwconfig="$muttshare/mutt-wizard.muttrc"
|
|
cachedir="$HOME/.cache/mutt-wizard"
|
|
muttrc="$muttdir/muttrc"
|
|
msmtprc="$HOME/.config/msmtp/config"
|
|
ssltype="IMAPS" # This is later changed to `None` later in the script if using Protonmail
|
|
|
|
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"
|
|
do
|
|
[ -f "$x" ] && sslcert="$x" && 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 "$accdir" -type f | grep -o "[0-9]-.*.muttrc" | sed "s/-/: /;s/\..*//" | sort -n)" ;}
|
|
list() { getaccounts && [ -n "$accounts" ] && echo "$accounts" ;}
|
|
|
|
getprofiles() { \
|
|
unset msmtp_header msmtp_profile mutt_profile mbsync_profile
|
|
printf "Creating profiles for \`%s\`..." "$title"
|
|
msmtp_header="defaults
|
|
auth on
|
|
tls on
|
|
tls_trust_file $sslcert
|
|
logfile ~/.config/msmtp/msmtp.log
|
|
"
|
|
msmtp_profile="account $title
|
|
host $smtp
|
|
port $sport
|
|
from $fulladdr
|
|
user $login
|
|
passwordeval \"pass mutt-wizard-$title\"
|
|
$starttlsoff
|
|
"
|
|
mbsync_profile="IMAPStore $title-remote
|
|
Host $imap
|
|
Port $iport
|
|
User $login
|
|
PassCmd \"pass mutt-wizard-$title\"
|
|
SSLType $ssltype
|
|
CertificateFile $sslcert
|
|
|
|
MaildirStore $title-local
|
|
Subfolders Verbatim
|
|
Path ~/.local/share/mail/$title/
|
|
Inbox ~/.local/share/mail/$title/INBOX
|
|
Flatten .
|
|
|
|
Channel $title
|
|
Expunge Both
|
|
Master :$title-remote:
|
|
Slave :$title-local:
|
|
Patterns * !\"[Gmail]/All Mail\"
|
|
Create Both
|
|
SyncState *
|
|
MaxMessages $maxmes
|
|
# End profile
|
|
"
|
|
|
|
if [ "$accounttype" = "offline" ]; then
|
|
mutt_profile="# vim: filetype=neomuttrc
|
|
# muttrc file for account $title
|
|
set realname = \"$realname\"
|
|
set from = \"$fulladdr\"
|
|
set sendmail = \"msmtp -a $title\"
|
|
alias me $realname <$fulladdr>
|
|
set folder = \"$maildir/$title\"
|
|
set header_cache = $cachedir/$title/headers
|
|
set message_cachedir = $cachedir/$title/bodies
|
|
set mbox_type = Maildir
|
|
|
|
bind index,pager gg noop
|
|
bind index,pager g noop
|
|
bind index,pager M noop
|
|
bind index,pager C noop
|
|
bind index gg first-entry
|
|
macro index o \"<shell-escape>mailsync -V $title<enter>\" \"run mbsync to sync $title\"
|
|
unmailboxes *
|
|
"
|
|
else
|
|
mutt_profile="# vim: filetype=neomuttrc
|
|
# muttrc file for account $title
|
|
set realname = \"$realname\"
|
|
set from = \"$fulladdr\"
|
|
set sendmail = \"$prefix/bin/msmtp -a $title\"
|
|
alias me $realname <$fulladdr>
|
|
set folder = \"imaps://$fulladdr@$imap:$iport\"
|
|
set imap_user = \"$login\"
|
|
set header_cache = $cachedir/$title/headers
|
|
set message_cachedir = $cachedir/$title/bodies
|
|
set imap_pass = \"\`pass mutt-wizard-$title\`\"
|
|
|
|
set mbox_type = Maildir
|
|
set ssl_starttls = yes
|
|
set ssl_force_tls = yes
|
|
|
|
bind index,pager gg noop
|
|
bind index,pager g noop
|
|
bind index,pager M noop
|
|
bind index,pager C noop
|
|
bind index gg first-entry
|
|
unmailboxes *
|
|
"
|
|
fi
|
|
printf "DONE.\\n"
|
|
}
|
|
|
|
askinfo() { \
|
|
printf "Insert the \033[31memail address\033[0m that you want to autoconfigure for mutt/mbsync\\n\tEmail: \033[36m"
|
|
read -r fulladdr
|
|
printf "\033[0m"
|
|
while ! echo "$fulladdr" | grep "$emailre" >/dev/null; do
|
|
printf "That is not a valid \033[31memail address\033[0m, please retype the desired email.\\n\\nEmail: \033[36m\t"
|
|
read -r fulladdr
|
|
printf "\033[0m"
|
|
done
|
|
domain="$(echo "$fulladdr" | sed "s/.*@//")"
|
|
printf "\\nSearching for \033[32m%s\033[0m in \033[34m\`domains.csv\`\033[0m..." "$domain"
|
|
serverinfo="$(grep "^$domain" "$muttshare/domains.csv" 2>/dev/null)"
|
|
if [ -z "$serverinfo" ]; then
|
|
printf "Your email domain is not in mutt-wizard's database yet.\\nmutt-wizard will still autoconfigure everything, but you will have to manually type in your service's IMAP and SMTP server information.\\nYou can usually quickly find this by internet searching for it.\\n"
|
|
printf "Insert the IMAP server for your email provider (excluding the port number)\\n\033[36m\t"
|
|
read -r imap
|
|
printf "\033[0mWhat is your server's IMAP port number? (Usually something like 993)\\n\033[36m\t"
|
|
read -r iport
|
|
printf "\033[0mInsert the SMTP server for your email provider (excluding the port number)\\n\033[36m\t"
|
|
read -r smtp
|
|
printf "\033[0mWhat is your server's SMTP port number? (Usually 587 or 465)\\n\033[36m\t"
|
|
read -r sport
|
|
printf "\033[0m\\nGreat! If you want to be helpful, copy the line below and you can add it to the \`domains.csv\` file on Github.\\nThis will make things easier for others who use your email provider.\\n\\n%s,%s,%s,%s,%s\\n\\nAlthough be sure to test to see if these settings work first! ;-)\\n" "$domain" "$imap" "$iport" "$smtp" "$sport"
|
|
else
|
|
IFS=, read -r service imap iport smtp sport <<EOF
|
|
$serverinfo
|
|
EOF
|
|
printf "\\n\033[3;33mCongrats!\033[0m Server info has automatically been found, so you won't have to look anything 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\\nThis data will be used by the wizard.\\n" "$imap" "$iport" "$smtp" "$sport"
|
|
case "$service" in
|
|
gmail.com) printf "\033[31mREMEMBER: Gmail users must enable \"less secure\" (third-party) applications first for the sync to work:\\nhttps://support.google.com/accounts/answer/6010255\\n\033[0m" ;;
|
|
protonmail.ch|protonmail.com|pm.me) printf "\033[31mREMEMBER: Protonmail users must install and configure Protonmail Bridge first for the sync to work:\\nhttps://protonmail.com/bridge/\\n\033[0m" && ssltype="None" ;;
|
|
esac
|
|
[ "$sport" = 465 ] && starttlsoff="tls_starttls off"
|
|
fi
|
|
printf "Enter the \033[35mfull name\033[0m you want to be identified by on this account.\\n\tReal name: "
|
|
read -r realname
|
|
printf "Enter a short, \033[36mone-word identifier\033[0m for this email account that will distinguish them from any other accounts you add.\\n\tAccount name: "
|
|
read -r title
|
|
while ! echo "$title" | grep "$namere" >/dev/null || ls "$accdir"/[0-9]"-$title.muttrc" >/dev/null 2>&1; do
|
|
printf "\033[31mTry again\033[0m. Pick a nickname that is one word only including lowercase letters and _ or - and that you have \033[1mnot\033[0m used before.\\n\tAccount name: \033[36m\t"
|
|
read -r title
|
|
printf "\033[0m"
|
|
done
|
|
printf "If your account has a special username different from your address, insert it now. Otherwise leave this prompt totally blank.\\n\033[34mMost accounts will not have a separate login, so you should probably leave this blank.\033[0m\\n\tLogin(?): \033[36m"
|
|
read -r login
|
|
printf "\033[0m"
|
|
[ -z "$login" ] && login="$fulladdr"
|
|
[ "$accounttype" = "offline" ] && printf "If you want to limit the number of messages kept offline to a number, enter that number below. If you do not want to limit your mail and would like \`mbsync\` to sync all mail, press enter without typing a number.\\n\t" && read -r maxmes
|
|
echo "$maxmes" | grep "[1-9]" >/dev/null || maxmes="0"
|
|
getpass
|
|
getprofiles
|
|
mkdir -p "$muttdir" "$accdir" "$cachedir/$title/bodies" "$HOME/.config/msmtp"
|
|
getaccounts
|
|
for x in $(seq 1 9); do echo "$accounts" | grep "$x" >/dev/null 2>&1 || { export idnum="$x"; break ;}; done
|
|
[ ! -f "$msmtprc" ] && echo "$msmtp_header" > "$msmtprc"
|
|
echo "$msmtp_profile" >> "$msmtprc"
|
|
command -V apt-get >/dev/null 2>&1 && ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null
|
|
case "$service" in
|
|
protonmail.ch|protonmail.com|pm.me) protonfinger || return 1 ;;
|
|
esac
|
|
echo "$mutt_profile" > "$accdir/$idnum-$title.muttrc"
|
|
echo "$mbsync_profile" >> "$mbsyncrc"
|
|
notmuchauto
|
|
[ ! -f "$muttrc" ] && echo "# vim: filetype=neomuttrc" > "$muttrc" && echo "muttrc created."
|
|
! grep "^source.*mutt-wizard.muttrc" "$muttrc" >/dev/null && echo "source $mwconfig # mw-autogenerated" >> "$muttrc"
|
|
! grep "^source.*.muttrc" "$muttrc" | grep -v "$mwconfig" >/dev/null && echo "source $accdir/$idnum-$title.muttrc # mw-autogenerated" >> "$muttrc"
|
|
echo "macro index,pager i$idnum '<sync-mailbox><enter-command>source $accdir/$idnum-$title.muttrc<enter><change-folder>!<enter>;<check-stats>' \"switch to $fulladdr\" # mw-autogenerated" >> "$muttrc"
|
|
}
|
|
|
|
protonfinger() { printf "Getting Protonmail bridge fingerprint...\\n"
|
|
fingerprint="$(msmtp --serverinfo --tls --tls-certcheck=off -a "$title")" || return 1
|
|
sed -ibu "s/account $title/&\ntls_trust_file\ntls_fingerprint $fingerprint/" "$msmtprc" ; rm -f "$msmtprc"bu
|
|
}
|
|
|
|
getpass() { while : ; do pass rm -f "mutt-wizard-$title" >/dev/null 2>&1
|
|
pass insert "mutt-wizard-$title" && break; done ;}
|
|
|
|
formatShortcut() { \
|
|
while read -r data; do { echo "macro index,pager g$1 \"<change-folder>$data<enter>\" \"go to $2\" # mw-autogenerated"
|
|
echo "macro index,pager M$1 \"<save-message>$data<enter>\" \"move mail to $2\" # mw-autogenerated"
|
|
echo "macro index,pager C$1 \"<copy-message>$data<enter>\" \"copy mail to $2\" # mw-autogenerated"; } >> "$accdir/$idnum-$title.muttrc"
|
|
done ;}
|
|
|
|
tryconnect() { mkdir -p "$maildir/$title"
|
|
if mailboxes="$(mbsync -l "$title" | sed 's/\//./')" >/dev/null 2>&1 && [ -n "$mailboxes" ]; then
|
|
[ "$accounttype" = "online" ] && sed -ibu "/IMAPStore $title-remote$/,/# End profile/d" "$mbsyncrc" ; rm -f "$mbsyncrc"bu
|
|
printf "\033[32mMailboxes detected.\033[0m\\n"
|
|
echo "$mailboxes" | xargs -I {} mkdir -p "$maildir/$title/{}"
|
|
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 ;}
|
|
|
|
finalize() { \
|
|
boxes="$(find "$maildir/$title/" -mindepth 1 -maxdepth 1 | sed "s/\ /\\\ /g;s/^.*\//=/")"
|
|
[ -z "$boxes" ] && 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" "$title" && return
|
|
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')
|
|
sed -ibu "/^mailboxes\|^set record\|^set postponed\|^set trash\|^set spoolfile/d" "$accdir/$idnum-$title.muttrc" ; rm -f "$accdir/$idnum-$title.muttrcbu"
|
|
{ echo "set spoolfile = \"$spoolfile\""; echo "set record = \"$record\""; echo "set postponed = \"$postponed\""; echo "set trash = \"$trash\""; } >> "$accdir/$idnum-$title.muttrc"
|
|
echo "mailboxes =$title ===================== $(echo "$boxes" | sed -e "s/^\|$/\"/g" | tr "\n" " ")" >> "$accdir/$idnum-$title.muttrc"
|
|
printf "Setting up your keyboard shortcuts for jumping between mailboxes...\\n"
|
|
sed -ibu "/# mw-autogenerated/d" "$accdir/$idnum-$title.muttrc" ; rm -f "$accdir/$idnum-$title.muttrcbu"
|
|
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
|
|
[ "$accounttype" = "offline" ] && printf "All done.\\n\033[33mYou should now be able to run \`\033[32mmbsync %s\033[33m\` to begin to download your mail.\033[0m\\n" "$title"
|
|
command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" > "$HOME/.urlview"
|
|
return 0
|
|
}
|
|
|
|
confirm() { printf "Do you want to %s? [y/N]\\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
|
|
printf "Are you really, really sure 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
|
|
return 0 ;}
|
|
|
|
pick() { printf "Select an accounts to %s:\\n" "$1"
|
|
list
|
|
read -r input
|
|
[ -z "$input" ] && return 1
|
|
title="$(echo "$accounts" | grep "$input" | awk '{print $2}')"
|
|
[ -z "$title" ] && printf "Invalid response." && return 1
|
|
return 0 ;}
|
|
|
|
delete() { sed -ibu "/IMAPStore $title-remote$/,/# End profile/d" "$mbsyncrc" ; rm -rf "$mbsyncrc"bu
|
|
rm -rf "${cachedir:?}/${title:?}" "$accdir/"[1-9]"-$title.muttrc"
|
|
sed -ibu "/[0-9]-$title.muttrc/d" "$muttrc" ; rm -f "$muttrc"bu
|
|
sed -ibu "/account $title/,/^\(\s*$\|account\)/d" "$msmtprc"; rm -f "$msmtprc"bu
|
|
}
|
|
|
|
choosecron() { ! 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
|
|
printf "\033[0m"
|
|
echo "$rmyn" | 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
|
|
printf "\033[0m"
|
|
while ! echo "$minnum" | grep "^[0-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
|
|
printf "\033[0m"
|
|
done
|
|
(crontab -l; echo "*/$minnum * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; export DISPLAY=:0; . \$HOME/.profile; $(type mailsync | cut -d' ' -f3)") | crontab - &&
|
|
echo "Cronjob added. Mail will sync every $minnum minutes. Be sure you have your cron manager running."
|
|
fi ;}
|
|
|
|
asktype() { while : ; do
|
|
printf "Do you want to keep your mail for this account offline with mbsync? [yes/no]\\n\t"
|
|
read -r offnot
|
|
case "$offnot" in
|
|
[Yy][Ee][Ss]) accounttype="offline" && break ;;
|
|
[Nn][Oo]) accounttype="online" && break ;;
|
|
*) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;;
|
|
esac; done ;}
|
|
|
|
purge() { confirm "delete all account data" || exit
|
|
rm -rf "$mbsyncrc" "$accdir" "$HOME/.config/msmtp" "$cachedir"
|
|
echo "All configs and account settings have been purged."
|
|
sed -ibu "/\# mw-autogenerated/d" "$muttrc" ; rm -f "$muttrc"bu
|
|
}
|
|
|
|
notmuchauto() { \
|
|
[ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
|
|
[ -f "$NOTMUCH_CONFIG" ] && return 0
|
|
nmbasic="[database]
|
|
path=$maildir
|
|
[user]
|
|
name=$realname
|
|
primary_email=$fulladdr
|
|
[new]
|
|
tags=unread;inbox;
|
|
ignore=
|
|
[search]
|
|
exclude_tags=deleted;spam;
|
|
[maildir]
|
|
synchronize_flags=true
|
|
[crypto]
|
|
gpg_path=$GPG"
|
|
echo "$nmbasic" > "$NOTMUCH_CONFIG" ;}
|
|
|
|
trap 'echo -e "\033[0m\n"; exit' STOP INT ABRT KILL
|
|
|
|
case "$1" in
|
|
ls) list ;;
|
|
add) asktype && askinfo && tryconnect && finalize || delete ;;
|
|
pass) pick "change the password of" && getpass ;;
|
|
delete) pick delete && confirm "delete the \`$title\` profile" && delete ;;
|
|
purge) purge ;;
|
|
cron) choosecron ;;
|
|
*) 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
|
|
\`mbsync -a\` to begin downloading mail.
|
|
EOF
|
|
esac
|