Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

718 lignes
24 KiB

  1. #!/bin/sh
  2. if [ -z "$prefix" ]; then
  3. case "$(uname)" in
  4. Linux) prefix="/usr" ;;
  5. *) prefix="/usr/local" ;;
  6. esac
  7. fi
  8. mwconfigdir=${XDG_CONFIG_HOME:-$HOME/.config}
  9. # Main mutt config location
  10. mwmuttdir="$mwconfigdir/mutt"
  11. mwmuttrc="$mwmuttdir/muttrc"
  12. # Directory for account settings
  13. mwaccmuttdir="$mwmuttdir/accounts"
  14. # Generated at every full sync
  15. mwgenmuttaccs=$mwmuttdir/mw_accounts.muttrc
  16. # Location of mail storage
  17. mwmaildir="${MAILDIR:-$HOME/mail}"
  18. # Regex to confirm valid email address
  19. mwemailre=".\+@.\+\\..\+"
  20. mwshare="$prefix/share/mutt-wizard"
  21. mwmbsyncrc="$mwconfigdir/isync/mbsyncrc"
  22. mwgetmaildir=$mwconfigdir/getmail # POP3
  23. mwmsmtprc="$mwconfigdir/msmtp/config"
  24. mwsharerc="$mwshare/mutt-wizard.muttrc"
  25. mwcachedir="${XDG_CACHE_HOME:-$HOME/.cache}/mutt-wizard"
  26. mwmbsyncbin="$prefix/bin/mbsync -c $mwmbsyncrc"
  27. mwgetmailbin="$prefix/bin/getmail"
  28. msmtpbin="$prefix/bin/msmtp"
  29. _mwtakeaddr(){
  30. mwaccmaildir="$mwmaildir/$mwaddr" # mail dir is $MAILDIR/email
  31. mwacccachedir=$mwcachedir/${mwaddr//[.@]/_} # @ cannot stay because of mutt, . could
  32. [ -z "$mwpass" ] || mwpass=mutt-wizard-$mwaddr
  33. [ -n "$mwidnum" ] && mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwaddr.mwonofftype.$mwtype.muttrc"
  34. }
  35. _mwaddrs() {
  36. mwaddrs="$(find "$mwaccmuttdir" -type f | grep -o "[1-9]-.*.muttrc" | sed "s/-/: /;s/\.muttrc//" | sort -n)"
  37. }
  38. _mwlist() {
  39. _mwaddrs && [ -n "$mwaddrs" ] && echo "${mwaddrs//.mwonofftype./ }"
  40. }
  41. _mwadd() {
  42. _mwcheckcert && _mwcheckinternet && _mwasktype && _mwaskinfo && _mwprofiles && _mwtryconnect && _mwfinalize || _mwdelete
  43. }
  44. _mwgetpass() {
  45. while : ; do pass rm -f "$mwpass" >/dev/null 2>&1
  46. pass insert "$mwpass" && break; done ;
  47. }
  48. _mwaskinfo() {
  49. if [ -z "$mwaddr" ]; then
  50. printf "Type the \033[31memail address\033[0m\\n\t\033[36m"
  51. read -r mwaddr
  52. printf "\033[0m"
  53. while ! echo "$mwaddr" | grep "$mwemailre" >/dev/null; do
  54. printf "That is not a valid \033[31memail address\033[0m, please retype\\n\t\033[36m"
  55. read -r mwaddr
  56. printf "\033[0m"
  57. done
  58. fi
  59. mwdomain="$(echo "$mwaddr" | sed "s/.*@//")"
  60. printf "\\nSearching for \033[32m%s\033[0m in \033[34m\`domains.csv\`\033[0m..." "$mwdomain"
  61. mwserverinfo="$(grep "^$mwdomain" "$mwshare/domains.csv" 2>/dev/null)"
  62. if [ -z "$mwserverinfo" ]; then
  63. printf "Your email domain is not known to mutt-wizard.\\nType in your settings.\\n"
  64. printf "Usually you find them by an internet search.\\n"
  65. printf "Type the IMAP/POP3 server (excluding the port number)\\n\033[36m\t"
  66. read -r mwurl
  67. printf "\033[0mIMAP port number (usually 993)\\n\033[36m\t"
  68. read -r mwport
  69. printf "\033[0mSMTP server (excluding the port number)\\n\033[36m\t"
  70. read -r mwsurl
  71. printf "\033[0mSMTP port number (usually 587 or 465)\\n\033[36m\t"
  72. read -r mwsport
  73. 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"
  74. printf "%s,%s,%s,%s,%s\\n\\nBut be sure the setting works, first! ;-)\\n" "$mwdomain" "$mwurl" "$mwport" "$mwsurl" "$mwsport"
  75. else # found server info
  76. IFS=, read -r mwservice mwurl mwport mwsurl mwsport <<EOF
  77. $mwserverinfo
  78. EOF
  79. printf "\\n\033[3;33mCongrats!\033[0m Server info is known, so you don't need to look it up!\\n"
  80. printf "\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" \
  81. "$mwurl" "$mwport" "$mwsurl" "$mwsport"
  82. case "$mwservice" in
  83. 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" ;;
  84. 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" && mwssltype="None" ;;
  85. esac
  86. fi
  87. if [ -z "$mwname" ]; then
  88. printf "Name to associate to email.\\n\t"
  89. read -r mwname
  90. fi
  91. if [ -z "$mwlogin" ]; then
  92. printf "Type your account username if different from your email address.\\n"
  93. printf "\033[34mFor most accounts you can probably leave this blank.\033[0m\\n\tLogin(?): \033[36m"
  94. read -r mwlogin
  95. printf "\033[0m"
  96. [ -z "$mwlogin" ] && mwlogin="$mwaddr"
  97. fi
  98. # if the user has a pass entry he could provide it via mwpass
  99. if [ -z "$mwpass" ]; then
  100. mwpass=mutt-wizard-$mwaddr
  101. _mwgetpass
  102. fi
  103. _mwtakeaddr
  104. if [ "$mwport" = "110" ] || [ "$mwport" = "995" ]; then # POP3
  105. [ "$mwport" = "110" ] && mwkind="pop" || mwkind="pops"
  106. else
  107. [ "$mwport" = "143" ] && mwkind="imap" || mwkind="imaps"
  108. [ "$mwkind" = "imap" ] && mwssltype="None" || mwssltype=${mwssltype:-${mwkind^^}}
  109. fi
  110. [ "$mwsport" = "465" ] && mwstarttlsoff="tls_starttls off"
  111. return 0
  112. }
  113. _mwsmtp() {
  114. mkdir -p "${mwmsmtprc%/*}"
  115. if [ ! -f "$mwmsmtprc" ]; then
  116. cat > "$mwmsmtprc" <<EOF
  117. defaults
  118. auth on
  119. tls on
  120. tls_trust_file $mwsslcert
  121. logfile ${XDG_LOG_HOME:-$HOME}/msmtp.log
  122. EOF
  123. else
  124. sed -i "/account $mwaddr/,/^\(\s*$\|account\)/d" "$mwmsmtprc" &>/dev/null
  125. fi
  126. cat >> "$mwmsmtprc" <<EOF
  127. account $mwaddr
  128. host $mwsurl
  129. port $mwsport
  130. from $mwaddr
  131. user $mwlogin
  132. passwordeval "pass $mwpass"
  133. $mwstarttlsoff
  134. EOF
  135. case "$mwservice" in
  136. protonmail.ch|protonmail.com|pm.me) _mwprotonfinger || return 1 ;;
  137. esac
  138. }
  139. _mwprotonfinger() {
  140. printf "Getting Protonmail bridge fingerprint...\\n"
  141. mwfingerprint="$($msmtpbin --serverinfo --host=127.0.0.1 --port=1025 --tls --tls-certcheck=off)" || return 1
  142. sed -i "s/account $mwaddr/&\ntls_trust_file\ntls_fingerprint $mwfingerprint/" "$mwmsmtprc" &>/dev/null
  143. }
  144. _mwmbsync() {
  145. mkdir -p "${mwmbsyncrc%/*}"
  146. [ -f "$mwmbsyncrc" ] && sed -i "/IMAPStore $mwaddr-remote$/,/# End mw profile/d" "$mwmbsyncrc"
  147. cat >> "$mwmbsyncrc" <<EOF
  148. IMAPStore $mwaddr-remote
  149. Host $mwurl
  150. Port $mwport
  151. User $mwlogin
  152. PassCmd "pass $mwpass"
  153. SSLType $mwssltype
  154. CertificateFile $mwsslcert
  155. MaildirStore $mwaddr-local
  156. Subfolders Verbatim
  157. Path $mwaccmaildir/
  158. Inbox $mwaccmaildir/INBOX
  159. Channel $mwaddr
  160. Expunge Both
  161. Master :$mwaddr-remote:
  162. Slave :$mwaddr-local:
  163. Patterns * !"[Gmail]" !"[Gmail]/All Mail"
  164. Create Both
  165. SyncState *
  166. MaxMessages 0
  167. # End mw profile
  168. EOF
  169. }
  170. _mwpop() {
  171. mkdir -p "$mwgetmaildir"
  172. cat > "$mwgetmaildir/$mwaddr" <<EOF
  173. [retriever]
  174. type = SimplePOP3SSLRetriever
  175. server = $mwurl
  176. username = $mwlogin
  177. port = $mwport
  178. password_command = ("pass", "$mwpass")
  179. [destination]
  180. type = Maildir
  181. path = $mwaccmaildir/INBOX/
  182. [options]
  183. read_all = true
  184. delete = true
  185. message_log = ${XDG_LOG_HOME:-$HOME}/getmail.log
  186. # vim: ft=conf
  187. EOF
  188. }
  189. _mwprofiles() {
  190. printf "Creating profiles for \`%s\`..." "$mwaddr"
  191. # mutt
  192. [ ! -f "$mwgenmuttaccs" ] && _mwgenmuttaccs
  193. if [ "$mwtype" = "offline" ]; then
  194. if [ "${mwkind::3}" = "pop" ]; then
  195. _mwpop
  196. else
  197. _mwmbsync
  198. fi
  199. _mwsmtp
  200. fi
  201. return 0
  202. }
  203. _mwtryconnect() {
  204. if [ ! -d "$mwaccmaildir" ]; then
  205. mwaccmaildirWasThere="NO" # need to remove again for "online"
  206. mkdir -p "$mwaccmaildir"
  207. fi
  208. if [ -z "$mwmailboxes" ]; then
  209. #just check server, no mail retrieval
  210. if [ "${mwkind::3}" = "pop" ]; then
  211. [ "$mwport" = "110" ] && mwp="POP3" || mwp="POP3_SSL"
  212. python -c "from poplib import $mwp;p=$mwp('$mwurl');print(p.getwelcome());p.quit()" | \
  213. grep "+OK" && mwmailboxes="INBOX"
  214. else
  215. # for online do without mbsync, as it might not be installed
  216. # mwmailboxes="$($mwmbsyncbin -l $mwaddr | sed 's/\//./')" >/dev/null 2>&1
  217. [ "$mwport" = "143" ] && mwi="IMAP4" || mwi="IMAP4_SSL"
  218. mwpw="$(pass $mwpass)"
  219. mwmailboxes="$(python -c "from imaplib import $mwi;m=$mwi('$mwurl');m.login('$mwlogin','$mwpw');b=m.list()[1];print('\n'.join(e.split(b' \"/\" ')[-1].strip(b'\"').decode() for e in b if all(x not in e for x in [b'[Gmail]/All Mail',b'Noselect',b'HasChildren'])));m.logout()")"
  220. fi
  221. fi
  222. if [ -n "$mwmailboxes" ]; then
  223. mwspoolfile=$(echo "$mwmailboxes" | grep -i -m 1 inbox | sed -ne 's/.*/+\0/p')
  224. [ -z "$mwspoolfile" ] && printf "\033[31m\033[31mNo spoolfile.\033[0m\\n" && return 1
  225. printf "\033[32mMailboxes detected.\033[0m\\n"
  226. echo "$mwmailboxes" | xargs -I {} mkdir -p "$mwaccmaildir/{}/"{cur,new,tmp}
  227. return 0
  228. else
  229. printf "\033[31m\033[31mLog-on not successful.\033[0m\\n"
  230. printf "It 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"
  231. return 1
  232. fi
  233. }
  234. _mwfinalize() { # new mwaccmuttrc
  235. if [ "$mwtype" = "online" ]; then
  236. mkdir -p "$mwacccachedir"
  237. sed -i "/IMAPStore $mwaddr-remote$/,/# End mw profile/d" "$mwmbsyncrc" &>/dev/null
  238. fi
  239. _mwgenmwaccmuttrc || return 1
  240. if [ "$mwtype" = "offline" ]; then
  241. _mwnotmuchauto
  242. printf "All done.\\n\033[33mYou can now run \`\033[32mmw [%s]\033[33m\` to sync your mail.\033[0m\\n" "$mwaddr"
  243. fi
  244. if [ "$mwtype" = "online" ]; then
  245. [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir" &>/dev/null
  246. fi
  247. }
  248. _mwconfirm() {
  249. printf "[y/N]: Do you want to %s?\\n\t" "$@" && read -r mwinput && ! echo "$mwinput" | grep -i "^y$\|^yes$" >/dev/null \
  250. && printf "That doesn't seem like a yes to me.\\n\\n" && return 1
  251. return 0 ;
  252. }
  253. _mwpick() {
  254. printf "Select an accounts to %s:\\n" "$1"
  255. _mwlist
  256. [ -z "$mwpick" ] && read -r mwpick
  257. mwidnum="$mwpick"
  258. [ -z "$mwidnum" ] && return 1
  259. mwaddr="$(echo "$mwaddrs" | grep -i -m 1 "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $2}')"
  260. mwtype="$(echo "$mwaddrs" | grep -i -m 1 "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $3}')"
  261. _mwtakeaddr
  262. [ -z "$mwaddr" ] && printf "Invalid response." && return 1
  263. return 0 ;
  264. }
  265. _mwdelete() {
  266. [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir" &>/dev/null
  267. rm -f "$mwaccmuttrc" &>/dev/null
  268. if [ "$mwtype" = "offline" ]; then
  269. sed -i "/${mwaccmuttrc//\//\\\/}/d" "$mwgenmuttaccs" &>/dev/null
  270. sed -i "/account $mwaddr/,/^\(\s*$\|account\)/d" "$mwmsmtprc" &>/dev/null
  271. if [ -f "$mwgetmaildir/$mwaddr" ]; then
  272. rm -f "$mwgetmaildir/$mwaddr" &>/dev/null
  273. else
  274. sed -i "/IMAPStore $mwaddr-remote$/,/# End mw profile/d" "$mwmbsyncrc" &>/dev/null
  275. fi
  276. else
  277. sed -i "/${mwaccmuttrc//\//\\\/}/d" "$mwmuttrc" &>/dev/null
  278. rm -rf "$mwacccachedir" &>/dev/null
  279. fi
  280. }
  281. _mwcron() {
  282. ! pgrep cron >/dev/null && echo "No cron manager running. Install/enable one and then select this option again." && return 1
  283. if crontab -l | grep "mw sync" >/dev/null; then
  284. echo "Active mail sync cronjob detected. Do you want to remove it?"
  285. printf "\033[36m\t"
  286. [ -z "$mwcronremove" ] && read -r mwcronremove
  287. printf "\033[0m"
  288. echo "$mwcronremove" | grep -i "^y\(es\)*$" >/dev/null && crontab -l | sed '/mw sync/d' | crontab - >/dev/null \
  289. && echo "Mail sync turned off."
  290. else
  291. echo "How many minutes between each mail sync?"
  292. printf "\033[36m\t"
  293. [ -z $mwcronminutes ] && read -r mwcronminutes
  294. printf "\033[0m"
  295. while ! echo "$mwcronminutes" | grep "^[1-9]\+$" >/dev/null; do
  296. printf "That doesn't look like a number. How many minutes between each mail sync?\\n\033[36m\t"
  297. read -r mwcronminutes
  298. printf "\033[0m"
  299. done
  300. (crontab -l; echo "*/$mwcronminutes * * * * export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus; export DISPLAY=:0; $(type mw | cut -d' ' -f3) sync") \
  301. | crontab - && \
  302. echo "Cronjob added. Mail will sync every $mwcronminutes minutes. Be sure you have your cron manager running."
  303. fi
  304. }
  305. _mwasktype() {
  306. if [ -z "$mwtype" ]; then
  307. while : ; do
  308. printf "[yes/no]: Local mail via mbsync? 'no' means, that Mutt remotes, which is slower.\\n"
  309. read -r mwoffline
  310. case "$mwoffline" in
  311. [Yy][Ee][Ss]) mwtype="offline" && break ;;
  312. [Nn][Oo]) mwtype="online" && break ;;
  313. *) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;;
  314. esac
  315. done
  316. fi
  317. }
  318. _mwpurge() {
  319. _mwconfirm "delete all mutt-wizard data" || exit
  320. mwaddrs="$(find "$mwaccmuttdir" -type f | grep -o "[1-9]-.*.muttrc" | sed "s/\.muttrc//")"
  321. for mwaddrsentry in $mwaddrs; do
  322. mwtype="$(echo "$mwaddrsentry" | sed "s/\.mwonofftype\./ /" | awk '{print $2}')"
  323. mwaddr="$(echo "$mwaddrsentry" | sed "s/\.mwonofftype\./ /" | awk '{print $1}')"
  324. mwidnum="$(echo "$mwaddr" | sed "s/-/ /" | awk '{print $1}')"
  325. mwaddr="$(echo "$mwaddr" | sed "s/-/ /" | awk '{print $2}')"
  326. _mwtakeaddr
  327. _mwdelete
  328. done
  329. rm -rf "$mwaccmuttdir"/[1-9]-*.muttrc "$mwcachedir" "$mwgenmuttaccs"
  330. sed -i "/\# mw-autogenerated/d" "$mwmuttrc"
  331. pgrep cron >/dev/null && crontab -l | sed '/mw sync/d' | crontab - >/dev/null
  332. echo "All configs and account settings have been purged."
  333. }
  334. _mwnotmuchauto() {
  335. [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
  336. [ -f "$NOTMUCH_CONFIG" ] && return 0
  337. mkdir -p "${NOTMUCH_CONFIG%/*}"
  338. cat > "$NOTMUCH_CONFIG" <<EOF
  339. [database]
  340. path=$mwmaildir
  341. [user]
  342. name=$mwname
  343. primary_email=$mwaddr
  344. [new]
  345. tags=unread;inbox;
  346. ignore=
  347. [search]
  348. exclude_tags=deleted;spam;
  349. [maildir]
  350. synchronize_flags=true
  351. [crypto]
  352. gpg_path=$GPG"
  353. EOF
  354. }
  355. # run after mbsync to create mutt settings for $mwaddr
  356. _mwgenmwaccmuttrc() {
  357. mwaccmaildir="$mwmaildir/$mwaddr"
  358. mwmailboxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")"
  359. [ "${mwmailboxes/ /}" = "" ] && echo "no mailboxes" && return 1
  360. mwspoolfile=$(echo "$mwmailboxes" | grep -i -m 1 inbox | sed -ne 's/.*/+\0/p')
  361. [ "${mwspoolfile/ /}" = "" ] && return 1
  362. mwrecord=$(echo "$mwmailboxes" | grep -i -m 1 sent | sed -ne 's/.*/+\0/p')
  363. [ -z "$mwrecord" ] && mkdir -p "$mwaccmaildir/Sent/"{cur,new,tmp} && mwrecord="Sent"
  364. mwpostponed=$(echo "$mwmailboxes" | grep -i -m 1 draft | sed -ne 's/.*/+\0/p')
  365. [ -z "$mwpostponed" ] && mkdir -p "$mwaccmaildir/Drafts/"{cur,new,tmp} && mwpostponed="Drafts"
  366. mwtrash=$(echo "$mwmailboxes" | grep -i -m 1 trash | sed -ne 's/.*/+\0/p')
  367. [ -z "$mwtrash" ] && mkdir -p "$mwaccmaildir/Trash/"{cur,new,tmp} && mwtrash="Trash"
  368. # again to reflect the change
  369. mwmailboxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")"
  370. # find mwaccmuttrc ...
  371. mwaccmuttrc="$mwaccmuttdir/$(find "$mwaccmuttdir" -type f | grep -m 1 -o "[1-9]-$mwaddr.mwonofftype.$mwtype.muttrc")"
  372. if [ ! -f "$mwaccmuttrc" ]; then
  373. # new mwidnum = first one missing
  374. _mwaddrs
  375. for mwx in $(seq 1 9); do echo "$mwaddrs" | grep "$mwx:" >/dev/null 2>&1 || { export mwidnum="$mwx"; break ;}; done
  376. mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwaddr.mwonofftype.$mwtype.muttrc"
  377. else
  378. mwidnum=${mwaccmuttrc%%-*}
  379. mwidnum=${mwidnum##*/}
  380. fi
  381. # link mwaccmuttrc ...
  382. if [ "$mwtype" = "offline" ]; then
  383. ! grep "source $mwaccmuttrc" "$mwgenmuttaccs" &>/dev/null && echo "source $mwaccmuttrc" >> $mwgenmuttaccs
  384. else
  385. ! grep "source $mwaccmuttrc" "$mwmuttrc" &>/dev/null && echo "source $mwaccmuttrc # mw-autogenerated" >> $mwmuttrc
  386. fi
  387. # (re-)generate mwaccmuttrc ...
  388. mwmuttsync=$(printf '<sync-mailbox><enter-command>source %s<enter><change-folder>!<enter>;<check-stats>' $mwaccmuttrc)
  389. cat > "$mwaccmuttrc" <<EOF
  390. # vim: filetype=muttrc
  391. # muttrc file for account $mwaddr
  392. # generated by mw
  393. set from = "$mwaddr"
  394. EOF
  395. if [ "$mwtype" = "offline" ]; then
  396. cat >> "$mwaccmuttrc" <<EOF
  397. macro index gm "<shell-escape>mw $mwaddr<enter>" "sync mail $mwaddr"
  398. set folder = "$mwaccmaildir"
  399. folder-hook \$folder '$mwmuttsync'
  400. set sendmail = "/usr/bin/msmtp -a \$from"
  401. EOF
  402. else # online
  403. if [ "${mwkind::3}" = "pop" ]; then
  404. cat >> "$mwaccmuttrc" <<EOF
  405. bind index gc fetch-mail
  406. # pop
  407. set pop_user = "$mwkind://$mwlogin@$mwurl:$mwport"
  408. set pop_pass = `pass magenta.at/roland.puntaier@chello.at`
  409. set pop_host = "\`pass $mwpass\`"
  410. set pop_delete = yes
  411. EOF
  412. else # imap
  413. mwssl=${mwkind/imap/no}
  414. cat >> "$mwaccmuttrc" <<EOF
  415. bind index gm imap-fetch-mail
  416. set folder = "$mwkind://$mwlogin@$mwurl:$mwport"
  417. set header_cache = "$mwacccachedir"
  418. set message_cachedir = \$header_cache
  419. set imap_user = "$mwlogin"
  420. set imap_pass = "\`pass $mwpass\`"
  421. account-hook \$folder 'set imap_user="$mwlogin" imap_pass="\`pass $mwpass\`"'
  422. set mbox_type = Maildir
  423. set ssl_starttls = ${mwssl/nos/yes}
  424. set ssl_force_tls = ${mwssl/nos/yes}
  425. set smtp_pass = "\`pass $mwpass\`"
  426. EOF
  427. fi # imap
  428. #smtp
  429. [ "$mwsport" = "25" ] && mwsmtp="smtp" || mwsmtp="smtps"
  430. cat >> "$mwaccmuttrc" <<EOF
  431. set smtp_url = "$mwsmtp://$mwlogin@$mwsmtp:$mwsport"
  432. EOF
  433. fi #online
  434. mwboxes="$(echo "$mwmailboxes" | sed -e "s/^ //g;s/.*/\"=\0\"/g" | tr "\n" " ")"
  435. mwaccmutt="${mwaddr//[.@]/_}"
  436. cat >> "$mwaccmuttrc" <<EOF
  437. set spoolfile = "$mwspoolfile"
  438. set record = "$mwrecord"
  439. set postponed = "$mwpostponed"
  440. set trash = "$mwtrash"
  441. unmailboxes *
  442. mailboxes =$mwaccmutt ===================== $mwboxes
  443. macro index,pager i$mwidnum '$mwmuttsync' "switch to $mwaddr"
  444. EOF
  445. [ -n "$mwname" ] && cat >> "$mwaccmuttrc" <<EOF
  446. set realname = "$mwname"
  447. alias me $mwname <$mwaddr>
  448. EOF
  449. IFS=$'\n'
  450. for eqbox in $mwmailboxes; do
  451. qbox=${eqbox/[/}
  452. b1=${qbox::1}
  453. box=${qbox##*/}
  454. [ "$box" = "$qbox" ] && b2=${qbox:1:1} || b2=${box:1:1}
  455. boxi="$b1$b2"
  456. boxi=${boxi,,}
  457. cat >> $mwaccmuttrc <<EOF
  458. macro index,pager i$boxi "<change-folder>=$eqbox<enter>" "go to $eqbox"
  459. macro index,pager M$boxi "<save-message>=$eqbox<enter>" "move mail to $eqbox"
  460. macro index,pager C$boxi "<copy-message>=$eqbox<enter>" "copy mail to $eqbox"
  461. EOF
  462. done
  463. unset IFS
  464. }
  465. if [ "$(uname)" = "Darwin" ]; then
  466. _mwnotify() { osascript -e "display notification \"$2 in $1\" with title \"You've got Mail\" subtitle \"Account: $1\"" ;}
  467. else
  468. if type notify-send >/dev/null; then
  469. _mwnotify() { notify-send "mutt-wizard" "📬 $2 new mail(s) in \`$1\` account." ;}
  470. else
  471. _mwnotify() { echo "mutt-wizard: 📬 $2 new mail(s) in \`$1\` account." ;}
  472. fi
  473. fi
  474. _mwaddr() {
  475. mwaddr=$1
  476. mwaddr=${mwaddr/#\~/$HOME}
  477. mwaddr=${mwaddr#$mwmaildir/}
  478. mwaddr=${mwaddr%%/*}
  479. mkdir -p $mwmaildir/$mwaddr
  480. }
  481. _mwgenmuttaccs(){
  482. mkdir -p "$mwmuttdir" "$mwaccmuttdir"
  483. [ ! -f "$mwmuttrc" ] && echo "# vim: filetype=muttrc" > "$mwmuttrc" && echo "muttrc created."
  484. ! grep "source $mwsharerc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc"
  485. ! grep "source $mwgenmuttaccs" "$mwmuttrc" >/dev/null && echo "source $mwgenmuttaccs # mw-autogenerated" >> "$mwmuttrc"
  486. cat > "$mwgenmuttaccs" <<EOF
  487. # vim: filetype=muttrc
  488. # generated by mw
  489. macro index gM '<shell-escape>mw<enter>' "sync all mail"
  490. EOF
  491. }
  492. _mwgatheremails() {
  493. unset mwemails
  494. _mwgenmuttaccs
  495. if [ -f "$mwmbsyncrc" ]; then
  496. for store in $(sed -ne 's/^Path\s*//p' $mwmbsyncrc); do
  497. _mwaddr "$store"
  498. mwemails+=" $mwaddr"
  499. done
  500. fi
  501. if [ -d "$mwgetmaildir" ]; then
  502. for gmrc in $mwgetmaildir/*; do
  503. [ "${gmrc#$mwgetmaildir}" = "/*" ] && break
  504. store=$(sed -ne "s/^path\s*=\s*//p" $gmrc)
  505. store=${store/#\~/$HOME}
  506. _mwaddr "$store"
  507. mkdir -p "$store"/{cur,new,tmp}
  508. mwemails+=" $mwaddr"
  509. done
  510. fi
  511. mwemails="${mwemails/ /}"
  512. }
  513. _mwsyncandnotify() {
  514. mwaccmaildir="$mwmaildir/$mwaddr"
  515. if [ -f "$mwgetmaildir/$mwaddr" ]; then
  516. $mwgetmailbin --rcfile=$mwaddr --getmaildir=$mwgetmaildir
  517. else
  518. tree $mwaccmaildir
  519. $mwmbsyncbin $mwaddr
  520. tree $mwaccmaildir
  521. fi
  522. mwlastrun="$mwaccmaildir/.mw.lastrun"
  523. mwnew=$(find "$mwaccmaildir/INBOX/new/" "$mwaccmaildir/Inbox/new/" "$mwaccmaildir/inbox/new/" -type f -newer "$mwlastrun" 2> /dev/null)
  524. newcount=$(echo "$mwnew" | sed '/^\s*$/d' | wc -l)
  525. if [ "$newcount" -gt "0" ]; then
  526. _mwnotify "$mwaddr" "$newcount"
  527. for file in $mwnew; do
  528. # Extract subject and sender from mail.
  529. from=$(awk '/^From: / && ++n ==1,/^\<.*\>:/' "$file" | perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | \
  530. awk '{ $1=""; if (NF>=3)$NF=""; print $0 }' | sed 's/^[[:blank:]]*[\"'\''\<]*//;s/[\"'\''\>]*[[:blank:]]*$//')
  531. subject=$(awk '/^Subject: / && ++n == 1,/^\<.*\>: / && ++i == 2' "$file" | head -n-1 | perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | \
  532. sed 's/^Subject: //' | sed 's/^{[[:blank:]]*[\"'\''\<]*//;s/[\"'\''\>]*[[:blank:]]*$//' | tr -d '\n')
  533. _mwnotify "📧$from:" "$subject"
  534. done
  535. fi
  536. touch "$mwlastrun"
  537. }
  538. _mwsyncemails() {
  539. for mwaddr in $mwemails; do
  540. _mwsyncandnotify
  541. done
  542. rm $XDG_CONFIG_HOME/getmail/oldmail-* &>/dev/null
  543. echo notmuch+afew ...
  544. notmuch new &>/dev/null
  545. # notmuch also created afew MailMover target mailboxes
  546. }
  547. _mwmuttemails() {
  548. for mwaddr in $mwemails; do
  549. _mwgenmwaccmuttrc
  550. done
  551. }
  552. _mwcheckcert() {
  553. for mwcrt in "/etc/ssl/certs/ca-certificates.crt" "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/ca-bundle.pem" \
  554. "/etc/pki/tls/cacert.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/ssl/cert.pem" "/usr/local/share/ca-certificates/"
  555. do
  556. [ -f "$mwcrt" ] && mwsslcert="$mwcrt" && break
  557. done || { echo "CA Certificate not found. Please install one or link it to /etc/ssl/certs/ca-certificates.crt" && return 1 ;}
  558. }
  559. _mwcheckinternet() {
  560. # Checks for internet connection
  561. if type systemctl >/dev/null; then
  562. if ! systemctl --type service | grep net | grep active > /dev/null; then
  563. echo "No internet connection."
  564. return 1
  565. fi
  566. else
  567. if ! ping -q -c 1 1.1.1.1 > /dev/null; then
  568. echo "No internet connection (ping failed)."
  569. return 1
  570. fi
  571. fi
  572. }
  573. _mwsync() {
  574. unset mwemails
  575. mwtype="offline"
  576. # Run only if user logged in (prevent cron errors)
  577. if ! pgrep -u "$USER" >/dev/null; then
  578. echo "$USER not logged in; sync will not run."
  579. return 1
  580. fi
  581. # Run only if not already running in other instance
  582. if pgrep -x mbsync >/dev/null; then
  583. echo "mbsync is running."
  584. return 1
  585. fi
  586. if pgrep -x notmuch >/dev/null; then
  587. echo "notmuch is running."
  588. return 1
  589. fi
  590. _mwcheckinternet || return 1
  591. _mwaddr "$1"
  592. mwemails="$mwaddr"
  593. [ "$mwemails" = "" ] && _mwgatheremails && _mwsyncemails && _mwmuttemails && return 0
  594. _mwsyncemails
  595. return 0
  596. }
  597. trap 'echo -e "\033[0m\n"; exit' STOP INT ABRT KILL
  598. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
  599. if [ "$#" -gt 1 ]; then
  600. echo "Command or email or no parameter (=sync all). See --help."
  601. return 1
  602. fi
  603. type gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
  604. [ -z "$PASSWORD_STORE_DIR" ] && PASSWORD_STORE_DIR="$HOME/.password-store"
  605. [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] &&
  606. "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || {
  607. printf "\`pass\` must be installed and initialized to encrypt passwords.\\nBe sure it is installed and run \`pass init <yourgpgemail>\`.\\n"
  608. printf "If you don't have a GPG public private key pair, run \`$GPG --full-gen-key\` first.\\n"
  609. exit
  610. }
  611. ! type "$prefix/bin/mbsync" >/dev/null && printf "\`mbsync\` must be installed to run mutt-wizard.\\n" && exit
  612. ! type "$prefix/bin/msmtp" >/dev/null && printf "\`msmtp\` must be installed.\\n" && exit
  613. ! ( type mutt >/dev/null || type neomutt >/dev/null ) && printf "\`mutt\` must be installed.\\n" && exit
  614. if [ "$1" = "" ]; then
  615. _mwsync
  616. else
  617. case "$1" in
  618. ls) _mwlist ;;
  619. add) _mwadd ;;
  620. pass) _mwpick "change the password of" && _mwgetpass ;;
  621. delete) _mwpick delete && _mwconfirm "delete the \`$mwaddr\` profile" && _mwdelete ;;
  622. purge) _mwpurge ;;
  623. cron) _mwcron ;;
  624. sync) _mwsync ;;
  625. *@*) _mwsync $1 ;;
  626. --help|-h) cat <<EOF
  627. mw: mutt-wizard, auto-configure and sync email accounts for mutt,
  628. including mutt-independent sync of mail with \`isync\` or download of POP3 mail with \`getmail\`.
  629. Commands:
  630. add Add and autoconfigure an email address (9 max.)
  631. ls List configured accounts
  632. delete Pick an account to delete
  633. purge Delete all accounts and settings
  634. cron Enable or disable an autosync via cronjob
  635. sync sync/download mail based on config in $mwmbsyncrc and $mwgetmaildir
  636. --help|-h Print this message
  637. With no parameter all configured emails are synced and all account muttrc's are created.
  638. With a parameter containing a @, an mail is assumed and that account is synced.
  639. Config requirements:
  640. - mbsyncrc: "Path" ends in email
  641. - getmail: config file name = email, "path" ends in email
  642. EOF
  643. esac
  644. exit $?
  645. fi
  646. fi