選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

mw 13 KiB

4年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
5年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
5年前
3年前
3年前
3年前
3年前
3年前
3年前
5年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #!/bin/sh
  2. command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
  3. [ -z ${PASSWORD_STORE_DIR+x} ] && PASSWORD_STORE_DIR="$HOME/.password-store"
  4. [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] &&
  5. "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || {
  6. 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 \`%s --full-gen-key\` first.\\n" "$GPG"
  7. exit
  8. }
  9. prefix="/usr/local"
  10. pass_prefix="mw-"
  11. muttdir="${XDG_CONFIG_HOME:-$HOME/.config}/mutt" # Main mutt config location
  12. accdir="$muttdir/accounts" # Directory for account settings
  13. maildir="${XDG_DATA_HOME:-$HOME/.local/share}/mail" # Location of mail storage
  14. emailre=".+@.+\..+" # Regex to confirm valid email address
  15. muttshare="$prefix/share/mutt-wizard"
  16. mbsyncrc="${MBSYNCRC:-$HOME/.mbsyncrc}"
  17. mwconfig="$muttshare/mutt-wizard.muttrc"
  18. cachedir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard"
  19. muttrc="$muttdir/muttrc"
  20. msmtprc="${XDG_CONFIG_HOME:-$HOME/.config}/msmtp/config"
  21. msmtplog="${XDG_CONFIG_HOME:-$HOME/.config}/msmtp/msmtp.log"
  22. MARKER="# mw-autogenerated"
  23. alias mbsync='mbsync -c "$mbsyncrc"'
  24. for x in "/etc/ssl/certs/ca-certificates.crt" "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/ca-bundle.pem" "/etc/pki/tls/cacert.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/ssl/cert.pem" "/usr/local/share/ca-certificates/"
  25. do
  26. [ -f "$x" ] && sslcert="$x" && break
  27. done || { echo "CA Certificate not found. Please install one or link it to /etc/ssl/certs/ca-certificates.crt" && exit 1 ;}
  28. getaccounts() { accounts="$(find -L "$accdir" -type f | grep -o "[0-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc$//" | sort -n)" ;}
  29. list() { getaccounts && [ -n "$accounts" ] && echo "$accounts" ;}
  30. getprofiles() { \
  31. unset msmtp_header msmtp_profile mutt_profile mbsync_profile
  32. msmtp_header="defaults
  33. auth on
  34. tls on
  35. tls_trust_file $sslcert
  36. logfile $msmtplog
  37. "
  38. msmtp_profile="account $fulladdr
  39. host $smtp
  40. port ${sport:-587}
  41. from $fulladdr
  42. user $login
  43. passwordeval \"pass $pass_prefix$fulladdr\"
  44. $tlsline
  45. "
  46. mbsync_profile="IMAPStore $fulladdr-remote
  47. Host $imap
  48. Port ${iport:-993}
  49. User $login
  50. PassCmd \"pass $pass_prefix$fulladdr\"
  51. AuthMechs LOGIN
  52. SSLType ${ssltype:-IMAPS}
  53. CertificateFile $sslcert
  54. MaildirStore $fulladdr-local
  55. Subfolders Verbatim
  56. Path ${XDG_DATA_HOME:-$HOME/.local/share}/mail/$fulladdr/
  57. Inbox ${XDG_DATA_HOME:-$HOME/.local/share}/mail/$fulladdr/INBOX
  58. Flatten .
  59. Channel $fulladdr
  60. Expunge Both
  61. Master :$fulladdr-remote:
  62. Slave :$fulladdr-local:
  63. Patterns * !\"[Gmail]/All Mail\"
  64. Create Both
  65. SyncState *
  66. MaxMessages ${maxmes:-0}
  67. ExpireUnread no
  68. # End profile
  69. "
  70. if [ -z "${online+x}" ]; then
  71. mutt_profile="# vim: filetype=neomuttrc
  72. # muttrc file for account $fulladdr
  73. set realname = \"$realname\"
  74. set from = \"$fulladdr\"
  75. set sendmail = \"msmtp -a $fulladdr\"
  76. alias me $realname <$fulladdr>
  77. set folder = \"$maildir/$fulladdr\"
  78. set header_cache = $cachedir/$fulladdr/headers
  79. set message_cachedir = $cachedir/$fulladdr/bodies
  80. set mbox_type = Maildir
  81. bind index,pager gg noop
  82. bind index,pager g noop
  83. bind index,pager M noop
  84. bind index,pager C noop
  85. bind index gg first-entry
  86. macro index o \"<shell-escape>mw -y $fulladdr<enter>\" \"run mbsync to sync $fulladdr\"
  87. unmailboxes *
  88. "
  89. else
  90. mutt_profile="# vim: filetype=neomuttrc
  91. # muttrc file for account $fulladdr
  92. set realname = \"$realname\"
  93. set from = \"$fulladdr\"
  94. set sendmail = \"msmtp -a $fulladdr\"
  95. alias me $realname <$fulladdr>
  96. set folder = \"imaps://$login@$imap:${iport:-993}\"
  97. set imap_user = \"$login\"
  98. set header_cache = $cachedir/$fulladdr/headers
  99. set message_cachedir = $cachedir/$fulladdr/bodies
  100. set imap_pass = \"\`pass $pass_prefix$fulladdr\`\"
  101. set mbox_type = Maildir
  102. set ssl_starttls = yes
  103. set ssl_force_tls = yes
  104. bind index,pager gg noop
  105. bind index,pager g noop
  106. bind index,pager M noop
  107. bind index,pager C noop
  108. bind index gg first-entry
  109. unmailboxes *
  110. "
  111. fi
  112. }
  113. parsedomains(){ serverinfo="$(grep "^${fulladdr#*@}" "$muttshare/domains.csv" 2>/dev/null)"
  114. [ -z "$serverinfo" ] && serverinfo="$(grep "$(echo "${fulladdr#*@}" | sed "s/\.[^\.]*$/\.\\\*/")" "$muttshare/domains.csv" 2>/dev/null)"
  115. IFS=, read -r service imapsugg iportsugg smtpsugg sportsugg <<EOF
  116. $serverinfo
  117. EOF
  118. imap="${imap:-$imapsugg}"
  119. smtp="${smtp:-$smtpsugg}"
  120. sport="${sport:-$sportsugg}"
  121. iport="${iport:-$iportsugg}"
  122. }
  123. delete() { if [ -z "${fulladdr+x}" ]; then
  124. echo "Select the account your would like to delete (by number):"
  125. list
  126. read -r input
  127. match="^$input:"
  128. else
  129. match=" $fulladdr$"
  130. getaccounts
  131. fi
  132. fulladdr="$(echo "$accounts" | grep "$match" | cut -f2 -d' ')"
  133. [ -z "$fulladdr" ] && echo "Invalid account name given." && return 1
  134. sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" ; rm -rf "$mbsyncrc"bu
  135. rm -rf "${cachedir:?}/${fulladdr:?}" "$accdir/"[1-9]"-$fulladdr.muttrc"
  136. sed -ibu "/[0-9]-$fulladdr.muttrc/d" "$muttrc" ; rm -f "$muttrc"bu
  137. sed -ibu "/account $fulladdr/,/^\(\s*$\|account\)/d" "$msmtprc"; rm -f "$msmtprc"bu
  138. pass rm -f "$pass_prefix$fulladdr" >/dev/null 2>&1
  139. }
  140. askinfo() { \
  141. [ -z "$fulladdr" ] && echo "Give the full email address to add:" &&
  142. read -r fulladdr
  143. while ! echo "$fulladdr" | grep -qE "$emailre"; do
  144. echo "\`$fulladdr\` is not a valid email address. Please retype the address:"
  145. read -r fulladdr
  146. done
  147. { [ -z "$imap" ] || [ -z "$smtp" ] ;} && parsedomains
  148. [ -z "$imap" ] && echo "Give your email server's IMAP address (excluding the port number):" &&
  149. read -r imap
  150. [ -z "$smtp" ] && echo "Give your email server's SMTP address (excluding the port number):" &&
  151. read -r smtp
  152. [ "$sport" = 465 ] && tlsline="tls_starttls off"
  153. [ -z "$realname" ] && echo "Give the name you would like to be identified by on the email account:" &&
  154. read -r realname
  155. login="${login:-$fulladdr}"
  156. if [ -n "${password+x}" ]; then
  157. createpass
  158. else
  159. getpass
  160. fi
  161. }
  162. createpass() { echo "$password" > "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr"
  163. "$GPG" -qer "$(cat "$PASSWORD_STORE_DIR/.gpg-id")" "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr"
  164. rm -f "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr" ;}
  165. writeinfo() { mkdir -p "$muttdir" "$accdir" "$cachedir/$fulladdr/bodies" "${XDG_CONFIG_HOME:-$HOME/.config}/msmtp" "$maildir/$fulladdr"
  166. # Get accounts and find the first missing account number (max. 9).
  167. getaccounts; for x in $(seq 1 9); do echo "$accounts" | grep -q "$x" || { export idnum="$x"; break ;}; done
  168. # Configure msmtprc for sending mail.
  169. [ ! -f "$msmtprc" ] && echo "$msmtp_header" > "$msmtprc"
  170. echo "$msmtp_profile" >> "$msmtprc"
  171. # On Ubuntu/Debian, a link is needed since they use an older version.
  172. command -V apt-get >/dev/null 2>&1 && ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null
  173. # Create the mbsync config file.
  174. mkdir -p "${mbsyncrc%/*}"
  175. echo "$mbsync_profile" >> "$mbsyncrc"
  176. # Create a muttrc for viewing mail.
  177. echo "$mutt_profile" > "$accdir/$idnum-$fulladdr.muttrc"
  178. [ ! -f "$muttrc" ] && echo "# vim: filetype=neomuttrc" > "$muttrc"
  179. ! grep -q "^source.*mutt-wizard.muttrc" "$muttrc" && echo "source $mwconfig $MARKER" >> "$muttrc"
  180. ! grep "^source.*.muttrc" "$muttrc" | grep -qv "$mwconfig" && echo "source $accdir/$idnum-$fulladdr.muttrc $MARKER" >> "$muttrc"
  181. echo "macro index,pager i$idnum '<sync-mailbox><enter-command>source $accdir/$idnum-$fulladdr.muttrc<enter><change-folder>!<enter>;<check-stats>' \"switch to $fulladdr\" $MARKER" >> "$muttrc"
  182. notmuchauto # Create a notmuch config file if not present already.
  183. }
  184. getpass() { while : ; do pass rm -f "$pass_prefix$fulladdr" >/dev/null 2>&1
  185. pass insert "$pass_prefix$fulladdr" && break; done ;}
  186. formatShortcut() { toappend="$toappend
  187. macro index,pager g$1 \"<change-folder>=$3<enter>\" \"go to $2\" $MARKER
  188. macro index,pager M$1 \";<save-message>=$3<enter>\" \"move mail to $2\" $MARKER
  189. macro index,pager C$1 \";<copy-message>=$3<enter>\" \"copy mail to $2\" $MARKER" >> "$accdir/$idnum-$fulladdr.muttrc" ;}
  190. setBox() { toappend="$toappend
  191. set $1 = \"+$2\" $MARKER" ;}
  192. getboxes() { [ -n "${force+x}" ] && mailboxes="INBOX
  193. Drafts
  194. Junk
  195. Trash
  196. Sent
  197. Archive" && return 0
  198. if mailboxes="$(mbsync -l "$fulladdr" | sed 's/\//./')" >/dev/null 2>&1 && [ -n "$mailboxes" ]; then
  199. [ -n "${online+x}" ] && sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" ; rm -f "$mbsyncrc"bu
  200. return 0
  201. else
  202. echo "$mailboxes"
  203. 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"
  204. return 1
  205. fi ;}
  206. finalize() { echo "$mailboxes" | xargs -I {} mkdir -p "$maildir/$fulladdr/{}/cur" "$maildir/$fulladdr/{}/tmp" "$maildir/$fulladdr/{}/new"
  207. sed -ibu "/$MARKER/d" "$accdir/$idnum-$fulladdr.muttrc" ; rm -f "$accdir/$idnum-$fulladdr.muttrcbu"
  208. toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/" | paste -sd ' ' )"
  209. for x in $mailboxes; do
  210. case $x in
  211. *[Ii][Nn][Bb][Oo][Xx]*) formatShortcut i inbox "$x"; setBox spoolfile "$x" ;;
  212. *[Ss][Ee][Nn][Tt]*) setBox record "$x"; formatShortcut s sent "$x" ;;
  213. *[Dd][Rr][Aa][Ff][Tt][Ss]*) setBox postponed "$x"; formatShortcut d drafts "$x" ;;
  214. *[Tt][Rr][Aa][Ss][Hh]*) formatShortcut t trash "$x"; setBox trash "$x" ;;
  215. *[Jj][Uu][Nn][Kk]*) formatShortcut j junk "$x" ;;
  216. *[Aa][Rr][Cc][Hh][Ii][Vv][Ee]*) formatShortcut a archive "$x" ;;
  217. *[Ss][Pp][Aa][Mm]*) formatShortcut S spam "$x" ;;
  218. esac
  219. done
  220. echo "$toappend" >> "$accdir/$idnum-$fulladdr.muttrc"
  221. [ -z "${online+x}" ] && printf "\033[33mYou should now be able to run \`\033[32mmw -y %s\033[33m\` to begin to download your mail.\033[0m\\n" "$fulladdr"
  222. command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" > "$HOME/.urlview"
  223. return 0 ;}
  224. syncwrapper() { mbsync "${1:--a}" &
  225. ( kill -46 "$(pidof "${STATUSBAR:-dwmblocks}")" >/dev/null 2>&1 ) 2>/dev/null
  226. wait
  227. ( kill -46 "$(pidof "${STATUSBAR:-dwmblocks}")" >/dev/null 2>&1 ) 2>/dev/null
  228. notmuch new ;}
  229. notmuchauto() { \
  230. [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
  231. [ -f "$NOTMUCH_CONFIG" ] && return 0
  232. nmbasic="[database]
  233. path=$maildir
  234. [user]
  235. name=$realname
  236. primary_email=$fulladdr
  237. [new]
  238. tags=unread;inbox;
  239. ignore=.mbsyncstate;.uidvalidity
  240. [search]
  241. exclude_tags=deleted;spam;
  242. [maildir]
  243. synchronize_flags=true
  244. [crypto]
  245. gpg_path=$GPG"
  246. echo "$nmbasic" > "$NOTMUCH_CONFIG" ;}
  247. setact() { if [ -n "${action+x}" ] && [ "$action" != "$1" ]; then
  248. echo "Running $1 with $action..."
  249. echo "Incompatible options given. Only one action may be specified per run."
  250. return 1
  251. else
  252. action="$1"
  253. fi; }
  254. trap 'echo -e "\033[0m\n"; exit' INT ABRT
  255. while getopts "fplhodYD:y:i:I:s:S:u:a:n:x:m:" o; do case "${o}" in
  256. l) setact list || exit 1 ;;
  257. d) setact delete || exit 1 ;;
  258. D) setact delete || exit 1 ; fulladdr="$OPTARG" ;;
  259. y) setact sync || exit 1 ; fulladdr="$OPTARG" ;;
  260. Y) setact sync || exit 1 ;;
  261. a) setact add || exit 1 ; fulladdr="$OPTARG" ;;
  262. i) setact add || exit 1 ; imap="$OPTARG" ;;
  263. I) setact add || exit 1 ; iport="$OPTARG" ;;
  264. s) setact add || exit 1 ; smtp="$OPTARG" ;;
  265. S) setact add || exit 1 ; sport="$OPTARG" ;;
  266. u) setact add || exit 1 ; login="$OPTARG" ;;
  267. n) setact add || exit 1 ; realname="$OPTARG" ;;
  268. m) setact add || exit 1 ; maxmes="$OPTARG" ;;
  269. o) setact add || exit 1 ; online=True ;;
  270. f) setact add || exit 1 ; force=True ;;
  271. x) setact add || exit 1 ; password="$OPTARG" ;;
  272. p) echo "NOTE: Protonmail users must install and configure Protonmail Bridge first for the first sync to work."
  273. imap="127.0.0.1"
  274. iport="1143"
  275. smtp="127.0.0.1"
  276. sport="1025"
  277. ssltype="None"
  278. tlsline="tls_fingerprint $(msmtp --serverinfo --host=$smtp --port=$sport --tls --tls-certcheck=off | awk '/SHA256:/ {print $2}')"
  279. setact add || exit 1
  280. ;;
  281. *) cat << EOF
  282. mw: mutt-wizard, auto-configure email accounts for mutt
  283. including downloadable mail with \`isync\`.
  284. Main actions:
  285. -a your@email.com Add an email address
  286. -l List email addresses configured
  287. -d Remove an already added address
  288. -D your@email.com Force remove account without confirmation
  289. -y your@email.com Sync mail for account by name
  290. -Y Sync mail for all accounts
  291. Options allowed with -a:
  292. -u Account login name if not full address
  293. -n "Real name" to be on the email account
  294. -i IMAP server address
  295. -I IMAP server port
  296. -s SMTP server address
  297. -S SMTP server port
  298. -x Password for account (recommended to be in double quotes)
  299. -p Install for a Protonmail account.
  300. -o Configure address, but keep mail online.
  301. -b Assume typical English mailboxes without attempting log-on.
  302. NOTE: Once at least one account is added, you can run
  303. \`mbsync -a\` to begin downloading mail.
  304. To change an account's password, run \`pass edit ${pass_prefix}your@email.com\`.
  305. EOF
  306. exit 1
  307. ;;
  308. esac done
  309. ! command -v mbsync >/dev/null && [ -z "${force+x}" ] && printf "\`mbsync (isync package)\` must be installed to run mutt-wizard.\\n" && exit
  310. case "$action" in
  311. list) list ;;
  312. add) askinfo && getprofiles && writeinfo && getboxes && finalize || { delete ; exit 1 ;} ;;
  313. delete) delete $fulladdr ;;
  314. sync) syncwrapper $fulladdr ;;
  315. esac