getunseen 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/bin/bash
  2. # password previously encrypted:
  3. # openssl enc -aes-256-cbc -iter 99999 -a -pass file:/etc/machine-id -out "$passfile"
  4. sep="################################################"
  5. server="posteo.de"
  6. user=danter
  7. me="${0##*/}"
  8. tag=Zaphod
  9. passfile="$HOME/.local/share/$me.txt"
  10. countonly=0
  11. debug=0
  12. after=''
  13. while getopts "cda:" opt; do
  14. case $opt in
  15. c)
  16. countonly=1
  17. ;;
  18. d)
  19. debug=1
  20. ;;
  21. a)
  22. after="$OPTARG"
  23. ;;
  24. esac
  25. done
  26. debug() {
  27. [[ "$debug" != 1 ]] && return
  28. (($# > 1)) && printf "$@" || echo "$1"
  29. }
  30. remCR() {
  31. # removes carriage returns from output
  32. # works directly on $out
  33. out="${out//$'\r'/}"
  34. }
  35. mimedecode() {
  36. # only if Perl & its Encode module are available
  37. # https://superuser.com/a/972248
  38. x="$(perl -CS -MEncode -e "print decode('MIME-Header', '$out')" 2>/dev/null)"
  39. [ -n "$x" ] && out="$x" || out="$@"
  40. }
  41. # Start the session
  42. coproc SSL { openssl s_client -connect "$server":993 -crlf -quiet 2>/dev/null; } || exit 1
  43. # Make sure openssl is dead when exiting
  44. trap 'kill $SSL_PID 2>/dev/null' EXIT
  45. # LOGIN
  46. line="$tag login $user@$server"
  47. echo "$line $(openssl enc -aes-256-cbc -iter 99999 -a -pass file:/etc/machine-id -d -in "$passfile")" >&${SSL[1]}
  48. debug "$line super_secret_password"
  49. # Catch output loop. Remove the printf if you want it quiet
  50. while read -r out; do
  51. debug '%q\n' "$out"
  52. # This reply tells us the server is done and waiting for more input
  53. [[ "$out" == "$tag "* ]] && break
  54. done <&${SSL[0]}
  55. debug "$sep"
  56. # Now we're talking to the server
  57. echo "$tag lsub INBOX \"*\"" >&${SSL[1]}
  58. debug "$tag lsub INBOX \"*\""
  59. # Catch output loop. Remove the printf if you want it quiet
  60. subs=(); count=0
  61. while read -r out; do
  62. debug '%q\n' "$out"
  63. # This is the first stepof the info we're after
  64. [[ "$out" == '* LSUB '* ]] && {
  65. out="${out#*\".\" }"
  66. remCR # remove carriage return!
  67. subs[count++]="$out"
  68. continue
  69. }
  70. # Again, this reply tells us the server is done and waiting for more input
  71. [[ "$out" == "$tag "* ]] && break
  72. done <&${SSL[0]}
  73. debug "$sep"
  74. # Now we're talking to the server
  75. declare -A unseen=()
  76. for i in "${subs[@]}"; do
  77. # 1. select folder
  78. echo "$tag select $i" >&${SSL[1]}
  79. debug "$tag select $i"
  80. # Catch output loop.
  81. found=0
  82. while read -r out; do
  83. debug '%q\n' "$out"
  84. # no need to search _each_ folder for unseen messages!
  85. [[ "$out" == '* OK [UNSEEN '* ]] && found=1
  86. [[ "$out" == "$tag "* ]] && break
  87. done <&${SSL[0]}
  88. # 2. search for unseen mail
  89. if [[ "$found" == 1 ]]; then
  90. echo "$tag search (unseen)" >&${SSL[1]}
  91. debug "$tag search (unseen)"
  92. # Catch output loop.
  93. while read -r out; do
  94. debug '%q\n' "$out"
  95. # 3. if SEARCH is followed by a space there are unseen messages
  96. [[ "$out" == '* SEARCH '* ]] && {
  97. out="${out#*SEARCH }"
  98. remCR
  99. # 4. asssign to array
  100. unseen[$i]="$out"
  101. continue
  102. }
  103. [[ "$out" == "$tag "* ]] && break
  104. done <&${SSL[0]}
  105. fi
  106. done
  107. debug "$sep"
  108. final=""
  109. # now also get subject lines
  110. for folder in "${!unseen[@]}"; do
  111. # select folder
  112. echo "$tag select $folder" >&${SSL[1]}
  113. debug "$tag select $folder"
  114. while read -r out; do
  115. debug '%q\n' "$out"
  116. # This reply tells us the server is done and waiting for more input
  117. [[ "$out" == "$tag "* ]] && break
  118. done <&${SSL[0]}
  119. # make array from numerical mail ids
  120. arr=(${unseen[$folder]})
  121. # removes leading & trailing quotes from folder name, for final display only
  122. folder="${folder#\"}";folder="${folder#\'}";folder="${folder%\"}";folder="${folder%\'}"
  123. final="${final}\n$folder"
  124. if [[ "$countonly" == 1 ]]; then
  125. final="$final: ${#arr[@]} unread mail"
  126. (( ${#arr[@]} > 1 )) && final="${final}s" || final="$final"
  127. else
  128. for i in "${arr[@]}"; do
  129. echo "$tag fetch $i body.peek[header.fields (subject)]" >&${SSL[1]}
  130. debug "$tag fetch $i body.peek[header.fields (subject)]"
  131. # Catch output loop.
  132. while read -r out; do
  133. debug '%q\n' "$out"
  134. [[ "$out" == "Subject: "* ]] && {
  135. out="${out#Subject: }"
  136. remCR
  137. [[ "${out,,}" == '=?utf-8?'*'?=' ]] && mimedecode
  138. final="$final\n - $out"
  139. continue
  140. }
  141. [[ "$out" == "$tag "* ]] && break
  142. done <&${SSL[0]}
  143. done
  144. fi
  145. done
  146. final="${final#\\n}"
  147. final="${final%\\n}"
  148. # That's all we wanted. Logging out
  149. echo "$tag logout" >&${SSL[1]}
  150. debug "$tag logout"
  151. while read -r out; do
  152. debug '%q\n' "$out"
  153. [[ "$out" == "$tag "* ]] && break
  154. done <&${SSL[0]}
  155. # at this point the openssl coproc should quit.
  156. debug "$sep"
  157. if [[ "$final" != "" ]]; then
  158. [[ "$after" != "" ]] && final="$final$after"
  159. echo -e "$final"
  160. fi