Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

429 строки
15 KiB

  1. #!/bin/sh
  2. if [ "$#" -gt 1 ]; then
  3. echo "To many arguments. You will be asked."
  4. exit
  5. fi
  6. if [ -z "$prefix" ]; then
  7. case "$(uname)" in
  8. Linux) prefix="/usr" ;;
  9. *) prefix="/usr/local" ;;
  10. esac
  11. fi
  12. command -V gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
  13. [ -z "$PASSWORD_STORE_DIR" ] && PASSWORD_STORE_DIR="$HOME/.password-store"
  14. [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] &&
  15. "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || {
  16. printf "\`pass\` must be installed and initialized to encrypt passwords.\\nBe sure it is installed and run \`pass init <yourgpgemail>\`.\\nIf you don't have a GPG public private key pair, run \`$GPG --full-gen-key\` first.\\n"
  17. exit
  18. }
  19. ! command -v "$prefix/bin/mbsync" >/dev/null && printf "\`mbsync\` must be installed to run mutt-wizard.\\n" && exit
  20. ! command -v "$prefix/bin/msmtp" >/dev/null && printf "\`msmtp\` must be installed.\\n" && exit
  21. ! ( command -v mutt >/dev/null || command -v neomutt >/dev/null ) && printf "\`mutt\` must be installed.\\n" && exit
  22. mwconfigdir=${XDG_CONFIG_HOME:-$HOME/.config}
  23. # Main mutt config location
  24. mwmuttdir="$mwconfigdir/mutt"
  25. # Directory for account settings
  26. mwaccmuttdir="$mwmuttdir/accounts"
  27. # Location of mail storage
  28. mwmaildir="${MAILDIR:-${XDG_DATA_HOME:-$HOME/.local/share}/mail}"
  29. # Regex to confirm valid email address
  30. mwemailre=".\+@.\+\\..\+"
  31. mwshare="$prefix/share/mutt-wizard"
  32. if [ -n "$XDG_CONFIG_HOME" ]; then
  33. mwmbsyncrc="$mwconfigdir/isync/mbsyncrc"
  34. else
  35. mwmbsyncrc="$HOME/.mbsyncrc"
  36. fi
  37. mwsharerc="$mwshare/mutt-wizard.muttrc"
  38. mwcachedir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard"
  39. mwmuttrc="$mwmuttdir/muttrc"
  40. mwmsmtprc="$mwconfigdir/msmtp/config"
  41. mwssltype="IMAPS"
  42. mbsyncbin="$prefix/bin/mbsync -c $mwmbsyncrc"
  43. msmtpbin="$prefix/bin/msmtp"
  44. takemwaddr(){
  45. mwacc="$mwaddr" # let the user always just deal with his email
  46. mwaccmutt="${mwaddr//[.@]/_}" # but mutt would not show it with an @ or .
  47. mwacccachedir=$mwcachedir/${mwaddr//[.@]/_} # @ cannot stay because of mutt, . could
  48. mwaccmaildir="$mwmaildir/$mwaccmutt" # folder name as shown by mutt and opens with gf in vim
  49. }
  50. 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/"
  51. do
  52. [ -f "$x" ] && sslcert="$x" && break
  53. done || { echo "CA Certificate not found. Please install one or link it to /etc/ssl/certs/ca-certificates.crt" && exit 1 ;}
  54. getaccounts() {
  55. accounts="$(find "$mwaccmuttdir" -type f | grep -o "[0-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc//" | sort -n)"
  56. }
  57. mwlist() {
  58. getaccounts && [ -n "$accounts" ] && echo "$accounts"
  59. }
  60. mwadd() {
  61. asktype && askinfo && tryconnect && finalize || mwdelete
  62. }
  63. getprofiles() {
  64. unset msmtp_header msmtp_profile mutt_profile mbsync_profile
  65. printf "Creating profiles for \`%s\`..." "$mwaddr"
  66. msmtp_header="defaults
  67. auth on
  68. tls on
  69. tls_trust_file $sslcert
  70. logfile ${XDG_LOG_HOME:-$HOME}/msmtp.log
  71. "
  72. msmtp_profile="account $mwacc
  73. host $mwsmtp
  74. port $mwsport
  75. from $mwaddr
  76. user $mwlogin
  77. passwordeval \"pass $mwpass\"
  78. $starttlsoff
  79. "
  80. mbsync_profile="IMAPStore $mwacc-remote
  81. Host $mwimap
  82. Port $mwiport
  83. User $mwlogin
  84. PassCmd \"pass $mwpass\"
  85. SSLType $mwssltype
  86. CertificateFile $sslcert
  87. MaildirStore $mwacc-local
  88. Subfolders Verbatim
  89. Path $mwaccmaildir/
  90. Inbox $mwaccmaildir/INBOX
  91. Flatten .
  92. Channel $mwacc
  93. Expunge Both
  94. Master :$mwacc-remote:
  95. Slave :$mwacc-local:
  96. Patterns * !\"[Gmail]/All Mail\"
  97. Create Both
  98. SyncState *
  99. MaxMessages 0
  100. # End profile
  101. "
  102. if [ "$mwtype" = "offline" ]; then
  103. mutt_profile="# vim: filetype=neomuttrc
  104. # muttrc file for account $mwaddr
  105. set realname = \"$mwname\"
  106. set from = \"$mwaddr\"
  107. set sendmail = \"$msmtpbin -a $mwacc\"
  108. alias me $mwname <$mwaddr>
  109. set folder = \"$mwaccmaildir\"
  110. set mbox_type = Maildir
  111. macro index gm \"<shell-escape>mailsync $mwacc<enter>\" \"sync mail $mwaddr\"
  112. unmailboxes *
  113. "
  114. else
  115. mutt_profile="# vim: filetype=neomuttrc
  116. # muttrc file for account $mwaddr
  117. set realname = \"$mwname\"
  118. set from = \"$mwaddr\"
  119. set sendmail = \"$msmtpbin -a $mwacc\"
  120. alias me $mwname <$mwaddr>
  121. set folder = \"imaps://$mwaddr@$mwimap:$mwiport\"
  122. set header_cache = \"$mwacccachedir\"
  123. set message_cachedir = \$header_cache
  124. set imap_user = \"$mwlogin\"
  125. set imap_pass = \"\`pass $mwpass\`\"
  126. account-hook \$folder 'set imap_user=\"$mwlogin\" imap_pass=\"\`pass $mwpass\`\"'
  127. set mbox_type = Maildir
  128. set ssl_starttls = yes
  129. set ssl_force_tls = yes
  130. unmailboxes *
  131. "
  132. fi
  133. printf "DONE.\\n"
  134. }
  135. askinfo() {
  136. if [ -z "$mwaddr" ]; then
  137. printf "Type the \033[31memail address\033[0m\\n\t\033[36m"
  138. read -r mwaddr
  139. printf "\033[0m"
  140. while ! echo "$mwaddr" | grep "$mwemailre" >/dev/null; do
  141. printf "That is not a valid \033[31memail address\033[0m, please retype\\n\t\033[36m"
  142. read -r mwaddr
  143. printf "\033[0m"
  144. done
  145. fi
  146. mwdomain="$(echo "$mwaddr" | sed "s/.*@//")"
  147. printf "\\nSearching for \033[32m%s\033[0m in \033[34m\`domains.csv\`\033[0m..." "$mwdomain"
  148. mwserverinfo="$(grep "^$mwdomain" "$mwshare/domains.csv" 2>/dev/null)"
  149. if [ -z "$mwserverinfo" ]; then
  150. printf "Your email domain is not known to mutt-wizard.\\nType in your settings.\\nUsually you find them by an internet search.\\n"
  151. printf "Type the IMAP server (excluding the port number)\\n\033[36m\t"
  152. read -r mwimap
  153. printf "\033[0mIMAP port number (usually 993)\\n\033[36m\t"
  154. read -r mwiport
  155. printf "\033[0mSMTP server (excluding the port number)\\n\033[36m\t"
  156. read -r mwsmtp
  157. printf "\033[0mSMTP port number (usually 587 or 465)\\n\033[36m\t"
  158. read -r mwsport
  159. printf "\033[0m\\nIf you want, you can copy the line below and add it to the \`domains.csv\` file on Github, for others.\\n\\n%s,%s,%s,%s,%s\\n\\nBut be sure the setting works, first! ;-)\\n" "$mwdomain" "$mwimap" "$mwiport" "$mwsmtp" "$mwsport"
  160. else
  161. IFS=, read -r mwservice mwimap mwiport mwsmtp mwsport <<EOF
  162. $mwserverinfo
  163. EOF
  164. printf "\\n\033[3;33mCongrats!\033[0m Server info is known, so you don't need to look it up!\\n\t\033[1mIMAP server\033[0m: %s\\n\t\033[1mIMAP port\033[0m: %s\\n\t\033[1mSMTP server\033[0m: %s\\n\t\033[1mSMTP port\033[0m: %s\\n" "$mwimap" "$mwiport" "$mwsmtp" "$mwsport"
  165. case "$mwservice" in
  166. gmail.com) printf "\033[31mGmail: \"less secure\" must be enabled before you continue.\\nDo it now, if you have not done it already:\\nhttps://support.google.com/accounts/answer/6010255\\n\033[0m" ;;
  167. protonmail.ch|protonmail.com|pm.me) printf "\033[31mProtonmail: Users must install and configure Protonmail Bridge for the sync to work:\\nhttps://protonmail.com/bridge/\\n\033[0m" && ssltype="None" ;;
  168. esac
  169. [ "$mwsport" = 465 ] && starttlsoff="tls_starttls off"
  170. fi
  171. if [ -z "$mwname" ]; then
  172. printf "Name to associate to email.\\n\t"
  173. read -r mwname
  174. fi
  175. takemwaddr
  176. if [ -z "$mwlogin" ]; then
  177. printf "Type your account username if different from your email address.\\n\033[34mFor most accounts you can probably leave this blank.\033[0m\\n\tLogin(?): \033[36m"
  178. read -r mwlogin
  179. printf "\033[0m"
  180. [ -z "$mwlogin" ] && mwlogin="$mwaddr"
  181. fi
  182. # if the user has a pass entry he could provide it via mwpass
  183. if [ -z "$mwpass" ]; then
  184. mwpass=mutt-wizard-$mwaddr
  185. getpass
  186. fi
  187. getprofiles
  188. mkdir -p "$mwmuttdir" "$mwaccmuttdir" "$mwconfigdir/msmtp" "${mwmbsyncrc%/*}"
  189. [ ! -f "$mwmsmtprc" ] && echo "$msmtp_header" > "$mwmsmtprc"
  190. echo "$msmtp_profile" >> "$mwmsmtprc"
  191. case "$mwservice" in
  192. protonmail.ch|protonmail.com|pm.me) protonfinger || return 1 ;;
  193. esac
  194. echo "$mbsync_profile" >> "$mwmbsyncrc"
  195. # new idnum = first one missing
  196. getaccounts
  197. for x in $(seq 1 9); do echo "$accounts" | grep "$x": >/dev/null 2>&1 || { export idnum="$x"; break ;}; done
  198. mwaccmuttrc="$mwaccmuttdir/$idnum-$mwacc.muttrc"
  199. echo "$mutt_profile" > "$mwaccmuttrc"
  200. [ ! -f "$mwmuttrc" ] && echo "# vim: filetype=neomuttrc" > "$mwmuttrc" && echo "muttrc created."
  201. ! grep "source.*mutt-wizard.muttrc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc"
  202. if [ "$mwtype" = "offline" ]; then
  203. ! grep "^macro .* gM .*" "$mwmuttrc" >/dev/null && echo "macro index gM '<shell-escape>mailsync -Va<enter>' \"sync all mail\" # mw-autogenerated" >> "$mwmuttrc"
  204. fi
  205. ! grep "^source.*$mwaccmuttrc" "$mwmuttrc" >/dev/null && echo "source $mwaccmuttrc # mw-autogenerated" >> "$mwmuttrc"
  206. return 0
  207. }
  208. protonfinger() {
  209. printf "Getting Protonmail bridge fingerprint...\\n"
  210. fingerprint="$($msmtpbin --serverinfo --host=127.0.0.1 --port=1025 --tls --tls-certcheck=off)" || return 1
  211. sed -i "s/account $mwacc/&\ntls_trust_file\ntls_fingerprint $fingerprint/" "$mwmsmtprc"
  212. }
  213. getpass() {
  214. while : ; do pass rm -f "$mwpass" >/dev/null 2>&1
  215. pass insert "$mwpass" && break; done ;}
  216. tryconnect() {
  217. if [ -z "$mailboxes" ]; then
  218. if [ ! -d "$mwaccmaildir" ]; then
  219. mwaccmaildirWasThere="NO" # we need to remove again for "online"
  220. mkdir -p "$mwaccmaildir"
  221. fi
  222. mailboxes="$($mbsyncbin -l $mwacc | sed 's/\//./')" >/dev/null 2>&1
  223. fi
  224. if [ -n "$mailboxes" ]; then
  225. spoolfile=$(echo "$mailboxes" | grep -i -m 1 inbox | sed -ne 's/.*/+\0/p')
  226. [ -z "$spoolfile" ] && return 1
  227. #make directories
  228. printf "\033[32mMailboxes detected.\033[0m\\n"
  229. echo "$mailboxes" | xargs -I {} mkdir -p "$mwaccmaildir/{}/"{cur,new,tmp}
  230. record=$(echo "$mailboxes" | grep -i -m 1 sent | sed -ne 's/.*/+\0/p')
  231. [ -z "$record" ] && mkdir -p "$mwaccmaildir/Sent/"{cur,new,tmp} && record="Sent"
  232. postponed=$(echo "$mailboxes" | grep -i -m 1 draft | sed -ne 's/.*/+\0/p')
  233. [ -z "$postponed" ] && mkdir -p "$mwaccmaildir/Drafts/"{cur,new,tmp} && postponed="Drafts"
  234. trash=$(echo "$mailboxes" | grep -i -m 1 trash | sed -ne 's/.*/+\0/p')
  235. [ -z "$trash" ] && mkdir -p "$mwaccmaildir/Trash/"{cur,new,tmp} && trash="Trash"
  236. return 0
  237. else
  238. 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"
  239. return 1
  240. fi
  241. }
  242. finalize() { # new mwaccmuttrc
  243. idnum=${mwaccmuttrc%%-*}
  244. idnum=${idnum##*/}
  245. boxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")"
  246. if [[ "$boxes" =~ ^[[:space:]]*$ ]]; then
  247. printf "\033[31mNo local mailboxes have been detected for %s.\033[0m\\nThis means that mbsync has not been successfully run.\\nRun mbsync, and if it has an error, be sure to check your password and server settings manually if needbe.\\n" "$mwacc"
  248. return
  249. fi
  250. mwaccmutt="${email//[.@]/_}"
  251. muttsync=$(printf '<sync-mailbox><enter-command>source %s<enter><change-folder>!<enter>;<check-stats>' $mwaccmuttrc)
  252. cat >> "$mwaccmuttrc" <<EOF
  253. set spoolfile = "$spoolfile"
  254. set record = "$record"
  255. set postponed = "$postponed"
  256. set trash = "$trash"
  257. folder-hook \$folder '$muttsync'
  258. macro index,pager i$idnum '$muttsync' "switch to $email"
  259. mailboxes =$mwaccmutt ===================== $(echo "$boxes" | sed -e "s/ //g;s/.*/\"=\0\"/g" | tr "\n" " ")
  260. EOF
  261. for eqbox in $boxes; do
  262. box=${eqbox##*/}
  263. box=${box##*.}
  264. boxi=${box::2}
  265. boxi=${boxi,,}
  266. cat >> $mwaccmuttrc <<EOF
  267. macro index,pager i$boxi "<change-folder>=$eqbox<enter>" "go to $box"
  268. macro index,pager M$boxi "<save-message>=$eqbox<enter>" "move mail to $box"
  269. macro index,pager C$boxi "<copy-message>=$eqbox<enter>" "copy mail to $box"
  270. EOF
  271. done
  272. if [ "$mwtype" = "offline" ]; then
  273. notmuchauto
  274. printf "All done.\\n\033[33mYou can now run \`\033[32mmailsync [%s]\033[33m\` to sync your mail.\033[0m\\n" "$mwacc"
  275. else
  276. mkdir -p "$mwacccachedir"
  277. sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc"
  278. [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir/"
  279. fi
  280. return 0
  281. }
  282. confirm() {
  283. printf "[y/N]: Do you want to %s?\\n\t" "$@" && read -r input && ! echo "$input" | grep -i "^y$\|^yes$" >/dev/null && printf "That doesn't seem like a yes to me.\\n\\n" && return 1
  284. return 0 ;
  285. }
  286. mwpick() {
  287. printf "Select an accounts to %s:\\n" "$1"
  288. mwlist
  289. read -r input
  290. [ -z "$input" ] && return 1
  291. mwaddr="$(echo "$accounts" | grep "$input": | awk '{print $2}')"
  292. takemwaddr
  293. [ -z "$mwacc" ] && printf "Invalid response." && return 1
  294. return 0 ;
  295. }
  296. mwdelete() {
  297. sed -i "/IMAPStore $mwacc-remote$/,/# End profile/d" "$mwmbsyncrc"
  298. rm -rf "$mwacccachedir"
  299. rm -rf "$mwaccmuttdir/"[1-9]"-$mwacc.muttrc"
  300. sed -i "/[0-9]-$mwacc.muttrc/d" "$mwmuttrc"
  301. sed -i "/account $mwacc/,/^\(\s*$\|account\)/d" "$mwmsmtprc"
  302. }
  303. mwcron() {
  304. ! pgrep cron >/dev/null && echo "No cron manager running. Install/enable one and then select this option again." && return 1
  305. if crontab -l | grep mailsync >/dev/null; then
  306. echo "Active mail sync cronjob detected. Do you want to remove it?"
  307. printf "\033[36m\t"
  308. read -r rmyn
  309. printf "\033[0m"
  310. echo "$rmyn" | grep -i "^y\(es\)*$" >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null && echo "Mail sync turned off."
  311. else
  312. echo "How many minutes between each mail sync?"
  313. printf "\033[36m\t"
  314. read -r minnum
  315. printf "\033[0m"
  316. while ! echo "$minnum" | grep "^[0-9]\+$" >/dev/null; do
  317. printf "That doesn't look like a number. How many minutes between each mail sync?\\n\033[36m\t"
  318. read -r minnum
  319. printf "\033[0m"
  320. done
  321. (crontab -l; echo "*/$minnum * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; export DISPLAY=:0; $(type mailsync | cut -d' ' -f3)") | crontab - &&
  322. echo "Cronjob added. Mail will sync every $minnum minutes. Be sure you have your cron manager running."
  323. fi
  324. }
  325. asktype() {
  326. if [ -z "$mwtype" ]; then
  327. while : ; do
  328. printf "[yes/no]: Local mail via mbsync? No: Mutt remotes (slower)\\n\t"
  329. read -r offnot
  330. case "$offnot" in
  331. [Yy][Ee][Ss]) mwtype="offline" && break ;;
  332. [Nn][Oo]) mwtype="online" && break ;;
  333. *) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;;
  334. esac
  335. done
  336. fi
  337. }
  338. mwpurge() {
  339. confirm "delete all account data" || exit
  340. rm -rf "$mwmbsyncrc" "$mwaccmuttdir" "$mwconfigdir/msmtp" "${mwmbsyncrc%/*}" "$mwcachedir"
  341. pgrep cron >/dev/null && crontab -l | sed '/mailsync/d' | crontab - >/dev/null
  342. sed -i "/\# mw-autogenerated/d" "$mwmuttrc"
  343. echo "All configs and account settings have been purged."
  344. }
  345. notmuchauto() {
  346. [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
  347. [ -f "$NOTMUCH_CONFIG" ] && return 0
  348. nmbasic="[database]
  349. path=$mwmaildir
  350. [user]
  351. name=$mwname
  352. primary_email=$mwaddr
  353. [new]
  354. tags=unread;inbox;
  355. ignore=
  356. [search]
  357. exclude_tags=deleted;spam;
  358. [maildir]
  359. synchronize_flags=true
  360. [crypto]
  361. gpg_path=$GPG"
  362. mkdir -p "${NOTMUCH_CONFIG%/*}"
  363. echo "$nmbasic" > "$NOTMUCH_CONFIG"
  364. }
  365. trap 'echo -e "\033[0m\n"; exit' STOP INT ABRT KILL
  366. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
  367. case "$1" in
  368. ls) mwlist ;;
  369. add) mwadd ;;
  370. pass) mwpick "change the password of" && getpass ;;
  371. delete) mwpick delete && confirm "delete the \`$mwacc\` profile" && mwdelete ;;
  372. purge) mwpurge ;;
  373. cron) mwcron ;;
  374. *) cat << EOF
  375. mw: mutt-wizard, auto-configure email accounts for mutt
  376. including downloadable mail with \`isync\`.
  377. Allowed options:
  378. add Add and autoconfigure an email address (9 max.)
  379. ls List configured accounts
  380. delete Pick an account to delete
  381. purge Delete all accounts and settings
  382. cron Enable or disable an autosync via cronjob
  383. all else Print this message
  384. NOTE: Once at least one account is added, you can run
  385. \`mailsync -a\` to begin downloading mail.
  386. EOF
  387. esac
  388. fi