Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

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