commit e2e031d52378a6f3d269bf9c37eb91b347d02588
parent 02d6cf66836fa77d9e5561c020616e8826292799
Author: awy <awy@awy.one>
Date: Wed, 24 Dec 2025 00:19:18 +0300
gpl header & different formatting
Diffstat:
| M | bin/aew | | | 552 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
| M | bin/mailsync | | | 150 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
2 files changed, 374 insertions(+), 328 deletions(-)
diff --git a/bin/aew b/bin/aew
@@ -1,4 +1,25 @@
#!/bin/bash
+# aew - auto-configure email accounts for aerc
+# including downloadable mail with `isync`.
+#
+# Copyright (C) 2018-2025 Luke Smith <luke@lukesmith.xyz>
+# Copyright (C) 2025 awy <awy@awy.one>
+#
+# This file is part of aerc-wizard.
+#
+# aerc-wizard is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation,
+# either version 3 of the License, or (at your option) any later version.
+#
+# aerc-wizard is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with aerc-wizard. If not, see
+# <https://www.gnu.org/licenses/>.
set -a
@@ -45,29 +66,29 @@ mbver="${mbver%.*}"
# dots and turn them into nice integers
mbver="${mbver/\./}"
if [ "${mbver}" -gt 14 ]; then
- master="Far"
- slave="Near"
+ master="Far"
+ slave="Near"
else
- master="Master"
- slave="Slave"
+ master="Master"
+ slave="Slave"
fi
for x in "/etc/ssl/certs/ca-certificates.crt" \
- "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/cert.pem" \
- "/etc/ssl/ca-bundle.pem" "/etc/pki/tls/cacert.pem" \
- "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" \
- "/usr/local/share/ca-certificates/"; do
- [ -f "$x" ] && sslcert="$x" && break
+ "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/cert.pem" \
+ "/etc/ssl/ca-bundle.pem" "/etc/pki/tls/cacert.pem" \
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" \
+ "/usr/local/share/ca-certificates/"; 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; }
checkbasics() {
- command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
- PASSWORD_STORE_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
- [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] || {
- echo "First run \`gopass init <yourgpgemail>\` to set up a password archive."
- echo "(If you don't already have a GPG key pair, first run \`$GPG --full-generate-key\`.)"
- exit 1
- }
+ command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
+ PASSWORD_STORE_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
+ [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] || {
+ echo "First run \`gopass init <yourgpgemail>\` to set up a password archive."
+ echo "(If you don't already have a GPG key pair, first run \`$GPG --full-generate-key\`.)"
+ exit 1
+ }
}
getaccounts() { accounts="$(sed -n 's/^\[\(.*\)\]/\1/p' "$accountsconf" 2>/dev/null | nl)"; }
@@ -75,225 +96,226 @@ getaccounts() { accounts="$(sed -n 's/^\[\(.*\)\]/\1/p' "$accountsconf" 2>/dev/n
list() { getaccounts && [ -n "$accounts" ] && echo "$accounts" || exit 1; }
prepmsmtp() {
- mkdir -p "${msmtprc%/*}" "${msmtplog%/*}"
- ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null
- envsubst <"$msmtptemp" >>"$msmtprc"
+ mkdir -p "${msmtprc%/*}" "${msmtplog%/*}"
+ ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null
+ envsubst <"$msmtptemp" >>"$msmtprc"
}
prepmbsync() {
- mkdir -p "${mbsyncrc%/*}"
- [ -f "$mbsyncrc" ] && echo >>"$mbsyncrc"
- case "$fulladdr" in
- *@gmail.com)
- envsubst <"$mbsyncgmailtemp" >>"$mbsyncrc"
- ;;
- *)
- envsubst <"$mbsynctemp" >>"$mbsyncrc"
- ;;
- esac
+ mkdir -p "${mbsyncrc%/*}"
+ [ -f "$mbsyncrc" ] && echo >>"$mbsyncrc"
+ case "$fulladdr" in
+ *@gmail.com)
+ envsubst <"$mbsyncgmailtemp" >>"$mbsyncrc"
+ ;;
+ *)
+ envsubst <"$mbsynctemp" >>"$mbsyncrc"
+ ;;
+ esac
}
prepmpop() {
- mkdir -p "${mpoprc%/*}"
- envsubst <"$mpoptemp" >>"$mpoprc"
+ mkdir -p "${mpoprc%/*}"
+ envsubst <"$mpoptemp" >>"$mpoprc"
}
prepimapnotify() {
- mkdir -p "$imapnotify" ; envsubst < "$imapnotifytemp" >> "$imapnotify/$fulladdr.conf"
+ mkdir -p "$imapnotify"
+ envsubst <"$imapnotifytemp" >>"$imapnotify/$fulladdr.conf"
}
prepaerc() {
- mkdir -p "$aercdir"
+ mkdir -p "$aercdir"
aercuser="${fulladdr%@*}"
aercdomain="${fulladdr#*@}"
- [ ! -f "$aercconf" ] && cat "$aerctempconf" >"$aercconf"
- [ ! -f "$accountsconf" ] && envsubst <"$aercbase" >"$accountsconf"
- ! grep -q "^multi-file-strategy" "$accountsconf" && envsubst <"$aercbase" >"$accountsconf"
- envsubst <"$aerctemp" >>"$accountsconf"
+ [ ! -f "$aercconf" ] && cat "$aerctempconf" >"$aercconf"
+ [ ! -f "$accountsconf" ] && envsubst <"$aercbase" >"$accountsconf"
+ ! grep -q "^multi-file-strategy" "$accountsconf" && envsubst <"$aercbase" >"$accountsconf"
+ envsubst <"$aerctemp" >>"$accountsconf"
chmod 600 "$accountsconf"
}
getprofiles() {
- safename="$(echo $fulladdr | sed 's/@/_/g')"
- case "$type" in
- online)
- folder="imaps://$login@$imap:$iport"
- extra="$(envsubst <"$onlinetemp")"
- ;;
- pop) prepmpop ;;
- *)
- case "$iport" in
- 1143) imapssl=None ;;
- 143) imapssl=STARTTLS ;;
- esac
- prepmbsync
- ;;
- esac
- prepmsmtp
+ safename="$(echo $fulladdr | sed 's/@/_/g')"
+ case "$type" in
+ online)
+ folder="imaps://$login@$imap:$iport"
+ extra="$(envsubst <"$onlinetemp")"
+ ;;
+ pop) prepmpop ;;
+ *)
+ case "$iport" in
+ 1143) imapssl=None ;;
+ 143) imapssl=STARTTLS ;;
+ esac
+ prepmbsync
+ ;;
+ esac
+ prepmsmtp
prepaerc
- prepnotmuch
+ prepnotmuch
prepimapnotify
}
parsedomains() {
- serverinfo="$(grep "^${fulladdr#*@}" "$muttshare/domains.csv" 2>/dev/null)"
+ serverinfo="$(grep "^${fulladdr#*@}" "$muttshare/domains.csv" 2>/dev/null)"
- [ -z "$serverinfo" ] && serverinfo="$(grep "$(echo "${fulladdr#*@}" | sed "s/\.[^\.]*$/\.\\\*/")" "$muttshare/domains.csv" 2>/dev/null)"
+ [ -z "$serverinfo" ] && serverinfo="$(grep "$(echo "${fulladdr#*@}" | sed "s/\.[^\.]*$/\.\\\*/")" "$muttshare/domains.csv" 2>/dev/null)"
- IFS=, read -r service imapsugg iportsugg smtpsugg sportsugg <<EOF
+ IFS=, read -r service imapsugg iportsugg smtpsugg sportsugg <<EOF
$serverinfo
EOF
- imap="${imap:-$imapsugg}"
- smtp="${smtp:-$smtpsugg}"
- sport="${sport:-$sportsugg}"
- iport="${iport:-$iportsugg}"
+ imap="${imap:-$imapsugg}"
+ smtp="${smtp:-$smtpsugg}"
+ sport="${sport:-$sportsugg}"
+ iport="${iport:-$iportsugg}"
}
delete() {
- if [ -z "${fulladdr+x}" ]; then
- echo "Select the account you would like to delete (by number):"
- list || exit 1
- read -r input
- match="^\s*$input\s\+"
- else
- match="\s\+$fulladdr$"
- getaccounts
- fi
-
- fulladdr="$(echo "$accounts" | grep "$match" | grep -o "\S*@\S*")"
-
- [ -z "$fulladdr" ] && echo "$fulladdr is not a valid account name." && return 1
-
- sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" 2>/dev/null
- rm -f "$mbsyncrc"bu
+ if [ -z "${fulladdr+x}" ]; then
+ echo "Select the account you would like to delete (by number):"
+ list || exit 1
+ read -r input
+ match="^\s*$input\s\+"
+ else
+ match="\s\+$fulladdr$"
+ getaccounts
+ fi
+
+ fulladdr="$(echo "$accounts" | grep "$match" | grep -o "\S*@\S*")"
+
+ [ -z "$fulladdr" ] && echo "$fulladdr is not a valid account name." && return 1
+
+ sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" 2>/dev/null
+ rm -f "$mbsyncrc"bu
sed -i "/^\[$fulladdr\]/,/^\[/ {
/^\[$fulladdr\]/d
/^\[/b
d
}" "$accountsconf" 2>/dev/null
- sed -ibu "/account $fulladdr$/,/^\(\s*$\|account\)/d" "$msmtprc" 2>/dev/null
- rm -f "$msmtprc"bu
- sed -ibu "/account $fulladdr$/,/^\(\s*$\|account\)/d" "$mpoprc" 2>/dev/null
- rm -f "$mpoprc"bu
- gopass rm -f "$passprefix$fulladdr" >/dev/null 2>&1
- [ -n "${purge+x}" ] && safename="$(echo $fulladdr | sed 's/@/_/g')" && rm -rf "${cachedir:?}/${safename:?}" "${maildir:?}/${fulladdr:?}"
+ sed -ibu "/account $fulladdr$/,/^\(\s*$\|account\)/d" "$msmtprc" 2>/dev/null
+ rm -f "$msmtprc"bu
+ sed -ibu "/account $fulladdr$/,/^\(\s*$\|account\)/d" "$mpoprc" 2>/dev/null
+ rm -f "$mpoprc"bu
+ gopass rm -f "$passprefix$fulladdr" >/dev/null 2>&1
+ [ -n "${purge+x}" ] && safename="$(echo $fulladdr | sed 's/@/_/g')" && rm -rf "${cachedir:?}/${safename:?}" "${maildir:?}/${fulladdr:?}"
}
askinfo() {
- [ -z "$fulladdr" ] && echo "Give the full email address to add:" &&
- read -r fulladdr
- while ! echo "$fulladdr" | grep -qE "^.+@.+\.[A-Za-z]+$"; do
- echo "$fulladdr is not a valid email address. Please retype the address:"
- read -r fulladdr
- done
- folder="$maildir/$fulladdr"
- getaccounts
- echo "$accounts" | grep -q "\s$fulladdr$" 2>/dev/null &&
- { echo "$fulladdr has already been added" && exit 1; }
- { [ -z "$imap" ] || [ -z "$smtp" ]; } && parsedomains
- [ -z "$imap" ] && echo "Give your email server's IMAP address (excluding the port number):" &&
- read -r imap
- [ -z "$smtp" ] && echo "Give your email server's SMTP address (excluding the port number):" &&
- read -r smtp
- case $sport in
- 587) tlsline="# tls_starttls" ;;
- esac
- [ -z "$realname" ] && realname="${fulladdr%%@*}"
- [ -z "$passprefix" ] && passprefix=""
- hostname="${fulladdr#*@}"
- login="${login:-$fulladdr}"
- if [ -n "${password+x}" ] && [ ! -f "$PASSWORD_STORE_DIR/$passprefix$fulladdr.gpg" ]; then
- insertpass
- elif [ ! -f "$PASSWORD_STORE_DIR/$passprefix$fulladdr.gpg" ]; then
- getpass
- fi
+ [ -z "$fulladdr" ] && echo "Give the full email address to add:" &&
+ read -r fulladdr
+ while ! echo "$fulladdr" | grep -qE "^.+@.+\.[A-Za-z]+$"; do
+ echo "$fulladdr is not a valid email address. Please retype the address:"
+ read -r fulladdr
+ done
+ folder="$maildir/$fulladdr"
+ getaccounts
+ echo "$accounts" | grep -q "\s$fulladdr$" 2>/dev/null &&
+ { echo "$fulladdr has already been added" && exit 1; }
+ { [ -z "$imap" ] || [ -z "$smtp" ]; } && parsedomains
+ [ -z "$imap" ] && echo "Give your email server's IMAP address (excluding the port number):" &&
+ read -r imap
+ [ -z "$smtp" ] && echo "Give your email server's SMTP address (excluding the port number):" &&
+ read -r smtp
+ case $sport in
+ 587) tlsline="# tls_starttls" ;;
+ esac
+ [ -z "$realname" ] && realname="${fulladdr%%@*}"
+ [ -z "$passprefix" ] && passprefix=""
+ hostname="${fulladdr#*@}"
+ login="${login:-$fulladdr}"
+ if [ -n "${password+x}" ] && [ ! -f "$PASSWORD_STORE_DIR/$passprefix$fulladdr.gpg" ]; then
+ insertpass
+ elif [ ! -f "$PASSWORD_STORE_DIR/$passprefix$fulladdr.gpg" ]; then
+ getpass
+ fi
}
insertpass() {
- printf "%s" "$password" | gopass insert -fe "$passprefix$fulladdr"
+ printf "%s" "$password" | gopass insert -fe "$passprefix$fulladdr"
}
errorexit() {
- echo "Log-on not successful."
- case "$imap" in
- imap.gmail.com)
- echo "This account with $service is using Google's Gmail servers, which disable all third-party applications without an application-specific password.
+ echo "Log-on not successful."
+ case "$imap" in
+ imap.gmail.com)
+ echo "This account with $service is using Google's Gmail servers, which disable all third-party applications without an application-specific password.
Please be sure you are using OAUTH with your Gmail account, or better yet, stop using Gmail."
- ;;
- imap.mail.me.com)
- echo "This account with $service is using Apple's iCloud servers, which disable all non-Apple applications by default.
+ ;;
+ imap.mail.me.com)
+ echo "This account with $service is using Apple's iCloud servers, which disable all non-Apple applications by default.
Please be sure you either enable third-party applications, or create an app-specific password, or best of all, stop using Apple."
- ;;
- esac
- exit 1
+ ;;
+ esac
+ exit 1
}
getpass() { while :; do
- gopass rm -f "$passprefix$fulladdr" >/dev/null 2>&1
- gopass insert -f "$passprefix$fulladdr" && break
+ gopass rm -f "$passprefix$fulladdr" >/dev/null 2>&1
+ gopass insert -f "$passprefix$fulladdr" && break
done; }
getboxes() {
- if [ -n "${force+x}" ]; then
- mailboxes="$(printf "INBOX\\nDrafts\\nJunk\\nTrash\\nSent\\nArchive")"
- else
- info="$(curl --location-trusted -s -m 5 --user "$login:$(gopass "$passprefix$fulladdr")" --url "${protocol:-imaps}://$imap:${iport:-993}")"
- [ -z "$info" ] && errorexit
- mailboxes="$(echo "$info" | grep -v HasChildren | sed "s/.*\" //;s/\"//g" | tr -d '\r')"
- fi
- [ "$type" = "pop" ] && mailboxes="INBOX"
+ if [ -n "${force+x}" ]; then
+ mailboxes="$(printf "INBOX\\nDrafts\\nJunk\\nTrash\\nSent\\nArchive")"
+ else
+ info="$(curl --location-trusted -s -m 5 --user "$login:$(gopass "$passprefix$fulladdr")" --url "${protocol:-imaps}://$imap:${iport:-993}")"
+ [ -z "$info" ] && errorexit
+ mailboxes="$(echo "$info" | grep -v HasChildren | sed "s/.*\" //;s/\"//g" | tr -d '\r')"
+ fi
+ [ "$type" = "pop" ] && mailboxes="INBOX"
sed -n 's/^\[\(.*\)\]/\1/p' "$accountsconf" | wc -l
idnum=$((idnum + 1))
- case "$fulladdr" in
- *@gmail.com)
- mailboxes=$(echo "$mailboxes" | sed -e 's#^\[Gmail\]/##' -e 's/^Sent Mail$/Sent/' -e 's/^Spam$/Junk/')
- toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/;s/'/\\\'/g" | paste -sd ' ' -)"
- ;;
- *)
- toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/;s/'/\\\'/g" | paste -sd ' ' -)"
- ;;
- esac
+ case "$fulladdr" in
+ *@gmail.com)
+ mailboxes=$(echo "$mailboxes" | sed -e 's#^\[Gmail\]/##' -e 's/^Sent Mail$/Sent/' -e 's/^Spam$/Junk/')
+ toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/;s/'/\\\'/g" | paste -sd ' ' -)"
+ ;;
+ *)
+ toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/;s/'/\\\'/g" | paste -sd ' ' -)"
+ ;;
+ esac
}
finalize() {
- [ "$type" != "online" ] && echo "$mailboxes" | xargs -I {} mkdir -p "$maildir/$fulladdr/{}/cur" "$maildir/$fulladdr/{}/tmp" "$maildir/$fulladdr/{}/new"
- mkdir -p "$cachedir/$safename/bodies"
- echo "$fulladdr (account #$idnum) added successfully."
- command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" >"$HOME/.urlview"
- return 0
+ [ "$type" != "online" ] && echo "$mailboxes" | xargs -I {} mkdir -p "$maildir/$fulladdr/{}/cur" "$maildir/$fulladdr/{}/tmp" "$maildir/$fulladdr/{}/new"
+ mkdir -p "$cachedir/$safename/bodies"
+ echo "$fulladdr (account #$idnum) added successfully."
+ command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" >"$HOME/.urlview"
+ return 0
}
prepnotmuch() {
- [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
- [ -f "$NOTMUCH_CONFIG" ] && return 0
- envsubst <"$notmuchtemp" >"$NOTMUCH_CONFIG"
+ [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
+ [ -f "$NOTMUCH_CONFIG" ] && return 0
+ envsubst <"$notmuchtemp" >"$NOTMUCH_CONFIG"
}
togglecron() {
- cron="$(mktemp)"
- crontab -l >"$cron"
- if grep -q mailsync "$cron"; then
- echo "Removing automatic mailsync..."
- sed -ibu /mailsync/d "$cron"
- rm -f "$cron"bu
- else
- echo "Adding automatic mailsync every ${cronmin:-10} minutes..."
- echo "*/${cronmin:-10} * * * * $prefix/bin/mailsync" >>"$cron"
- fi &&
- crontab "$cron"
- rm -f "$cron"
+ cron="$(mktemp)"
+ crontab -l >"$cron"
+ if grep -q mailsync "$cron"; then
+ echo "Removing automatic mailsync..."
+ sed -ibu /mailsync/d "$cron"
+ rm -f "$cron"bu
+ else
+ echo "Adding automatic mailsync every ${cronmin:-10} minutes..."
+ echo "*/${cronmin:-10} * * * * $prefix/bin/mailsync" >>"$cron"
+ fi &&
+ crontab "$cron"
+ rm -f "$cron"
}
setact() { if [ -n "${action+x}" ] && [ "$action" != "$1" ]; then
- echo "Running $1 with $action..."
- echo "Incompatible options given. Only one action may be specified per run."
- exit 1
+ echo "Running $1 with $action..."
+ echo "Incompatible options given. Only one action may be specified per run."
+ exit 1
else
- action="$1"
+ action="$1"
fi; }
aewinfo() {
- cat <<EOF
+ cat <<EOF
aew: aerc-wizard, auto-configure email accounts for aerc
including downloadable mail with \`isync\`.
@@ -328,114 +350,114 @@ EOF
}
reorder() {
- tempfile="$(mktemp -u)"
- tmp_out="$(mktemp -u)"
- trap 'rm -f $tempfile' HUP INT QUIT TERM PWR EXIT
- echo "# Carefully reorder these accounts with the desired numbers in the first column.
+ tempfile="$(mktemp -u)"
+ tmp_out="$(mktemp -u)"
+ trap 'rm -f $tempfile' HUP INT QUIT TERM PWR EXIT
+ echo "# Carefully reorder these accounts with the desired numbers in the first column.
# DO NOT reorder rows or rename the accounts in the second column." >"$tempfile"
sed -n 's/^\[\(.*\)\]/\1/p' "$accountsconf" | nl -w1 -s' ' >>"$tempfile"
- ${EDITOR:-vim} "$tempfile" || exit 1
+ ${EDITOR:-vim} "$tempfile" || exit 1
awk '
/^\[/ { exit }
{ print }
- ' "$accountsconf" > "$tmp_out"
- echo >> "$tmp_out"
- sed -e 's/#.*//' -e '/^[[:space:]]*$/d' "$tempfile" > "${tempfile}.clean"
- sort -n "${tempfile}.clean" > "${tempfile}.sorted"
+ ' "$accountsconf" >"$tmp_out"
+ echo >>"$tmp_out"
+ sed -e 's/#.*//' -e '/^[[:space:]]*$/d' "$tempfile" >"${tempfile}.clean"
+ sort -n "${tempfile}.clean" >"${tempfile}.sorted"
while read -r idx email; do
awk -v acct="[$email]" '
$0 == acct { inblock=1; print; next }
inblock && /^\[/ { exit }
inblock { print }
- ' "$accountsconf" >> "$tmp_out"
- echo >> "$tmp_out"
- done < "${tempfile}.sorted"
- awk 'NF{blank=0} !NF{blank++} blank<2' "$tmp_out" > "$accountsconf"
+ ' "$accountsconf" >>"$tmp_out"
+ echo >>"$tmp_out"
+ done <"${tempfile}.sorted"
+ awk 'NF{blank=0} !NF{blank++} blank<2' "$tmp_out" >"$accountsconf"
rm -f "${tempfile}.clean" "${tempfile}.sorted"
}
while getopts "rfpXlhodTYD:y:i:I:s:S:u:a:n:P:x:m:t:" o; do case "${o}" in
- l) setact list ;;
- r) setact reorder ;;
- d) setact delete ;;
- D)
- setact delete
- fulladdr="$OPTARG"
- ;;
- y)
- setact sync
- fulladdr="$OPTARG"
- ;;
- Y) setact sync ;;
- a)
- setact add
- fulladdr="$OPTARG"
- ;;
- i)
- setact add
- imap="$OPTARG"
- ;;
- I)
- setact add
- iport="$OPTARG"
- ;;
- s)
- setact add
- smtp="$OPTARG"
- ;;
- S)
- setact add
- sport="$OPTARG"
- ;;
- u)
- setact add
- login="$OPTARG"
- ;;
- n)
- setact add
- realname="$OPTARG"
- ;;
- P)
- setact add
- passprefix="$OPTARG"
- ;;
- m)
- setact add
- maxmes="$OPTARG"
- ;;
- o)
- setact add
- type="online"
- ;;
- p)
- setact add
- type="pop"
- protocol="pop3s"
- iport="${iport:-995}"
- ;;
- f)
- setact add
- force=True
- ;;
- x)
- setact add
- password="$OPTARG"
- ;;
- X)
- setact delete
- purge=True
- ;;
- t)
- setact toggle
- cronmin="$OPTARG"
- ;;
- T) setact toggle ;;
- h) setact info ;;
- \?)
- echo "See \`$(basename $0) -h\` for possible options and help."
- exit 1
- ;;
- esac done
+ l) setact list ;;
+ r) setact reorder ;;
+ d) setact delete ;;
+ D)
+ setact delete
+ fulladdr="$OPTARG"
+ ;;
+ y)
+ setact sync
+ fulladdr="$OPTARG"
+ ;;
+ Y) setact sync ;;
+ a)
+ setact add
+ fulladdr="$OPTARG"
+ ;;
+ i)
+ setact add
+ imap="$OPTARG"
+ ;;
+ I)
+ setact add
+ iport="$OPTARG"
+ ;;
+ s)
+ setact add
+ smtp="$OPTARG"
+ ;;
+ S)
+ setact add
+ sport="$OPTARG"
+ ;;
+ u)
+ setact add
+ login="$OPTARG"
+ ;;
+ n)
+ setact add
+ realname="$OPTARG"
+ ;;
+ P)
+ setact add
+ passprefix="$OPTARG"
+ ;;
+ m)
+ setact add
+ maxmes="$OPTARG"
+ ;;
+ o)
+ setact add
+ type="online"
+ ;;
+ p)
+ setact add
+ type="pop"
+ protocol="pop3s"
+ iport="${iport:-995}"
+ ;;
+ f)
+ setact add
+ force=True
+ ;;
+ x)
+ setact add
+ password="$OPTARG"
+ ;;
+ X)
+ setact delete
+ purge=True
+ ;;
+ t)
+ setact toggle
+ cronmin="$OPTARG"
+ ;;
+ T) setact toggle ;;
+ h) setact info ;;
+ \?)
+ echo "See \`$(basename $0) -h\` for possible options and help."
+ exit 1
+ ;;
+ esac done
[ -z "$action" ] && action="info"
@@ -444,13 +466,13 @@ list) list ;;
add) checkbasics && askinfo && getboxes && getprofiles && finalize ;;
delete) delete ;;
sync)
- echo "\`aew -y\` and \`aew -Y\` are now deprecated and will be removed in a future update. Please switch to using \`mailsync\`."
- mailsync $fulladdr
- ;;
+ echo "\`aew -y\` and \`aew -Y\` are now deprecated and will be removed in a future update. Please switch to using \`mailsync\`."
+ mailsync $fulladdr
+ ;;
toggle) togglecron ;;
reorder) reorder ;;
info)
- aewinfo
- exit 1
- ;;
+ aewinfo
+ exit 1
+ ;;
esac
diff --git a/bin/mailsync b/bin/mailsync
@@ -1,10 +1,30 @@
#!/bin/sh
-
-# - Syncs mail for all accounts, or a single account given as an argument.
-# - Displays a notification showing the number of new mails.
-# - Displays a notification for each new mail with its subject displayed.
-# - Runs notmuch to index new mail.
-# - This script can be set up as a cron job for automated mail syncing.
+# mailsync - synchronize mail accounts.
+#
+# Syncs mail for all accounts, or a single account given as an argument.
+# Displays a notification showing the number of new mails.
+# Displays a notification for each new mail with its subject displayed.
+# Runs notmuch to index new mail.
+# This script can be set up as a cron job for automated mail syncing.
+#
+# Copyright (C) 2018-2025 Luke Smith <luke@lukesmith.xyz>
+# Copyright (C) 2025 awy <awy@awy.one>
+#
+# This file is part of aerc-wizard.
+#
+# aerc-wizard is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation,
+# either version 3 of the License, or (at your option) any later version.
+#
+# aerc-wizard is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with aerc-wizard. If not, see
+# <https://www.gnu.org/licenses/>.
# There are many arbitrary and ugly features in this script because it is
# inherently difficult to pass environmental variables to cronjobs and other
@@ -12,20 +32,23 @@
# Xorg and MacOS as well.
# Run only if not already running in other instance
-pgrep mbsync >/dev/null && { echo "mbsync is already running."; exit ;}
+pgrep mbsync >/dev/null && {
+ echo "mbsync is already running."
+ exit
+}
# First, we have to get the right variables for the mbsync file, the gopass
# archive, notmuch and the GPG home. This is done by searching common profile
# files for variable assignments. This is ugly, but there are few options that
# will work on the maximum number of machines.
eval "$(grep -h -- \
- "^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \
- "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \
- "$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \
- "$HOME/.pam_environment" 2>/dev/null)"
+ "^\s*\(export \)\?\(MBSYNCRC\|MPOPRC\|PASSWORD_STORE_DIR\|PASSWORD_STORE_GPG_OPTS\|NOTMUCH_CONFIG\|GNUPGHOME\|MAILSYNC_MUTE\|XDG_CONFIG_HOME\|XDG_DATA_HOME\)=" \
+ "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.zprofile" "$HOME/.config/zsh/.zprofile" "$HOME/.zshenv" \
+ "$HOME/.config/zsh/.zshenv" "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/zsh/.zshrc" \
+ "$HOME/.pam_environment" 2>/dev/null)"
# For non-interactive shell (e.g. cron job) run only when the GPG key (in $GNUPGHOME or gopass --homedir) is unlocked
-tty -s || (echo "dummy" | gpg --sign --batch --yes -o /dev/null > /dev/null 2>&1) || exit
+tty -s || (echo "dummy" | gpg --sign --batch --yes -o /dev/null >/dev/null 2>&1) || exit
export GPG_TTY="$(tty)"
@@ -36,51 +59,52 @@ lastrun="${XDG_CONFIG_HOME:-$HOME/.config}/aerc/.mailsynclastrun"
# Settings are different for MacOS (Darwin) systems.
case "$(uname)" in
- Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\"" ;} ;;
- *)
- case "$(readlink -f /sbin/init)" in
- *systemd*|*openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;;
- # *dinit*) export DBUS_SESSION_BUS_ADDRESS=$(grep -E -z "DBUS_SESSION_BUS_ADDRESS" "/proc/$(pgrep -x swaybar)/environ" | sed 's/DBUS_SESSION_BUS_ADDRESS=//') ;;
- esac
-
- notify() {
- notify-send --app-name="aerc-wizard" -- "$1" "$2"
- }
- ;;
+Darwin) notify() { osascript -e "display notification \"$2\" with title \"$1\""; } ;;
+*)
+ case "$(readlink -f /sbin/init)" in
+ *systemd* | *openrc*) export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus ;;
+ # *dinit*) export DBUS_SESSION_BUS_ADDRESS=$(grep -E -z "DBUS_SESSION_BUS_ADDRESS" "/proc/$(pgrep -x swaybar)/environ" | sed 's/DBUS_SESSION_BUS_ADDRESS=//') ;;
+ esac
+
+ notify() {
+ notify-send --app-name="aerc-wizard" -- "$1" "$2"
+ }
+ ;;
esac
# Check account for new mail. Notify if there is new content.
syncandnotify() {
- case "$1" in
- imap) mbsync -q "$2" ;;
- pop) mpop -q "$2" ;;
- esac
- new=$(find\
- "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \
- "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \
- -type f -newer "$lastrun" 2> /dev/null)
- newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l)
- case 1 in
- $((newcount > 5)) )
- echo "$newcount new mails for $2."
- [ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mails in \`$2\` account."
- ;;
- $((newcount > 0)) )
- echo "$newcount new mail(s) for $2."
- [ -z "$MAILSYNC_MUTE" ] &&
- for file in $new; do
- # Extract and decode subject and sender from mail.
- subject=$(awk '/^Subject: / && ++n == 1,/^.*: / && ++i == 2' "$file" | head -n-1 |
- perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' |
- sed 's/^Subject: //' | tr -d '\n\t')
- from="$(sed -n "/^From:/ s|From: *|| p" "$file" |
- perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')"
- from="${from% *}" ; from="${from%\"}" ; from="${from#\"}"
- notify "📧$from:" "$subject"
- done
- ;;
- *) echo "No new mail for $2." ;;
-esac
+ case "$1" in
+ imap) mbsync -q "$2" ;;
+ pop) mpop -q "$2" ;;
+ esac
+ new=$(find "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/new/ \
+ "$HOME/.local/share/mail/$2/"[Ii][Nn][Bb][Oo][Xx]/cur/ \
+ -type f -newer "$lastrun" 2>/dev/null)
+ newcount=$(echo "$new" | sed '/^\s*$/d' | wc -l)
+ case 1 in
+ $((newcount > 5)))
+ echo "$newcount new mails for $2."
+ [ -z "$MAILSYNC_MUTE" ] && notify "New Mail!" "📬 $newcount new mails in \`$2\` account."
+ ;;
+ $((newcount > 0)))
+ echo "$newcount new mail(s) for $2."
+ [ -z "$MAILSYNC_MUTE" ] &&
+ for file in $new; do
+ # Extract and decode subject and sender from mail.
+ subject=$(awk '/^Subject: / && ++n == 1,/^.*: / && ++i == 2' "$file" | head -n-1 |
+ perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' |
+ sed 's/^Subject: //' | tr -d '\n\t')
+ from="$(sed -n "/^From:/ s|From: *|| p" "$file" |
+ perl -CS -MEncode -ne 'print decode("MIME-Header", $_)')"
+ from="${from% *}"
+ from="${from%\"}"
+ from="${from#\"}"
+ notify "📧$from:" "$subject"
+ done
+ ;;
+ *) echo "No new mail for $2." ;;
+ esac
}
allaccounts="$(grep -hs "^\(Channel\|Group\|account\)" "$MBSYNCRC" "$MPOPRC")"
@@ -90,20 +114,20 @@ allaccounts=$(echo "$allaccounts" | grep -v 'gmail\.com-[^ ]*')
IFS='
'
if [ -z "$1" ]; then
- tosync="$allaccounts"
+ tosync="$allaccounts"
else
- tosync="$(for arg in "$@"; do for availacc in $allaccounts; do
- [ "$arg" = "${availacc##* }" ] && echo "$availacc" && break
- done || echo "error $arg"; done)"
+ tosync="$(for arg in "$@"; do for availacc in $allaccounts; do
+ [ "$arg" = "${availacc##* }" ] && echo "$availacc" && break
+ done || echo "error $arg"; done)"
fi
for account in $tosync; do
- case $account in
- Channel*) syncandnotify imap "${account##* }" & ;;
- Group*) syncandnotify imap "${account##* }" & ;;
- account*) syncandnotify pop "${account##* }" & ;;
- error*) echo "ERROR: Account ${account##* } not found." ;;
- esac
+ case $account in
+ Channel*) syncandnotify imap "${account##* }" & ;;
+ Group*) syncandnotify imap "${account##* }" & ;;
+ account*) syncandnotify pop "${account##* }" & ;;
+ error*) echo "ERROR: Account ${account##* } not found." ;;
+ esac
done
wait