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.
 
 
 
 

727 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 # not online, actually outside mutt
  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. [ ! "${mwkind::3}" = "pop" ] && mwaccmaildirWasThere="NO" # mutt uses $mwacccachedir for "online" IMAP, so clean up later
  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, i.e. don't require it for mail setup, either
  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. if [ ! "${mwkind::3}" = "pop" ]; then
  237. mkdir -p "$mwacccachedir"
  238. fi
  239. fi
  240. _mwgenmwaccmuttrc || return 1
  241. if [ "$mwtype" = "offline" ]; then # not online
  242. _mwnotmuchauto
  243. printf "All done.\\n\033[33mYou can now run \`\033[32mmw [%s]\033[33m\` to sync your mail.\033[0m\\n" "$mwaddr"
  244. elif [ "${mwkind::3}" = "pop" ]; then # and online
  245. _mwnotmuchauto #still usable for online (in mutt) pop
  246. fi
  247. if [ "$mwtype" = "online" ]; then
  248. [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir" &>/dev/null
  249. fi
  250. return 0
  251. }
  252. _mwconfirm() {
  253. printf "[y/N]: Do you want to %s?\\n\t" "$@" && read -r mwinput && ! echo "$mwinput" | grep -i "^y$\|^yes$" >/dev/null \
  254. && printf "That doesn't seem like a yes to me.\\n\\n" && return 1
  255. return 0 ;
  256. }
  257. _mwpick() {
  258. printf "Select an accounts to %s:\\n" "$1"
  259. _mwlist
  260. [ -z "$mwpick" ] && read -r mwpick
  261. mwidnum="$mwpick"
  262. [ -z "$mwidnum" ] && return 1
  263. mwaddr="$(echo "$mwaddrs" | grep -i -m 1 "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $2}')"
  264. mwtype="$(echo "$mwaddrs" | grep -i -m 1 "$mwidnum:" | sed "s/\.mwonofftype\./ /" | awk '{print $3}')"
  265. _mwtakeaddr
  266. [ -z "$mwaddr" ] && printf "Invalid response." && return 1
  267. return 0 ;
  268. }
  269. _mwdelete() {
  270. [ "$mwaccmaildirWasThere" = "NO" ] && rm -rf "$mwaccmaildir" &>/dev/null
  271. rm -f "$mwaccmuttrc" &>/dev/null
  272. if [ "$mwtype" = "offline" ]; then # not online
  273. sed -i "/${mwaccmuttrc//\//\\\/}/d" "$mwgenmuttaccs" &>/dev/null
  274. sed -i "/account $mwaddr/,/^\(\s*$\|account\)/d" "$mwmsmtprc" &>/dev/null
  275. if [ -f "$mwgetmaildir/$mwaddr" ]; then
  276. rm -f "$mwgetmaildir/$mwaddr" &>/dev/null
  277. else
  278. sed -i "/IMAPStore $mwaddr-remote$/,/# End mw profile/d" "$mwmbsyncrc" &>/dev/null
  279. fi
  280. else
  281. sed -i "/${mwaccmuttrc//\//\\\/}/d" "$mwmuttrc" &>/dev/null
  282. rm -rf "$mwacccachedir" &>/dev/null
  283. fi
  284. }
  285. _mwcron() {
  286. ! pgrep cron >/dev/null && echo "No cron manager running. Install/enable one and then select this option again." && return 1
  287. if crontab -l | grep "mw sync" >/dev/null; then
  288. echo "Active mail sync cronjob detected. Do you want to remove it?"
  289. printf "\033[36m\t"
  290. [ -z "$mwcronremove" ] && read -r mwcronremove
  291. printf "\033[0m"
  292. echo "$mwcronremove" | grep -i "^y\(es\)*$" >/dev/null && crontab -l | sed '/mw sync/d' | crontab - >/dev/null \
  293. && echo "Mail sync turned off."
  294. else
  295. echo "How many minutes between each mail sync?"
  296. printf "\033[36m\t"
  297. [ -z $mwcronminutes ] && read -r mwcronminutes
  298. printf "\033[0m"
  299. while ! echo "$mwcronminutes" | grep "^[1-9]\+$" >/dev/null; do
  300. printf "That doesn't look like a number. How many minutes between each mail sync?\\n\033[36m\t"
  301. read -r mwcronminutes
  302. printf "\033[0m"
  303. done
  304. (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") \
  305. | crontab - && \
  306. echo "Cronjob added. Mail will sync every $mwcronminutes minutes. Be sure you have your cron manager running."
  307. fi
  308. }
  309. _mwasktype() {
  310. if [ -z "$mwtype" ]; then
  311. while : ; do
  312. printf "Do you want to sync your mails using the command 'mw' outside mutt? [yes/no]\\n"
  313. printf "'no' makes Neomutt slow for IMAP accounts, so probably you want 'yes'.\\n\t"
  314. read -r mwoffline
  315. case "$mwoffline" in
  316. [Yy][Ee][Ss]) mwtype="offline" && break ;;
  317. [Nn][Oo]) mwtype="online" && break ;;
  318. *) echo "Write out either yes or no completely. Try again or press ctrl-c to quit." ;;
  319. esac
  320. done
  321. fi
  322. }
  323. _mwpurge() {
  324. _mwconfirm "delete all mutt-wizard data" || exit
  325. mwaddrs="$(find "$mwaccmuttdir" -type f | grep -o "[1-9]-.*.muttrc" | sed "s/\.muttrc//")"
  326. for mwaddrsentry in $mwaddrs; do
  327. mwtype="$(echo "$mwaddrsentry" | sed "s/\.mwonofftype\./ /" | awk '{print $2}')"
  328. mwaddr="$(echo "$mwaddrsentry" | sed "s/\.mwonofftype\./ /" | awk '{print $1}')"
  329. mwidnum="$(echo "$mwaddr" | sed "s/-/ /" | awk '{print $1}')"
  330. mwaddr="$(echo "$mwaddr" | sed "s/-/ /" | awk '{print $2}')"
  331. _mwtakeaddr
  332. _mwdelete
  333. done
  334. rm -rf "$mwaccmuttdir"/[1-9]-*.muttrc "$mwcachedir" "$mwgenmuttaccs"
  335. sed -i "/\# mw-autogenerated/d" "$mwmuttrc"
  336. crontab -l | sed '/mw sync/d' | crontab - >/dev/null
  337. echo "All configs and account settings have been purged."
  338. }
  339. _mwnotmuchauto() {
  340. [ -z "$NOTMUCH_CONFIG" ] && NOTMUCH_CONFIG="$HOME/.notmuch-config"
  341. [ -f "$NOTMUCH_CONFIG" ] && return 0
  342. mkdir -p "${NOTMUCH_CONFIG%/*}"
  343. cat > "$NOTMUCH_CONFIG" <<EOF
  344. [database]
  345. path=$mwmaildir
  346. [user]
  347. name=$mwname
  348. primary_email=$mwaddr
  349. [new]
  350. tags=unread;inbox;
  351. ignore=
  352. [search]
  353. exclude_tags=deleted;spam;
  354. [maildir]
  355. synchronize_flags=true
  356. [crypto]
  357. gpg_path=$GPG"
  358. EOF
  359. }
  360. # run after mbsync to create mutt settings for $mwaddr
  361. _mwgenmwaccmuttrc() {
  362. mwaccmaildir="$mwmaildir/$mwaddr"
  363. mwmailboxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")"
  364. [ "${mwmailboxes/ /}" = "" ] && echo "no mailboxes" && return 1
  365. mwspoolfile=$(echo "$mwmailboxes" | grep -i -m 1 inbox | sed -ne 's/.*/+\0/p')
  366. [ "${mwspoolfile/ /}" = "" ] && return 1
  367. mwrecord=$(echo "$mwmailboxes" | grep -i -m 1 sent | sed -ne 's/.*/+\0/p')
  368. [ -z "$mwrecord" ] && mkdir -p "$mwaccmaildir/Sent/"{cur,new,tmp} && mwrecord="+Sent"
  369. mwpostponed=$(echo "$mwmailboxes" | grep -i -m 1 draft | sed -ne 's/.*/+\0/p')
  370. [ -z "$mwpostponed" ] && mkdir -p "$mwaccmaildir/Drafts/"{cur,new,tmp} && mwpostponed="+Drafts"
  371. mwtrash=$(echo "$mwmailboxes" | grep -i -m 1 trash | sed -ne 's/.*/+\0/p')
  372. [ -z "$mwtrash" ] && mkdir -p "$mwaccmaildir/Trash/"{cur,new,tmp} && mwtrash="+Trash"
  373. # again to reflect the change
  374. mwmailboxes="$(find "$mwaccmaildir/" -name cur | sed "s,$mwaccmaildir/,,g;s,/cur,,")"
  375. # find mwaccmuttrc ...
  376. mwaccmuttrc="$mwaccmuttdir/$(find "$mwaccmuttdir" -type f | grep -m 1 -o "[1-9]-$mwaddr.mwonofftype.$mwtype.muttrc")"
  377. if [ ! -f "$mwaccmuttrc" ]; then
  378. # new mwidnum = first one missing
  379. _mwaddrs
  380. for mwx in $(seq 1 9); do echo "$mwaddrs" | grep "$mwx:" >/dev/null 2>&1 || { export mwidnum="$mwx"; break ;}; done
  381. mwaccmuttrc="$mwaccmuttdir/$mwidnum-$mwaddr.mwonofftype.$mwtype.muttrc"
  382. else
  383. mwidnum=${mwaccmuttrc%%-*}
  384. mwidnum=${mwidnum##*/}
  385. fi
  386. # link mwaccmuttrc ...
  387. if [ "$mwtype" = "offline" ]; then
  388. ! grep "source $mwaccmuttrc" "$mwgenmuttaccs" &>/dev/null && echo "source $mwaccmuttrc" >> $mwgenmuttaccs
  389. else #online
  390. ! grep "source $mwaccmuttrc" "$mwmuttrc" &>/dev/null && echo "source $mwaccmuttrc # mw-autogenerated" >> $mwmuttrc
  391. fi
  392. # (re-)generate mwaccmuttrc ...
  393. mwmuttsync=$(printf '<sync-mailbox><enter-command>source %s<enter><change-folder>!<enter>;<check-stats>' $mwaccmuttrc)
  394. cat > "$mwaccmuttrc" <<EOF
  395. # vim: filetype=muttrc
  396. # muttrc file for account $mwaddr
  397. # generated by mw
  398. set from = "$mwaddr"
  399. EOF
  400. if [ "$mwtype" = "offline" ]; then
  401. cat >> "$mwaccmuttrc" <<EOF
  402. macro index gm "<shell-escape>mw $mwaddr<enter>" "sync mail $mwaddr"
  403. set folder = "$mwaccmaildir"
  404. folder-hook \$folder '$mwmuttsync'
  405. set sendmail = "/usr/bin/msmtp -a \$from"
  406. EOF
  407. else # online
  408. if [ "${mwkind::3}" = "pop" ]; then
  409. cat >> "$mwaccmuttrc" <<EOF
  410. bind index gm fetch-mail
  411. # pop
  412. set pop_user = "$mwlogin"
  413. set pop_pass = "\`pass $mwpass\`"
  414. set pop_host = "$mwkind://$mwlogin@$mwurl:$mwport"
  415. set pop_delete = yes
  416. set folder = "$mwaccmaildir"
  417. folder-hook \$folder '$mwmuttsync'
  418. EOF
  419. else # imap
  420. mwssl=${mwkind/imap/no}
  421. cat >> "$mwaccmuttrc" <<EOF
  422. bind index gm imap-fetch-mail
  423. set folder = "$mwkind://$mwlogin@$mwurl:$mwport"
  424. set header_cache = "$mwacccachedir"
  425. set message_cachedir = \$header_cache
  426. set imap_user = "$mwlogin"
  427. set imap_pass = "\`pass $mwpass\`"
  428. account-hook \$folder 'set imap_user="$mwlogin" imap_pass="\`pass $mwpass\`"'
  429. set mbox_type = Maildir
  430. set ssl_starttls = ${mwssl/nos/yes}
  431. set ssl_force_tls = ${mwssl/nos/yes}
  432. set smtp_pass = "\`pass $mwpass\`"
  433. EOF
  434. fi # imap
  435. #smtp
  436. [ "$mwsport" = "25" ] && mwsmtp="smtp" || mwsmtp="smtps"
  437. cat >> "$mwaccmuttrc" <<EOF
  438. set smtp_url = "$mwsmtp://$mwlogin@$mwsurl:$mwsport"
  439. EOF
  440. fi #online
  441. mwboxes="$(echo "$mwmailboxes" | sed -e "s/^ //g;s/.*/\"=\0\"/g" | tr "\n" " ")"
  442. mwaccmutt="${mwaddr//[.@]/_}"
  443. cat >> "$mwaccmuttrc" <<EOF
  444. set spoolfile = "$mwspoolfile"
  445. set record = "$mwrecord"
  446. set postponed = "$mwpostponed"
  447. set trash = "$mwtrash"
  448. unmailboxes *
  449. mailboxes =$mwaccmutt ===================== $mwboxes
  450. macro index,pager i$mwidnum '$mwmuttsync' "switch to $mwaddr"
  451. EOF
  452. [ -n "$mwname" ] && cat >> "$mwaccmuttrc" <<EOF
  453. set realname = "$mwname"
  454. alias me $mwname <$mwaddr>
  455. EOF
  456. IFS=$'\n'
  457. for eqbox in $mwmailboxes; do
  458. qbox="${eqbox/\[/}"
  459. b1="${qbox::1}"
  460. box="${qbox##*/}"
  461. [ "$box" = "$qbox" ] && b2="${qbox:1:1}" || b2="${box:1:1}"
  462. boxi="$b1$b2"
  463. boxi="${boxi,,}"
  464. cat >> $mwaccmuttrc <<EOF
  465. macro index,pager i$boxi "<change-folder>=$eqbox<enter>" "go to $eqbox"
  466. macro index,pager M$boxi "<save-message>=$eqbox<enter>" "move mail to $eqbox"
  467. macro index,pager C$boxi "<copy-message>=$eqbox<enter>" "copy mail to $eqbox"
  468. EOF
  469. done
  470. unset IFS
  471. return 0
  472. }
  473. if [ "$(uname)" = "Darwin" ]; then
  474. _mwnotify() { osascript -e "display notification \"$2 in $1\" with title \"You've got Mail\" subtitle \"Account: $1\"" ;}
  475. else
  476. if type notify-send >/dev/null; then
  477. _mwnotify() { notify-send "mutt-wizard" "📬 $2 new mail(s) in \`$1\` account." ;}
  478. else
  479. _mwnotify() { echo "mutt-wizard: 📬 $2 new mail(s) in \`$1\` account." ;}
  480. fi
  481. fi
  482. _mwaddr() {
  483. mwaddr=$1
  484. mwaddr=${mwaddr/#\~/$HOME}
  485. mwaddr=${mwaddr#$mwmaildir/}
  486. mwaddr=${mwaddr%%/*}
  487. mkdir -p $mwmaildir/$mwaddr
  488. }
  489. _mwgenmuttaccs(){
  490. mkdir -p "$mwmuttdir" "$mwaccmuttdir"
  491. [ ! -f "$mwmuttrc" ] && echo "# vim: filetype=muttrc" > "$mwmuttrc" && echo "muttrc created."
  492. ! grep "source $mwsharerc" "$mwmuttrc" >/dev/null && echo "source $mwsharerc # mw-autogenerated" >> "$mwmuttrc"
  493. ! grep "source $mwgenmuttaccs" "$mwmuttrc" >/dev/null && echo "source $mwgenmuttaccs # mw-autogenerated" >> "$mwmuttrc"
  494. cat > "$mwgenmuttaccs" <<EOF
  495. # vim: filetype=muttrc
  496. # generated by mw
  497. macro index gM '<shell-escape>mw<enter>' "sync all mail"
  498. EOF
  499. }
  500. _mwgatheremails() {
  501. unset mwemails
  502. _mwgenmuttaccs
  503. if [ -f "$mwmbsyncrc" ]; then
  504. for store in $(sed -ne 's/^Path\s*//p' $mwmbsyncrc); do
  505. _mwaddr "$store"
  506. mwemails+=" $mwaddr"
  507. done
  508. fi
  509. if [ -d "$mwgetmaildir" ]; then
  510. for gmrc in $mwgetmaildir/*; do
  511. [ "${gmrc#$mwgetmaildir}" = "/*" ] && break
  512. store=$(sed -ne "s/^path\s*=\s*//p" $gmrc)
  513. store=${store/#\~/$HOME}
  514. _mwaddr "$store"
  515. mkdir -p "$store"/{cur,new,tmp}
  516. mwemails+=" $mwaddr"
  517. done
  518. fi
  519. mwemails="${mwemails/ /}"
  520. }
  521. _mwsyncandnotify() {
  522. mwaccmaildir="$mwmaildir/$mwaddr"
  523. if [ -f "$mwgetmaildir/$mwaddr" ]; then
  524. $mwgetmailbin --rcfile=$mwaddr --getmaildir=$mwgetmaildir
  525. else
  526. $mwmbsyncbin $mwaddr
  527. fi
  528. mwlastrun="$mwaccmaildir/.mw.lastrun"
  529. mwnew=$(find "$mwaccmaildir/INBOX/new/" "$mwaccmaildir/Inbox/new/" "$mwaccmaildir/inbox/new/" -type f -newer "$mwlastrun" 2> /dev/null)
  530. newcount=$(echo "$mwnew" | sed '/^\s*$/d' | wc -l)
  531. if [ "$newcount" -gt "0" ]; then
  532. _mwnotify "$mwaddr" "$newcount"
  533. for file in $mwnew; do
  534. # Extract subject and sender from mail.
  535. from=$(awk '/^From: / && ++n ==1,/^\<.*\>:/' "$file" | perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | \
  536. awk '{ $1=""; if (NF>=3)$NF=""; print $0 }' | sed 's/^[[:blank:]]*[\"'\''\<]*//;s/[\"'\''\>]*[[:blank:]]*$//')
  537. subject=$(awk '/^Subject: / && ++n == 1,/^\<.*\>: / && ++i == 2' "$file" | head -n-1 | perl -CS -MEncode -ne 'print decode("MIME-Header", $_)' | \
  538. sed 's/^Subject: //' | sed 's/^{[[:blank:]]*[\"'\''\<]*//;s/[\"'\''\>]*[[:blank:]]*$//' | tr -d '\n')
  539. _mwnotify "📧$from:" "$subject"
  540. done
  541. fi
  542. touch "$mwlastrun"
  543. }
  544. _mwsyncemails() {
  545. for mwaddr in $mwemails; do
  546. _mwsyncandnotify
  547. done
  548. rm $XDG_CONFIG_HOME/getmail/oldmail-* &>/dev/null
  549. echo notmuch new ...
  550. notmuch new &>/dev/null
  551. }
  552. _mwmuttemails() {
  553. for mwaddr in $mwemails; do
  554. _mwgenmwaccmuttrc
  555. done
  556. }
  557. _mwcheckcert() {
  558. for mwcrt in "/etc/ssl/certs/ca-certificates.crt" "/etc/pki/tls/certs/ca-bundle.crt" "/etc/ssl/ca-bundle.pem" \
  559. "/etc/pki/tls/cacert.pem" "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" "/etc/ssl/cert.pem" "/usr/local/share/ca-certificates/"
  560. do
  561. [ -f "$mwcrt" ] && mwsslcert="$mwcrt" && break
  562. done || { echo "CA Certificate not found. Please install one or link it to /etc/ssl/certs/ca-certificates.crt" && return 1 ;}
  563. }
  564. _mwcheckinternet() {
  565. # Checks for internet connection
  566. if type systemctl >/dev/null; then
  567. if ! systemctl --type service | grep net | grep active > /dev/null; then
  568. echo "No internet connection."
  569. return 1
  570. fi
  571. else
  572. if ! ping -q -c 1 1.1.1.1 > /dev/null; then
  573. echo "No internet connection (ping failed)."
  574. return 1
  575. fi
  576. fi
  577. }
  578. _mwsync() {
  579. unset mwemails
  580. mwtype="offline"
  581. # Run only if user logged in (prevent cron errors)
  582. if ! pgrep -u "$USER" >/dev/null; then
  583. echo "$USER not logged in; sync will not run."
  584. return 1
  585. fi
  586. # Run only if not already running in other instance
  587. if pgrep -x mbsync >/dev/null; then
  588. echo "mbsync is running."
  589. return 1
  590. fi
  591. if pgrep -x notmuch >/dev/null; then
  592. echo "notmuch is running."
  593. return 1
  594. fi
  595. _mwcheckinternet || return 1
  596. _mwaddr "$1"
  597. mwemails="$mwaddr"
  598. [ "$mwemails" = "" ] && _mwgatheremails && _mwsyncemails && _mwmuttemails && return 0
  599. _mwsyncemails
  600. return 0
  601. }
  602. trap 'echo -e "\033[0m\n"; exit' STOP INT ABRT KILL
  603. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
  604. if [ "$#" -gt 1 ]; then
  605. echo "Command or email or no parameter (=sync all). See --help."
  606. return 1
  607. fi
  608. type gpg >/dev/null 2>&1 && GPG="gpg" || GPG="gpg2"
  609. [ -z "$PASSWORD_STORE_DIR" ] && PASSWORD_STORE_DIR="$HOME/.password-store"
  610. [ -r "$PASSWORD_STORE_DIR/.gpg-id" ] &&
  611. "$GPG" --list-secret-keys $(cat "$PASSWORD_STORE_DIR/.gpg-id") >/dev/null 2>&1 || {
  612. printf "\`pass\` must be installed and initialized to encrypt passwords.\\nBe sure it is installed and run \`pass init <yourgpgemail>\`.\\n"
  613. printf "If you don't have a GPG public private key pair, run \`$GPG --full-gen-key\` first.\\n"
  614. exit
  615. }
  616. ! type "$prefix/bin/mbsync" >/dev/null && printf "\`mbsync\` must be installed to run mutt-wizard.\\n" && exit
  617. ! type "$prefix/bin/msmtp" >/dev/null && printf "\`msmtp\` must be installed.\\n" && exit
  618. ! ( type mutt >/dev/null || type neomutt >/dev/null ) && printf "\`mutt\` must be installed.\\n" && exit
  619. if [ "$1" = "" ]; then
  620. _mwsync
  621. else
  622. case "$1" in
  623. ls) _mwlist ;;
  624. add) _mwadd ;;
  625. pass) _mwpick "change the password of" && _mwgetpass ;;
  626. delete) _mwpick delete && _mwconfirm "delete the \`$mwaddr\` profile" && _mwdelete ;;
  627. purge) _mwpurge ;;
  628. cron) _mwcron ;;
  629. sync) _mwsync ;;
  630. *@*) _mwsync $1 ;;
  631. --version|-v) echo "mutt-wizard version 0.9" ;;
  632. --help|-h) cat <<EOF
  633. mw: mutt-wizard, auto-configure and sync email accounts for mutt,
  634. including mutt-independent sync of mail with \`isync\` or download of POP3 mail with \`getmail\`.
  635. Commands:
  636. add Add and autoconfigure an email address (9 max.)
  637. ls List configured accounts
  638. delete Pick an account to delete
  639. purge Delete all accounts and settings
  640. cron Enable or disable an autosync via cronjob
  641. sync sync/download mail based on config in $mwmbsyncrc and $mwgetmaildir
  642. --help|-h Print this message
  643. With no parameter all configured emails are synced and all account muttrc's are created.
  644. With a parameter containing a @, an mail is assumed and that account is synced.
  645. Config requirements:
  646. - mbsyncrc: "Path" ends in email
  647. - getmail: config file name = email, "path" ends in email
  648. EOF
  649. esac
  650. exit $?
  651. fi
  652. fi