From 4183969b68723b373655efc5c490d6faedfaf755 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Wed, 9 Apr 2025 20:46:38 -0400 Subject: [PATCH] Started some much needed updating of the fleacollar code. Likely not usable yet. --- files/add_address.sh | 49 +++++ files/generic.template | 10 + files/gmail.template | 11 + files/gpg-agent.conf | 3 + files/gpg.conf | 12 + files/hotmail.template | 13 ++ files/macros | 7 + files/mailcap | 12 + files/muttrc | 27 +++ fleacollar.sh | 481 ++++++++++++++++------------------------- 10 files changed, 331 insertions(+), 294 deletions(-) create mode 100644 files/add_address.sh create mode 100644 files/generic.template create mode 100644 files/gmail.template create mode 100644 files/gpg-agent.conf create mode 100644 files/gpg.conf create mode 100644 files/hotmail.template create mode 100644 files/macros create mode 100644 files/mailcap create mode 100644 files/muttrc diff --git a/files/add_address.sh b/files/add_address.sh new file mode 100644 index 0000000..8aa7fa3 --- /dev/null +++ b/files/add_address.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +add_email() { + local alias="<${newAlias% *}" + local emailAddress="<${newAlias##*<}" + local ignoreList=( + 'amazon.com' + 'billing@' + 'do-not-reply' + 'donotreply' + 'github.com' + 'gitlab.com' + 'mailto' + 'no-reply' + 'noreply' + 'paypal.com' + 'walmart.com' + ) + # Make the list into a format that works with bash regexp. + ignoreList="${ignoreList[*]}" + ignoreList="${ignoreList// /|}" + # Do not add aliases with no alias-name + if [[ "$alias" == "UNNAMED" ]]; then + return + fi + # Try to filter out addresses that do not receive replies. + if [[ "${emailAddress,,}" =~ ${ignoreList} ]]; then + return + fi + # Do not add the same address twice. + if grep -Fq "$emailAddress" $HOME/.mutt/aliases ; then + return + fi + # Try to not use the same alias-name + if grep -Fq " $alias " $HOME/.mutt/aliases; then + alias="${alias}-${emailAddress#*@}" + alias="${alias%.*}" + fi + if grep -Fq "$alias" $HOME/.mutt/aliases; then + return + fi + echo "$newAlias" >> $HOME/.mutt/aliases + sort -u ~/.mutt/aliases -o ~/.mutt/aliases +} + +message=$(cat) +newAlias=$(echo "${message}" | grep ^"From: " | sed -e s/[\,\"\']//g -e s/'From: '//g | awk -F" " '{if (NF == 1) {print "alias UNNAMED UNNAMED " $0;} else if (NF == 2) {print "alias " $1" " toupper(substr($0,1,1)) tolower(substr($0,2));} else if (NF >= 3) {print "alias ", tolower($1)"-"tolower($(NF-1))" " toupper(substr($0,1,1)) tolower(substr($0,2));}}') +add_email +echo "${message}" diff --git a/files/generic.template b/files/generic.template new file mode 100644 index 0000000..a30b75c --- /dev/null +++ b/files/generic.template @@ -0,0 +1,10 @@ +unset imap_passive +unset record +set smtp_url="smtp://SMTP_USER@SMTP_HOST:SMTP_PORT/ +set folder=imaps://IMAP_USER@IMAP_HOST:IMAP_PORT/ +mailboxes = +INBOX +set spoolfile = +INBOX +set postponed = +Drafts +set imap_keepalive=300 +set mail_check=300 +bind editor complete-query diff --git a/files/gmail.template b/files/gmail.template new file mode 100644 index 0000000..5fde188 --- /dev/null +++ b/files/gmail.template @@ -0,0 +1,11 @@ +unset imap_passive +unset record +set imap_user=EMAIL_ADDRESS +set smtp_url="smtp://USERNAME@smtp.gmail.com:587/ +set folder=imaps://USERNAME@imap.gmail.com/ +set spoolfile = +INBOX +mailboxes = +INBOX +set postponed = +[Gmail]/Drafts +set record=+[Gmail]/Sent +set imap_keepalive=300 +set mail_check=300 diff --git a/files/gpg-agent.conf b/files/gpg-agent.conf new file mode 100644 index 0000000..87abe19 --- /dev/null +++ b/files/gpg-agent.conf @@ -0,0 +1,3 @@ +default-cache-ttl 300 +max-cache-ttl 999999 +allow-loopback-pinentry diff --git a/files/gpg.conf b/files/gpg.conf new file mode 100644 index 0000000..f98456c --- /dev/null +++ b/files/gpg.conf @@ -0,0 +1,12 @@ +charset utf-8 +require-cross-certification +no-escape-from-lines +no-mangle-dos-filenames +personal-digest-preferences SHA512 +cert-digest-algo SHA512 +use-agent +default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed +keyserver wwwkeys.pgp.net +keyserver hkp://pool.sks-keyservers.net +keyserver pgp.zdv.uni-mainz.de +keyserver-options auto-key-retrieve diff --git a/files/hotmail.template b/files/hotmail.template new file mode 100644 index 0000000..2d570e5 --- /dev/null +++ b/files/hotmail.template @@ -0,0 +1,13 @@ +unset imap_passive +unset record +set imap_user=EMAIL_ADDRESS +set smtp_url="smtp://EMAIL_ADDRESS@smtp-mail.outlook.com:587/ +set folder=imaps://EMAIL_ADDRESS@imap-mail.outlook.com/ +set ssl_force_tls=yes +set spoolfile=+Inbox +mailboxes = +Inbox +set postponed=+Drafts +set record=+Sent +set imap_keepalive=300 +set mail_check=300 +bind editor complete-query diff --git a/files/macros b/files/macros new file mode 100644 index 0000000..92abb0a --- /dev/null +++ b/files/macros @@ -0,0 +1,7 @@ +macro index 'c' '?^K=' +bind index "^" imap-fetch-mail" +macro pager \cb 'urlview' 'Follow links with urlview' +macro attach 'B' "cat >~/.cache/mutt/mail.html && $BROWSER ~/.cache/" +macro index,pager b 'source $muttHome/aliases' +macro index,pager f 'source $muttHome/aliases' +macro index,pager m 'source $muttHome/aliases' diff --git a/files/mailcap b/files/mailcap new file mode 100644 index 0000000..4ca2909 --- /dev/null +++ b/files/mailcap @@ -0,0 +1,12 @@ +text/html; w3m -s -o display_link=yes -o display_link_number=yes -o decode_url=yes -dump -T text/html %s -I %{charset};nametemplate=%s.html;copiousoutput +audio/*; mpv --quiet %s; needsterminal +application/msword; soffice --cat %s 2> /dev/null; copiousoutput +application/vnd.openxmlformats-officedocument.wordprocessingml.document; soffice --cat %s 2> /dev/null; copiousoutput +application/vnd.ms-excel; xls2csv %s; copiousoutput +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; xlsx2csv --all %s; copiousoutput +application/rtf; soffice --cat %s 2> /dev/null; copiousoutput +application/vnd.oasis.opendocument.text; soffice --cat %s 2> /dev/null; copiousoutput +application/vnd.oasis.opendocument.spreadsheet;soffice --cat --convert-to csv:"Text - txt - csv (StarCalc)":"59,ANSI,1" %s 2> /dev/null; copiousoutput +application/pdf; pdftotext %s -; copiousoutput +video/*; mpv --quiet %s; test=test -n "$DISPLAY"; needsterminal +video/*; mpv --quiet --no-video %s; needsterminal diff --git a/files/muttrc b/files/muttrc new file mode 100644 index 0000000..0dd6ad8 --- /dev/null +++ b/files/muttrc @@ -0,0 +1,27 @@ +set text_flowed = yes +set index_format = '[%Z] %-20.20F %s (Attached %X, Msg %4C)' +set send_charset = us-ascii:utf-8 +set pager = 'builtin' +set pager_stop = 'yes' +set sort = threads +set beep_new = yes +set display_filter = '$muttHome/scripts/add_address.sh' +set print = yes +set imap_check_subscribed = yes +set sort_alias = alias +set reverse_alias = yes +set alias_file = ${muttHome/#$HOME/\~}/aliases +source ${muttHome/#$HOME/\~}/aliases +set history_file = ${muttHome/#$HOME/\~}/history +set history = 1024 +set mailcap_path = ${muttHome/#$HOME/\~}/mailcap +set header_cache = ${muttHome/#$HOME/\~}/cache/headers +set message_cachedir = ${muttHome/#$HOME/\~}/cache/bodies +set certificate_file = ${muttHome/#$HOME/\~}/certificates +set markers = no +unset mark_old +auto_view text/html +alternative_order text/plain text/enriched text/html +message-hook '!(~g|~G) ~b\"^ 5 dash charactersBEGIN\\ PGP\\ (SIGNED\\ )?MESSAGE\"' "exec check-traditional-pgp" +source ${muttHome/#$HOME/\~}/gpg.rc +source ${muttHome/#$HOME/\~}/macros diff --git a/fleacollar.sh b/fleacollar.sh index 1f638fe..5ad3ee4 100755 --- a/fleacollar.sh +++ b/fleacollar.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script has the lofty goal of becoming a full configuration utility for mutt. # Written by Storm Dragon: https://social.stormdragon.tk/storm @@ -6,32 +6,61 @@ # Contributions by Kyle: https://kyle.tk # Released under the terms of the WTFPL: http://wtfpl.net -# Setup for gettext localization -export TEXTDOMAIN=fleacollar.sh -export TEXTDOMAINDIR=/usr/share/locale -. gettext.sh - # Settings to improve accessibility of dialog. export DIALOGOPTS='--insecure --no-lines --visit-items' # Use the cli entry system for gpg keys. export PINENTRY_USER_DATA="USE_CURSES=1" +# Array of command line arguments +declare -A command=( + [h]="Show this help information." + [t]="Test mode. Use ~/mutt_test instead of ~/.mutt for configuration." +) + # Variables muttHome=~/.mutt +fileDir="$(dirname "$(realpath "$0")")/files" +testMode=false + +# Process command line arguments +# Convert the keys of the associative array to a format usable by getopts +args="${!command[*]}" +args="${args//[[:space:]]/}" +while getopts "${args}" i ; do + case "$i" in + h) help ;; + t) + testMode=true + muttHome=~/mutt_test + ;; + esac +done # Functions +help() { + echo "fleacollar.sh" + echo "Released under the terms of the WTFPL: http://wtfpl.net" + echo -e "A configuration utility for mutt.\n" + echo -e "Usage:\n" + echo "With no arguments, run the configuration utility." + for i in "${!command[@]}" ; do + echo "-${i}: ${command[${i}]}" + done | sort + exit 0 +} + check_dependancies() { local dep - for dep in dialog gettext gpg2 mutt ; do + for dep in dialog gpg2 mutt pass w3m ; do if ! command -v $dep &> /dev/null ; then - echo "$(eval_gettext "\$dep is not installed. Please install $dep and run this script again.")" + echo "$dep is not installed. Please install $dep and run this script again." exit 1 fi done if ! [ -d ~/.gnupg ]; then - read -p "$(eval_gettext "No configuration for GPG was found. To have Fleacollar configure this for you press enter. If you would like to configure GPG manually, press control+c.") " continue + read -p "No configuration for GPG was found. To have Fleacollar configure this for you press enter. If you would like to configure GPG manually, press control+c. " continue configure_gpg fi } @@ -40,7 +69,7 @@ inputbox() { # Returns: text entered by the user # Args 1, Instructions for box. # args: 2 initial text (optional) - dialog --backtitle "$(gettext "Enter text and press enter.")" \ + dialog --backtitle "Enter text and press enter." \ --inputbox "$1" 0 0 "$2" --stdout } @@ -50,9 +79,9 @@ menulist() { local menuList ifs="$IFS" IFS=$'\n' - dialog --backtitle "$(gettext "Use the up and down arrow keys to find the option you want, then press enter to select it.")" \ + dialog --backtitle "Use the up and down arrow keys to find the option you want, then press enter to select it." \ --no-tags \ - --menu "$(gettext "Please select one")" 0 0 0 $@ --stdout + --menu "Please select one" 0 0 0 $@ --stdout IFS="$ifs" } @@ -66,7 +95,7 @@ passwordbox() { # Returns: text entered by the user # Args 1, Instructions for box. # args: 2 initial text (optional) - dialog --backtitle "$(gettext "Enter text and press enter.")" \ + dialog --backtitle "Enter text and press enter." \ --passwordbox "$1" 0 0 "$2" --stdout } @@ -75,8 +104,8 @@ yesno() { # Args: Question to user. # Called in if $(yesno) == "Yes" # Or variable=$(yesno) - dialog --backtitle "$(gettext "Press 'Enter' for \"yes\" or 'Escape' for -\"no\".")" --yesno "$*" 0 0 --stdout + dialog --backtitle "Press 'Enter' for \"yes\" or 'Escape' for +\"no\"." --yesno "$*" 0 0 --stdout if [[ $? -eq 0 ]]; then echo "Yes" else @@ -91,116 +120,19 @@ initialize_directory() if ! [ -f "$muttHome/aliases" ]; then touch "$muttHome/aliases" fi - # Create scripts + + # Copy the add_address.sh script if ! [ -f "$muttHome/scripts/add_address.sh" ]; then - cat << 'EOF' > "$muttHome/scripts/add_address.sh" -#!/bin/bash - -add_email() { - local alias="<${newAlias% *}" - local emailAddress="<${newAlias##*<}" - local ignoreList=( - 'amazon.com' - 'billing@' - 'do-not-reply' - 'donotreply' - 'github.com' - 'gitlab.com' - 'mailto' - 'no-reply' - 'noreply' - 'paypal.com' - 'walmart.com' - ) - # Make the list into a format that works with bash regexp. - ignoreList="${ignoreList[*]}" - ignoreList="${ignoreList// /|}" - # Do not add aliases with no alias-name - if [[ "$alias" == "UNNAMED" ]]; then - return + cp "$fileDir/add_address.sh" "$muttHome/scripts/add_address.sh" + chmod 700 "$muttHome/scripts/add_address.sh" fi - # Try to filter out addresses that do not receive replies. - if [[ "${emailAddress,,}" =~ ${ignoreList} ]]; then - return - fi - # Do not add the same address twice. - if grep -Fq "$emailAddress" $HOME/.mutt/aliases ; then - return - fi - # Try to not use the same alias-name - if grep -Fq " $alias " $HOME/.mutt/aliases; then - alias="${alias}-${emailAddress#*@}" - alias="${alias%.*}" - fi - if grep -Fq "$alias" $HOME/.mutt/aliases; then - return - fi - echo "$newAlias" >> $HOME/.mutt/aliases - sort -u ~/.mutt/aliases -o ~/.mutt/aliases -} - -message=$(cat) -newAlias=$(echo "${message}" | grep ^"From: " | sed -e s/[\,\"\']//g -e s/'From: '//g | awk -F" " '{if (NF == 1) {print "alias UNNAMED UNNAMED " $0;} else if (NF == 2) {print "alias " $1" " toupper(substr($0,1,1)) tolower(substr($0,2));} else if (NF >= 3) {print "alias ", tolower($1)"-"tolower($(NF-1))" " toupper(substr($0,1,1)) tolower(substr($0,2));}}') -add_email -echo "${message}" - -EOF - chmod 700 "$muttHome/scripts/add_address.sh" - fi - # End of add_address script + + # Create mailcap file (now always using w3m) if ! [ -f "$muttHome/mailcap" ]; then - # Find desired browser - local x=0 - for i in\ - $BROWSER\ - chromium\ - elinks\ - epiphany\ - firefox\ - google-chrome\ - links\ - lynx\ - midori\ - seamonkey\ - w3m - do - unset browserPath - browserPath="$(command -v $i)" - if [ -n "$browserPath" ]; then - browsers[$x]="$browserPath" - ((x++)) - fi - done - echo "$(gettext "Select browser for viewing html email:")" - browserPath="$(menulist $(for i in "${browsers[@]##*/}" ; do echo "$i";echo "$i";done))" - if [ -z "$browserPath" ]; then - exit 0 - fi - case "${browserPath##*/}" in - "elinks") - echo "text/html; $browserPath %s; nametemplate=%s.html; needsterminal" > "$muttHome/mailcap" - ;; - "lynx") - echo "text/html; $browserPath -I %{charset} -T text/html %s; nametemplate=%s.html; copiousoutput" > "$muttHome/mailcap" - ;; - "w3m") - echo "text/html; $browserPath -dump -s -o display_link=yes -o display_link_number=yes -o decode_url=yes -I %{charset} -T text/html %s; nametemplate=%s.html; copiousoutput" > "$muttHome/mailcap" - ;; - *) - echo "text/html; $browserPath %s; nametemplate=%s.html; needsterminal" > "$muttHome/mailcap" - esac - echo 'audio/*; mpv --quiet %s; needsterminal' >> "$muttHome/mailcap" - echo 'application/msword; soffice --cat %s 2> /dev/null; copiousoutput' >> "$muttHome/mailcap" - echo 'application/vnd.openxmlformats-officedocument.wordprocessingml.document; soffice --cat %s 2> /dev/null; copiousoutput' >> "$muttHome/mailcap" - echo 'application/vnd.ms-excel; xls2csv %s; copiousoutput' >> "$muttHome/mailcap" - echo 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; xlsx2csv --all %s; copiousoutput' >> "$muttHome/mailcap" - echo 'application/rtf; soffice --cat %s 2> /dev/null; copiousoutput' >> "$muttHome/mailcap" - echo 'application/vnd.oasis.opendocument.text; soffice --cat %s 2> /dev/null; copiousoutput' >> "$muttHome/mailcap" - echo 'application/vnd.oasis.opendocument.spreadsheet;soffice --cat --convert-to csv:"Text - txt - csv (StarCalc)":"59,ANSI,1" %s 2> /dev/null; copiousoutput' >> "$muttHome/mailcap" - echo 'application/pdf; pdftotext %s -; copiousoutput' >> "$muttHome/mailcap" - echo 'video/*; mpv --quiet %s; test=test -n "$DISPLAY"; needsterminal' >> "$muttHome/mailcap" - echo 'video/*; mpv --quiet --no-video %s; needsterminal' >> "$muttHome/mailcap" + cp "$fileDir/mailcap" "$muttHome/mailcap" fi + + # Create gpg.rc file if ! [ -f "$muttHome/gpg.rc" ]; then find /usr -name gpg.rc -exec cp "{}" "$muttHome/" \; 2> /dev/null echo "set pgp_autosign=yes" >> "$muttHome/gpg.rc" @@ -208,13 +140,13 @@ EOF echo "set pgp_replyencrypt=yes" >> "$muttHome/gpg.rc" echo "set pgp_timeout=1800" >> "$muttHome/gpg.rc" if [[ $(gpg --list-secret-keys | wc -l) -eq 0 ]]; then - read -p "$(gettext "No gpg key was found. Type your name and press entr to generate a PGP key.control+c if you would like to create it manually.") " continue + read -p "No gpg key was found. Type your name and press enter to generate a PGP key. Control+c if you would like to create it manually. " continue # Try to use quick key generation, and fall back to the more verbose version for legacy systems. if ! gpg2 --quick-gen-key "${continue:-${USER}}"; then gpg2 --gen-key fi fi - PS3="$(gettext "Select the key you want to use for encryption/signing:")" + PS3="Select the key you want to use for encryption/signing:" select key in $(gpg --list-secret-keys | grep '.*@.*' | cut -d '<' -f2 | cut -d '>' -f1) ; do if [[ -n "$key" ]]; then break @@ -223,31 +155,15 @@ EOF keyName="$(gpg2 --list-secret-keys --keyid-format short | grep -B1 ^uid | head -n1 | rev | cut -c -8 | rev)" echo "set pgp_sign_as=$keyName" >> "$muttHome/gpg.rc" fi + # Create or update macro file - echo "macro index 'c' '?^K='" >> "$muttHome/macros" - echo "bind index \"^\" imap-fetch-mail\"" >> "$muttHome/macros" - echo "macro pager \cb 'urlview' 'Follow links with urlview'" >> "$muttHome/macros" - echo "macro attach 'B' \"cat >~/.cache/mutt/mail.html && $BROWSER ~/.cache/\"" >> "$muttHome/macros" - echo "macro index,pager b 'source $muttHome/aliases'" >> "$muttHome/macros" - echo "macro index,pager f 'source $muttHome/aliases'" >> "$muttHome/macros" - echo "macro index,pager m 'source $muttHome/aliases'" >> "$muttHome/macros" - + cp "$fileDir/macros" "$muttHome/macros" + # Create basic muttrc if ! [ -f "$muttHome/muttrc" ]; then # Find desired editor x=0 - for i in\ - emacs\ - geany\ - gedit\ - leafpad\ - mousepad\ - nano\ - ne\ - pluma\ - vi\ - vim - do + for i in nano vim ; do unset editorPath editorPath="$(command -v $i)" if [ -n "$editorPath" ]; then @@ -255,47 +171,23 @@ EOF ((x++)) fi done - echo "$gettext "Select editor for email composition:")" + echo "Select editor for email composition:" i="$(menulist ${EDITOR} ${EDITOR} $(for i in "${editors[@]##*/}" ; do echo "$i";echo "$i";done))" if [ -z "$i" ]; then exit 0 fi - # Try to handle special cases like with ne and nano skipping headers and line wrapping. + + # Copy base muttrc + cp "$fileDir/muttrc" "$muttHome/muttrc" + + # Set editor in muttrc case "$i" in - "nano") echo "set editor = '$i +7 -r 72'" > "$muttHome/muttrc";; - "ne") echo "set editor = '$i +7'" > "$muttHome/muttrc";; - "vim") echo "set editor = \"vim -c 'set spell spelllang=${LANG::2}'\"" > "$muttHome/muttrc";; - *) echo "set editor = '$i'" > "$muttHome/muttrc";; + "nano") sed -i "1s|^|set editor = '$i +7 -r 72'\n|" "$muttHome/muttrc" ;; + "vim") sed -i "1s|^|set editor = \"vim -c 'set spell spelllang=${LANG::2}'\"\n|" "$muttHome/muttrc" ;; esac - echo "set text_flowed = yes" >> "$muttHome/muttrc" - # Move the messge index number to the right edge. - echo "set index_format = '[%Z] %-20.20F %s (Attached %X, Msg %4C)'" >> "$muttHome/muttrc" - # I need to figure out a way to detect and set the language for the next setting. - echo "set send_charset = us-ascii:utf-8" >> "$muttHome/muttrc" - echo "set pager = 'builtin'" >> "$muttHome/muttrc" - echo "set pager_stop = 'yes'" >> "$muttHome/muttrc" - echo "set sort = threads" >> "$muttHome/muttrc" - echo "set beep_new = yes" >> "$muttHome/muttrc" - echo "set display_filter = '$muttHome/scripts/add_address.sh'" >> "$muttHome/muttrc" - echo "set print = yes" >> "$muttHome/muttrc" - echo "set imap_check_subscribed = yes" >> "$muttHome/muttrc" - echo "set sort_alias = alias" >> "$muttHome/muttrc" - echo "set reverse_alias = yes" >> "$muttHome/muttrc" - echo "set alias_file = ${muttHome/#$HOME/\~}/aliases" >> "$muttHome/muttrc" - echo "source ${muttHome/#$HOME/\~}/aliases" >> "$muttHome/muttrc" - echo "set history_file = ${muttHome/#$HOME/\~}/history" >> "$muttHome/muttrc" - echo "set history = 1024" >> "$muttHome/muttrc" - echo "set mailcap_path = ${muttHome/#$HOME/\~}/mailcap" >> "$muttHome/muttrc" - echo "set header_cache = ${muttHome/#$HOME/\~}/cache/headers" >> "$muttHome/muttrc" - echo "set message_cachedir = ${muttHome/#$HOME/\~}/cache/bodies" >> "$muttHome/muttrc" - echo "set certificate_file = ${muttHome/#$HOME/\~}/certificates" >> "$muttHome/muttrc" - echo "set markers = no" >> "$muttHome/muttrc" - echo "unset mark_old" >> "$muttHome/muttrc" - echo "auto_view text/html" >> "$muttHome/muttrc" - echo "alternative_order text/plain text/enriched text/html" >> "$muttHome/muttrc" - echo "message-hook '!(~g|~G) ~b\"^ 5 dash charactersBEGIN\\ PGP\\ (SIGNED\\ )?MESSAGE\"' \"exec check-traditional-pgp\"" >> "$muttHome/muttrc" - echo "source ${muttHome/#$HOME/\~}/gpg.rc" >> "$muttHome/muttrc" - echo "source ${muttHome/#$HOME/\~}/macros" >> "$muttHome/muttrc" + + # Replace muttHome in muttrc + sed -i "s|\$muttHome|${muttHome/#$HOME/\~}|g" "$muttHome/muttrc" fi } @@ -305,55 +197,44 @@ configure_gpg() if ! grep 'GPG_TTY=$(tty)' ~/.bashrc ; then echo -e 'GPG_TTY=$(tty)\nexport GPG_TTY' >> ~/.bashrc fi + # Make sure the configuration directory exists -if ! [ -d ~/.gnupg/ ]; then + if ! [ -d ~/.gnupg/ ]; then gpg2 --list-secret-keys &> /dev/null fi + if [ -f ~/.gnupg/gpg.conf ]; then - read -p "$(gettext "This will overwrite your existing ~/.gnupg/gpg.conf file. Press enter to continue or control+c to abort. ")" continue + read -p "This will overwrite your existing ~/.gnupg/gpg.conf file. Press enter to continue or control+c to abort. " continue fi - cat << EOF > ~/.gnupg/gpg.conf -charset utf-8 -require-cross-certification -no-escape-from-lines -no-mangle-dos-filenames -personal-digest-preferences SHA512 -cert-digest-algo SHA512 -use-agent -default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed -keyserver wwwkeys.pgp.net -keyserver hkp://pool.sks-keyservers.net -keyserver pgp.zdv.uni-mainz.de -keyserver-options auto-key-retrieve -EOF + + # Copy GPG configuration files + cp "$fileDir/gpg.conf" ~/.gnupg/gpg.conf + if [ -f ~/.gnupg/gpg-agent.conf ]; then - read -p "$(gettext "This will overwrite your existing ~/.gnupg/gpg-agent.conf file. Press enter to continue or control+c to abort. ")" continue + read -p "This will overwrite your existing ~/.gnupg/gpg-agent.conf file. Press enter to continue or control+c to abort. " continue fi - cat << EOF > ~/.gnupg/gpg-agent.conf -default-cache-ttl 300 -max-cache-ttl 999999 -allow-loopback-pinentry -EOF + + cp "$fileDir/gpg-agent.conf" ~/.gnupg/gpg-agent.conf } add_email_address() { - read -p "$(gettext "Please enter your email address: ")" emailAddress + read -p "Please enter your email address: " emailAddress if ! [[ "$emailAddress" =~ .*@.*\..* ]]; then - read -p "$(gettext "this appears to be an invalid email address. Continue anyway? (y/n) ")" continue + read -p "This appears to be an invalid email address. Continue anyway? (y/n) " continue if [ "${continue^}" != "Y" ]; then exit 0 fi fi if [ -f "$muttHome/$emailAddress" ]; then - read -p "$(gettext "This email address already exists. Overwrite the existing settings? (y/n) ")" continue + read -p "This email address already exists. Overwrite the existing settings? (y/n) " continue if [ "${continue^}" != "Y" ]; then exit 0 else sed -i "/$emailAddress/d" "$muttHome/muttrc" fi fi - read -p "$(gettext "Enter your name as you want it to appear in emails. From: ")" realName + read -p "Enter your name as you want it to appear in emails. From: " realName echo "set realname=\"$realName\"" > "$muttHome/$emailAddress" echo "set from=\"$emailAddress\"" >> "$muttHome/$emailAddress" echo "set use_from = \"yes\"" >> "$muttHome/$emailAddress" @@ -366,60 +247,60 @@ add_email_address() configure_hotmail "$emailAddress" ;; *) - continue="$(yesno "$(gettext "Is this a gmail account?")")" + continue="$(yesno "Is this a gmail account?")" if [[ "$continue" == "Yes" ]]; then configure_gmail "$emailAddress" else configure_generic "$emailAddress" fi esac - # Password encryption with gpg + + # Password storage with pass passOne=a passTwo=b until [ "$passOne" = "$passTwo" ]; do - passOne="$(passwordbox "$(gettext "Please enter the password for $emailAddress:")")" - passTwo="$(passwordbox "$(gettext "Please enter the password again: ")")" + passOne="$(passwordbox "Please enter the password for $emailAddress:")" + passTwo="$(passwordbox "Please enter the password again: ")" if [ "$passOne" != "$passTwo" ]; then - echo "$(gettext "The passwords do not match.")" + echo "The passwords do not match." fi done - keyName="$(gpg2 --list-secret-keys --keyid-format short | grep -B1 ^uid | head -n1 | rev | cut -c -8 | rev)" - # I wish it were possible to just echo the password through gpg and not have an unencrypted file at all. - # but either it's not, or I just can't figure out how to do it. So we'll use mktemp and shred. - passwordFile="$(mktemp)" - echo -e "set imap_pass=\"$passOne\"\nset smtp_pass=\"$passOne\"" > "$passwordFile" - gpg2 -r $keyName -e "$passwordFile" - mv "$passwordFile.gpg" "$muttHome/$emailAddress.gpg" - shred -fuzn 10 "$passwordFile" - echo "source \"gpg -d ${muttHome/#$HOME/\~}/${emailAddress}.gpg|\"" >> "$muttHome/$emailAddress" + + # Store password in pass + pass insert -f "email/$emailAddress" <<< "$passOne" + + # Add configuration to retrieve password from pass + echo "set imap_pass=\"`pass show email/$emailAddress`\"" >> "$muttHome/$emailAddress" + echo "set smtp_pass=\"`pass show email/$emailAddress`\"" >> "$muttHome/$emailAddress" + add_keybinding -echo "folder-hook .*$emailAddress/ 'source ${muttHome/#$HOME/\~}/$emailAddress'" >> "$muttHome/$emailAddress" - msgbox "$(gettext "Email address added, press enter to continue.")" + echo "folder-hook .*$emailAddress/ 'source ${muttHome/#$HOME/\~}/$emailAddress'" >> "$muttHome/$emailAddress" + msgbox "Email address added, press enter to continue." } configure_gmail() { - # This is just to create the base file with settings common to all gmail accounts - # I decided to do these in functions so as to not have a truly giagantic case statement in the add email function - echo "unset imap_passive" >> "$muttHome/$1" -echo "unset record" >> "$muttHome/$1" -echo "set imap_user=$1" >> "$muttHome/$1" -echo "set smtp_url=\"smtp://${1%@*}@smtp.gmail.com:587/" >> "$muttHome/$1" -echo "set folder=imaps://${1%@*}@imap.gmail.com/" >> "$muttHome/$1" -echo "set spoolfile = +INBOX" >> "$muttHome/$1" -echo "mailboxes = +INBOX" >> "$muttHome/$1" -echo "set postponed = +[Gmail]/Drafts" >> "$muttHome/$1" -echo "set record=+[Gmail]/Sent" >> "$muttHome/$1" -echo "set imap_keepalive=300" >> "$muttHome/$1" -echo "set mail_check=300" >> "$muttHome/$1" + # Copy the Gmail template and replace placeholders + cp "$fileDir/gmail.template" "$muttHome/$1.tmp" + + # Replace email placeholder in the template + sed -i "s|EMAIL_ADDRESS|$1|g" "$muttHome/$1.tmp" + sed -i "s|USERNAME|${1%@*}|g" "$muttHome/$1.tmp" + + # Append the template to the existing config + cat "$muttHome/$1.tmp" >> "$muttHome/$1" + rm "$muttHome/$1.tmp" + + # Handle goobook integration if available unset continue if command -v goobook &> /dev/null ; then - read -p "$(eval_gettext "Goobook is installed, would you like to use it as your addressbook for the account \$1? ")" continue - fi - if [ "${continue^}" = "Y" ]; then - echo "set query_command=\"goobook query %s\"" >> "$muttHome/$1" - # Normally macros go in muttHome/macros, but this may be a gmail specific setting - echo "macro index,pager a \"goobook add\" \"add sender to google contacts\"" >> "$muttHome/$1" + read -p "Goobook is installed, would you like to use it as your addressbook for the account $1? " continue + if [ "${continue^}" = "Y" ]; then + echo "set query_command=\"goobook query %s\"" >> "$muttHome/$1" + echo "macro index,pager a \"goobook add\" \"add sender to google contacts\"" >> "$muttHome/$1" + else + echo "source ~/${muttHome#/home/*/}/aliases" >> "$muttHome/$1" + fi else echo "source ~/${muttHome#/home/*/}/aliases" >> "$muttHome/$1" fi @@ -427,21 +308,17 @@ echo "set mail_check=300" >> "$muttHome/$1" configure_hotmail() { - # This is just to create the base file with settings common to all hotmail accounts - # I decided to do these in functions so as to not have a truly giagantic case statement in the add email function - echo "unset imap_passive" >> "$muttHome/$1" -echo "unset record" >> "$muttHome/$1" -echo "set imap_user=$1" >> "$muttHome/$1" -echo "set smtp_url=\"smtp://$1@smtp-mail.outlook.com:587/" >> "$muttHome/$1" -echo "set folder=imaps://$1@imap-mail.outlook.com/" >> "$muttHome/$1" -echo "set ssl_force_tls=yes" >> "$muttHome/$1" -echo "set spoolfile=+Inbox" >> "$muttHome/$1" -echo "mailboxes = +Inbox" >> "$muttHome/$1" -echo "set postponed=+Drafts" >> "$muttHome/$1" -echo "set record=+Sent" >> "$muttHome/$1" -echo "set imap_keepalive=300" >> "$muttHome/$1" -echo "set mail_check=300" >> "$muttHome/$1" -echo "bind editor complete-query" >> "$muttHome/$1" + # Copy the Hotmail template and replace placeholders + cp "$fileDir/hotmail.template" "$muttHome/$1.tmp" + + # Replace email placeholder in the template + sed -i "s|EMAIL_ADDRESS|$1|g" "$muttHome/$1.tmp" + + # Append the template to the existing config + cat "$muttHome/$1.tmp" >> "$muttHome/$1" + rm "$muttHome/$1.tmp" + + # Add source for aliases echo "source ~/${muttHome#/home/*/}/aliases" >> "$muttHome/$1" } @@ -456,78 +333,94 @@ configure_generic() local smtpHost local smtpUser local smtpPort - local extraSettings - read -p "$(gettext "Enter imap host: ")" -e -i imap.$hostName imapHost - read -p "$(gettext "Enter imap user: ")" -e -i $1 imapUser - read -p "$(gettext "Enter imap port: ")" -e -i 993 imapPort - read -p "$(gettext "Enter smtp host: ")" -e -i smtp.$hostName smtpHost - read -p "$(gettext "Enter smtp user: ")" -e -i $userName smtpUser - read -p "$(gettext "Enter smtp port: ")" -e -i 587 smtpPort - read -p "$(gettext "Enter extra settings, one line at a time, just press enter when done: ")" extraSettings + + # Gather input + read -p "Enter imap host: " -e -i imap.$hostName imapHost + read -p "Enter imap user: " -e -i $1 imapUser + read -p "Enter imap port: " -e -i 993 imapPort + read -p "Enter smtp host: " -e -i smtp.$hostName smtpHost + read -p "Enter smtp user: " -e -i $userName smtpUser + read -p "Enter smtp port: " -e -i 587 smtpPort + + # Copy the generic template + cp "$fileDir/generic.template" "$muttHome/$1.tmp" + + # Replace placeholders + sed -i "s|IMAP_HOST|$imapHost|g" "$muttHome/$1.tmp" + sed -i "s|IMAP_USER|$imapUser|g" "$muttHome/$1.tmp" + sed -i "s|IMAP_PORT|$imapPort|g" "$muttHome/$1.tmp" + sed -i "s|SMTP_HOST|$smtpHost|g" "$muttHome/$1.tmp" + sed -i "s|SMTP_USER|$smtpUser|g" "$muttHome/$1.tmp" + sed -i "s|SMTP_PORT|$smtpPort|g" "$muttHome/$1.tmp" + + # Append the template to the existing config + cat "$muttHome/$1.tmp" >> "$muttHome/$1" + rm "$muttHome/$1.tmp" + + # Add any extra settings + read -p "Enter extra settings, one line at a time, just press enter when done: " extraSettings while [ "$extraSettings" != "" ]; do echo "$extraSettings" >> "$muttHome/$1" - read $extreSettings + read extraSettings done - echo "unset imap_passive" >> "$muttHome/$1" -echo "unset record" >> "$muttHome/$1" -echo "set smtp_url=\"smtp://$smtpUser@$smtpHost:$smtpPort/" >> "$muttHome/$1" -echo "set folder=imaps://$imapUser@$imapHost:$imapPort/" >> "$muttHome/$1" -echo "mailboxes = +INBOX" >> "$muttHome/$1" -echo "set spoolfile = +INBOX" >> "$muttHome/$1" -echo "set postponed = +Drafts" >> "$muttHome/$1" -echo "set imap_keepalive=300" >> "$muttHome/$1" -echo "set mail_check=300" >> "$muttHome/$1" -echo "bind editor complete-query" >> "$muttHome/$1" + + # Add source for aliases echo "source ~/${muttHome#/home/*/}/aliases" >> "$muttHome/$1" } add_keybinding() { -# Here we search for previous keybinding -local fNumber=1 -while : ; do -grep "^[[:space:]m]acro.*index.*.*" $muttHome/muttrc &> /dev/null || break # fNumber is now the currently open keybinding. -((fNumber++)) # fNumber was taken, so increment it. -done -# Bind key FfNumber to the mail account. -echo "macro generic,index 'source ${muttHome/#$HOME/\~}/$emailAddress!'" >> "$muttHome/muttrc" -echo "mail account $emailAddress bound to F$fNumber." -if ! grep "^source.*@.*\..*" "$muttHome/muttrc" &> /dev/null ; then -continue="$(yesno "$(eval_gettext "Make \$emailAddress the default account?")")" -if [ "$continue" = "Yes" ]; then -echo "source ${muttHome/#$HOME/\~}/$emailAddress" >> "$muttHome/muttrc" -fi -fi + # Here we search for previous keybinding + local fNumber=1 + while : ; do + grep "^[[:space:]m]acro.*index.*.*" $muttHome/muttrc &> /dev/null || break # fNumber is now the currently open keybinding. + ((fNumber++)) # fNumber was taken, so increment it. + done + # Bind key FfNumber to the mail account. + echo "macro generic,index 'source ${muttHome/#$HOME/\~}/$emailAddress!'" >> "$muttHome/muttrc" + echo "mail account $emailAddress bound to F$fNumber." + if ! grep "^source.*@.*\..*" "$muttHome/muttrc" &> /dev/null ; then + continue="$(yesno "Make $emailAddress the default account?")" + if [ "$continue" = "Yes" ]; then + echo "source ${muttHome/#$HOME/\~}/$emailAddress" >> "$muttHome/muttrc" + fi + fi } new_contact() { - contactName="$(inputbox "$(gettext "Enter the contact's first and last name..")")" + contactName="$(inputbox "Enter the contact's first and last name..")" if [ -z "$contactName" ]; then exit 0 fi - contactEmail="$(inputbox "$(gettext "Enter the email address for") $contactName")" + contactEmail="$(inputbox "Enter the email address for $contactName")" if [ -z "$contactEmail" ]; then exit 0 fi contactAlias="${contactName,,}" contactAlias="${contactAlias// /-}" if grep "<$contactEmail>\| $contactAlias " "$muttHome/aliases" &> /dev/null ; then - [[ "$(yesno "$(gettext "This email address already exists in your contacts. Continue anyway?")")" != "Yes" ]] && exit 0 + [[ "$(yesno "This email address already exists in your contacts. Continue anyway?")" != "Yes" ]] && exit 0 fi echo "alias $contactAlias $contactName <$contactEmail>" >> "$muttHome/aliases" sort -u "$muttHome/aliases" -o "$muttHome/aliases" - msgbox "$contactName $(gettext "added to your address book")." + msgbox "$contactName added to your address book." } # This is the main loop of the program # Call functions to be ran every time the script is ran. check_dependancies initialize_directory + +# If in test mode, display a notification +if [ "$testMode" = true ]; then + echo "Running in test mode. Using $muttHome for configuration." +fi + # Let's make a mainmenu variable to hold all the options for the select loop. -mainmenu=("$(gettext "Add Email Address")" "$(gettext "Configure GPG")" "$(gettext "New Contact")" "$(gettext "Exit")") +mainmenu=("Add Email Address" "Configure GPG" "New Contact" "Exit") while : ; do -i="$(IFS=$'\n';menulist $(for i in "${mainmenu[@]}" ; do echo "$i";echo "$i";done))" + i="$(IFS=$'\n';menulist $(for i in "${mainmenu[@]}" ; do echo "$i";echo "$i";done))" [[ -z "$i" ]] && continue functionName="${i,,}" functionName="${functionName// /_}"