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

mw 13 KiB

4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
5年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
5年前
4年前
4年前
4年前
4年前
4年前
4年前
4年前
5年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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 1
  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. unalternates *
  89. "
  90. else
  91. mutt_profile="# vim: filetype=neomuttrc
  92. # muttrc file for account $fulladdr
  93. set realname = \"$realname\"
  94. set from = \"$fulladdr\"
  95. set sendmail = \"msmtp -a $fulladdr\"
  96. alias me $realname <$fulladdr>
  97. set folder = \"imaps://$login@$imap:${iport:-993}\"
  98. set imap_user = \"$login\"
  99. set header_cache = $cachedir/$fulladdr/headers
  100. set message_cachedir = $cachedir/$fulladdr/bodies
  101. set imap_pass = \"\`pass $pass_prefix$fulladdr\`\"
  102. set mbox_type = Maildir
  103. set ssl_starttls = yes
  104. set ssl_force_tls = yes
  105. bind index,pager gg noop
  106. bind index,pager g noop
  107. bind index,pager M noop
  108. bind index,pager C noop
  109. bind index gg first-entry
  110. unmailboxes *
  111. "
  112. fi
  113. }
  114. parsedomains(){ serverinfo="$(grep "^${fulladdr#*@}" "$muttshare/domains.csv" 2>/dev/null)"
  115. [ -z "$serverinfo" ] && serverinfo="$(grep "$(echo "${fulladdr#*@}" | sed "s/\.[^\.]*$/\.\\\*/")" "$muttshare/domains.csv" 2>/dev/null)"
  116. IFS=, read -r service imapsugg iportsugg smtpsugg sportsugg <<EOF
  117. $serverinfo
  118. EOF
  119. imap="${imap:-$imapsugg}"
  120. smtp="${smtp:-$smtpsugg}"
  121. sport="${sport:-$sportsugg}"
  122. iport="${iport:-$iportsugg}"
  123. }
  124. delete() { if [ -z "${fulladdr+x}" ]; then
  125. echo "Select the account your would like to delete (by number):"
  126. list
  127. read -r input
  128. match="^$input:"
  129. else
  130. match=" $fulladdr$"
  131. getaccounts
  132. fi
  133. fulladdr="$(echo "$accounts" | grep "$match" | cut -f2 -d' ')"
  134. [ -z "$fulladdr" ] && echo "Invalid account name given." && return 1
  135. sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" ; rm -f "$mbsyncrc"bu
  136. rm -rf "${cachedir:?}/${fulladdr:?}" "$accdir/"[1-9]"-$fulladdr.muttrc"
  137. sed -ibu "/[0-9]-$fulladdr.muttrc/d" "$muttrc" ; rm -f "$muttrc"bu
  138. sed -ibu "/account $fulladdr/,/^\(\s*$\|account\)/d" "$msmtprc"; rm -f "$msmtprc"bu
  139. pass rm -f "$pass_prefix$fulladdr" >/dev/null 2>&1
  140. }
  141. askinfo() { \
  142. [ -z "$fulladdr" ] && echo "Give the full email address to add:" &&
  143. read -r fulladdr
  144. while ! echo "$fulladdr" | grep -qE "$emailre"; do
  145. echo "\`$fulladdr\` is not a valid email address. Please retype the address:"
  146. read -r fulladdr
  147. done
  148. grep -q "Channel\s*$fulladdr$" "$mbsyncrc" &&
  149. { echo "$fulladdr has already been added" && exit 1 ;}
  150. { [ -z "$imap" ] || [ -z "$smtp" ] ;} && parsedomains
  151. [ -z "$imap" ] && echo "Give your email server's IMAP address (excluding the port number):" &&
  152. read -r imap
  153. [ -z "$smtp" ] && echo "Give your email server's SMTP address (excluding the port number):" &&
  154. read -r smtp
  155. [ "$sport" = 465 ] && tlsline="tls_starttls off"
  156. [ -z "$realname" ] && echo "Give the name you would like to be identified by on the email account:" &&
  157. read -r realname
  158. login="${login:-$fulladdr}"
  159. if [ -n "${password+x}" ]; then
  160. createpass
  161. else
  162. getpass
  163. fi
  164. }
  165. createpass() { echo "$password" > "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr"
  166. "$GPG" -qer "$(cat "$PASSWORD_STORE_DIR/.gpg-id")" "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr"
  167. rm -f "$PASSWORD_STORE_DIR/$pass_prefix$fulladdr" ;}
  168. writeinfo() { mkdir -p "$muttdir" "$accdir" "$cachedir/$fulladdr/bodies" "${XDG_CONFIG_HOME:-$HOME/.config}/msmtp" "$maildir/$fulladdr"
  169. # Get accounts and find the first missing account number (max. 9).
  170. getaccounts; for x in $(seq 1 9); do echo "$accounts" | grep -q "$x" || { export idnum="$x"; break ;}; done
  171. # Configure msmtprc for sending mail.
  172. [ ! -f "$msmtprc" ] && echo "$msmtp_header" > "$msmtprc"
  173. echo "$msmtp_profile" >> "$msmtprc"
  174. # On Ubuntu/Debian, a link is needed since they use an older version.
  175. command -V apt-get >/dev/null 2>&1 && ln -s "$msmtprc" "$HOME/.msmtprc" 2>/dev/null
  176. # Create the mbsync config file.
  177. mkdir -p "${mbsyncrc%/*}"
  178. echo "$mbsync_profile" >> "$mbsyncrc"
  179. # Create a muttrc for viewing mail.
  180. echo "$mutt_profile" > "$accdir/$idnum-$fulladdr.muttrc"
  181. [ ! -f "$muttrc" ] && echo "# vim: filetype=neomuttrc" > "$muttrc"
  182. ! grep -q "^source.*mutt-wizard.muttrc" "$muttrc" && echo "source $mwconfig $marker" >> "$muttrc"
  183. ! grep "^source.*.muttrc" "$muttrc" | grep -qv "$mwconfig" && echo "source $accdir/$idnum-$fulladdr.muttrc $marker" >> "$muttrc"
  184. 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"
  185. notmuchauto # Create a notmuch config file if not present already.
  186. }
  187. getpass() { while : ; do pass rm -f "$pass_prefix$fulladdr" >/dev/null 2>&1
  188. pass insert "$pass_prefix$fulladdr" && break; done ;}
  189. formatShortcut() { toappend="$toappend
  190. macro index,pager g$1 \"<change-folder>=$3<enter>\" \"go to $2\" $marker
  191. macro index,pager M$1 \";<save-message>=$3<enter>\" \"move mail to $2\" $marker
  192. macro index,pager C$1 \";<copy-message>=$3<enter>\" \"copy mail to $2\" $marker" >> "$accdir/$idnum-$fulladdr.muttrc" ;}
  193. setBox() { toappend="$toappend
  194. set $1 = \"+$2\" $marker" ;}
  195. getboxes() { [ -n "${force+x}" ] && mailboxes="INBOX
  196. Drafts
  197. Junk
  198. Trash
  199. Sent
  200. Archive" && return 0
  201. if mailboxes="$(mbsync -l "$fulladdr" | sed 's/\//./')" >/dev/null 2>&1 && [ -n "$mailboxes" ]; then
  202. [ -n "${online+x}" ] && sed -ibu "/IMAPStore $fulladdr-remote$/,/# End profile/d" "$mbsyncrc" ; rm -f "$mbsyncrc"bu
  203. return 0
  204. else
  205. echo "$mailboxes"
  206. 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"
  207. return 1
  208. fi ;}
  209. finalize() { echo "$mailboxes" | xargs -I {} mkdir -p "$maildir/$fulladdr/{}/cur" "$maildir/$fulladdr/{}/tmp" "$maildir/$fulladdr/{}/new"
  210. sed -ibu "/$marker/d" "$accdir/$idnum-$fulladdr.muttrc" ; rm -f "$accdir/$idnum-$fulladdr.muttrcbu"
  211. toappend="mailboxes $(echo "$mailboxes" | sed "s/^/\"=/;s/$/\"/" | paste -sd ' ' - )"
  212. for x in $mailboxes; do
  213. case "$x" in
  214. *[Ss][Ee][Nn][Tt]*) setBox record "$x"; formatShortcut s sent "$x" ;;
  215. *[Dd][Rr][Aa][Ff][Tt][Ss]*) setBox postponed "$x"; formatShortcut d drafts "$x" ;;
  216. *[Tt][Rr][Aa][Ss][Hh]*) formatShortcut t trash "$x"; setBox trash "$x" ;;
  217. *[Jj][Uu][Nn][Kk]*) formatShortcut j junk "$x" ;;
  218. *[Aa][Rr][Cc][Hh][Ii][Vv][Ee]*) formatShortcut a archive "$x" ;;
  219. *[Ss][Pp][Aa][Mm]*) formatShortcut S spam "$x" ;;
  220. *[Ii][Nn][Bb][Oo][Xx]*) formatShortcut i inbox "$x"; setBox spoolfile "$x" ;;
  221. esac
  222. done
  223. echo "$toappend" >> "$accdir/$idnum-$fulladdr.muttrc"
  224. [ -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"
  225. command -V urlview >/dev/null 2>&1 && [ ! -f "$HOME/.urlview" ] && echo "COMMAND \$BROWSER" > "$HOME/.urlview"
  226. return 0 ;}
  227. notmuchauto() { \
  228. [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
  229. [ -f "$NOTMUCH_CONFIG" ] && return 0
  230. nmbasic="[database]
  231. path=$maildir
  232. [user]
  233. name=$realname
  234. primary_email=$fulladdr
  235. [new]
  236. tags=unread;inbox;
  237. ignore=.mbsyncstate;.uidvalidity
  238. [search]
  239. exclude_tags=deleted;spam;
  240. [maildir]
  241. synchronize_flags=true
  242. [crypto]
  243. gpg_path=$GPG"
  244. echo "$nmbasic" > "$NOTMUCH_CONFIG" ;}
  245. togglecron() { cron="$(mktemp)"
  246. crontab -l > "$cron"
  247. if grep -q mailsync "$cron"; then
  248. echo "Removing automatic mailsync..."
  249. sed -ibu /mailsync/d "$cron"; rm -f "$cron"bu
  250. else
  251. echo "Adding automatic mailsync every ${cronmin:-10} minutes..."
  252. echo "*/${cronmin-10} * * * * /usr/local/bin/mailsync" >> "$cron"
  253. fi &&
  254. crontab "$cron"; rm -f "$cron" ;}
  255. setact() { if [ -n "${action+x}" ] && [ "$action" != "$1" ]; then
  256. echo "Running $1 with $action..."
  257. echo "Incompatible options given. Only one action may be specified per run."
  258. return 1
  259. else
  260. action="$1"
  261. fi; }
  262. trap 'echo -e "\033[0m\n"; exit' INT ABRT
  263. while getopts "fplhodTYD:y:i:I:s:S:u:a:n:x:m:t:" o; do case "${o}" in
  264. l) setact list || exit 1 ;;
  265. d) setact delete || exit 1 ;;
  266. D) setact delete || exit 1 ; fulladdr="$OPTARG" ;;
  267. y) setact sync || exit 1 ; fulladdr="$OPTARG" ;;
  268. Y) setact sync || exit 1 ;;
  269. a) setact add || exit 1 ; fulladdr="$OPTARG" ;;
  270. i) setact add || exit 1 ; imap="$OPTARG" ;;
  271. I) setact add || exit 1 ; iport="$OPTARG" ;;
  272. s) setact add || exit 1 ; smtp="$OPTARG" ;;
  273. S) setact add || exit 1 ; sport="$OPTARG" ;;
  274. u) setact add || exit 1 ; login="$OPTARG" ;;
  275. n) setact add || exit 1 ; realname="$OPTARG" ;;
  276. m) setact add || exit 1 ; maxmes="$OPTARG" ;;
  277. o) setact add || exit 1 ; online=True ;;
  278. f) setact add || exit 1 ; force=True ;;
  279. x) setact add || exit 1 ; password="$OPTARG" ;;
  280. t) setact toggle || exit 1 ; cronmin="$OPTARG" ;;
  281. T) setact toggle || exit 1 ;;
  282. p) echo "NOTE: Protonmail users must install and configure Protonmail Bridge first for the first sync to work."
  283. imap="127.0.0.1"
  284. iport="1143"
  285. smtp="127.0.0.1"
  286. sport="1025"
  287. ssltype="None"
  288. tlsline="tls_fingerprint $(msmtp --serverinfo --host=$smtp --port=$sport --tls --tls-certcheck=off | awk '/SHA256:/ {print $2}')"
  289. setact add || exit 1
  290. ;;
  291. *) cat << EOF
  292. mw: mutt-wizard, auto-configure email accounts for mutt
  293. including downloadable mail with \`isync\`.
  294. Main actions:
  295. -a your@email.com Add an email address
  296. -l List email addresses configured
  297. -d Remove an already added address
  298. -D your@email.com Force remove account without confirmation
  299. -y your@email.com Sync mail for account by name
  300. -Y Sync mail for all accounts
  301. -t number Toggle automatic mailsync every <number> minutes
  302. -T Toggle automatic mailsync
  303. Options allowed with -a:
  304. -u Account login name if not full address
  305. -n "Real name" to be on the email account
  306. -i IMAP server address
  307. -I IMAP server port
  308. -s SMTP server address
  309. -S SMTP server port
  310. -x Password for account (recommended to be in double quotes)
  311. -p Install for a Protonmail account.
  312. -o Configure address, but keep mail online.
  313. -f Assume typical English mailboxes without attempting log-on.
  314. NOTE: Once at least one account is added, you can run
  315. \`mbsync -a\` to begin downloading mail.
  316. To change an account's password, run \`pass edit ${pass_prefix}your@email.com\`.
  317. EOF
  318. exit 1
  319. ;;
  320. esac done
  321. ! command -v mbsync >/dev/null && [ -z "${force+x}" ] && printf "\`mbsync (isync package)\` must be installed to run mutt-wizard.\\n" && exit 1
  322. case "$action" in
  323. list) list ;;
  324. add) askinfo && getprofiles && writeinfo && getboxes && finalize || { delete ; exit 1 ;} ;;
  325. delete) delete $fulladdr ;;
  326. sync) mailsync $fulladdr ;;
  327. toggle) togglecron ;;
  328. esac