search (6610B)
1 #!/usr/bin/env zsh 2 # 3 # Jaro Mail, your humble and faithful electronic postman 4 # 5 # a tool to easily and privately handle your e-mail communication 6 # 7 # Copyleft (C) 2010-2015 Denis Roio <jaromil@dyne.org> 8 # 9 # This source code is free software; you can redistribute it and/or 10 # modify it under the terms of the GNU Public License as published by 11 # the Free Software Foundation; either version 3 of the License, or 12 # (at your option) any later version. 13 # 14 # This source code is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 # Please refer to the GNU Public License for more details. 18 # 19 # You should have received a copy of the GNU Public License along with 20 # this source code; if not, write to: 21 # Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 ####################### 24 ## Search into maildirs 25 # using notmuch 26 27 28 # internal use 29 nm() { 30 fn "notmuch $*" 31 32 [[ -r "$MAILDIRS"/cache/notmuch/rc ]] || nm_setup 33 lock "$MAILDIRS"/cache/notmuch 34 notmuch --config="$MAILDIRS"/cache/notmuch/rc $* 35 _res=$? 36 unlock "$MAILDIRS"/cache/notmuch 37 [[ $_res = 0 ]] || { 38 error "Notmuch error on command: ${@}" 39 func "Returning status to caller: $_res" 40 } 41 return $_res 42 } 43 44 nm_setup() { 45 fn nm_setup 46 47 nm_dir="$MAILDIRS"/cache/notmuch 48 mkdir -p $nm_dir 49 50 # setup the default tags for all new messages 51 deftags="$1" 52 53 act "notmuch setup $deftags" 54 55 # read if there are other email aliases configured 56 [[ -r "$MAILDIRS"/Aliases.txt ]] && { 57 other_email="other_email" 58 _aliases=`cat "$MAILDIRS"/Aliases.txt` 59 _sep=\= 60 for i in ${(f)_aliases}; do 61 other_email+="${_sep}${i}" 62 _sep=";" 63 done 64 } 65 66 rm -f "$nm_dir"/rc 67 cat <<EOF > "$nm_dir"/rc 68 [database] 69 path=$MAILDIRS 70 71 [new] 72 tags=$deftags 73 ignore=tmp;cache;logs;outbox;incoming;zz.social;zz.bounces;zz.blacklist;zz.spam;Accounts;Groups;.mutt;webnomad;Aliases.txt;Filters;Identity.txt;Keyring;Manual.pdf;Mutt.txt;whitelist.abook;blacklist.abook;Applications.txt;Filters.sieve;Filters.txt 74 75 [maildir] 76 synchronize_flags=true 77 EOF 78 [[ "$name" = "" ]] || { 79 cat <<EOF >> "$nm_dir"/rc 80 81 [user] 82 name=$name 83 primary_email=$email 84 $other_email 85 EOF 86 } 87 } 88 89 nm_index() { 90 fn nm_index 91 92 # init the environment 93 read_account 94 notice "Indexing all mail archive" 95 act "please wait, this may take a while..." 96 nm_setup 97 nm new 98 nm tag +inbox +priv -unsorted folder:known 99 nm tag +inbox +priv -unsorted folder:sent 100 nm tag -inbox +priv -unsorted folder:priv 101 nm tag -inbox -priv +unsorted folder:unsorted 102 act "compressing database" 103 nm compact 104 notice "Indexing completed" 105 } 106 107 update_notmuch() { 108 fn update_notmuch 109 110 isfound notmuch && [[ -r $MAILDIRS/.notmuch/xapian ]] && { 111 notice "Updating notmuch indexes" 112 nm_setup 113 nm new 2>&1 | grep -v '^Note: Ignoring' 114 } 115 } 116 117 search() { 118 fn search $* 119 func "searching for ${#option_params} terms" 120 # launch the search with notmuch 121 _results="" 122 123 ztmp 124 nm search --output=files $* >> $ztmpfile 125 search_results=(`cat $ztmpfile`) 126 127 [[ $? = 0 ]] || { 128 error "notmuch search failed with an error" 129 return 1 130 } 131 132 notice "${#search_results} matches found" 133 } 134 135 136 # run a search with notmuch and show results with alot 137 alot_search() { 138 fn alot_search $* 139 140 read_account 141 nm_setup 142 143 notice "Searching emails for: ${=option_params}" 144 145 # read if there are other email aliases configured 146 [[ -r "$MAILDIRS"/Aliases.txt ]] && { 147 other_email="aliases" 148 _aliases=`cat "$MAILDIRS"/Aliases.txt` 149 _sep=" = " 150 for i in ${(f)_aliases}; do 151 other_email+="${_sep}${i}" 152 _sep="," 153 done 154 } 155 156 # setup alot to show results 157 mkdir -p "$MAILDIRS"/cache/alot 158 cat <<EOF > "$MAILDIRS"/cache/alot/rc 159 160 editor_cmd = jaro edit 161 edit_headers_whitelist = From,To,Cc,Subject 162 displayed_headers = From,To,Cc,Bcc,Subject,User-Agent 163 auto_remove_unread = True 164 honor_followup_to = True 165 hooksfile = $MAILDIRS/cache/alot/hooks.py 166 initial_command = search tag:inbox 167 prefer_plaintext = True 168 tabwidth = 4 169 user_agent = Jaro Mail <http://jaromail.dyne.org> 170 171 [bindings] 172 i = search tag:inbox 173 p = search tag:priv 174 u = search tag:unsorted 175 / = prompt 'search ' 176 l = prompt 'search ' 177 backspace = bclose 178 179 [accounts] 180 [[$account]] 181 realname = $name 182 address = $email 183 sendmail_command = jaro queue 184 sent_box = maildir:///$MAILDIRS/sent 185 $other_email 186 [[[abook]]] 187 type = shellcommand 188 command = jaro -q search addr 189 regexp = (?P<name>.+)\s*<(?P<email>.*.+?@.+?)> 190 191 [tags] 192 [[inbox]] 193 translated = ★ 194 [[priv]] 195 translated = ⚡ 196 [[attachment]] 197 translated = ⚓ 198 [[unsorted]] 199 translated = ? 200 [[flagged]] 201 translated = ⚑ 202 normal = '','','light red','','light red','' 203 focus = '','','light red','','light red','' 204 [[unread]] 205 translated = ☉ 206 [[replied]] 207 translated = ⏎ 208 [[encrypted]] 209 translated = ⚷ 210 [[signed]] 211 translated = ✍ 212 [[filters]] 213 translated = ⚙ 214 [[mailinglist]] 215 translated = ☰ 216 EOF 217 218 alot -c "$MAILDIRS"/cache/alot/rc -n "$MAILDIRS"/cache/notmuch/rc \ 219 search $* 220 221 return $? 222 } 223 224 backup() { 225 fn backup $* 226 dst=${option_params[1]} 227 shift 1 option_params 228 expr=${option_params} 229 req=(dst expr) 230 ckreq 231 232 maildircheck "$dst" 233 [[ $? = 0 ]] || { 234 error "First argument of backup must be a destination maildir" 235 return 1 236 } 237 238 [[ "$expr" = "" ]] && { 239 error "No expression set for backup, please indicate what you want to backup" 240 act "For example: date:10y..2y (all mails older than 1 year up to 10 years ago)" 241 act "Or a simple search string, all expressions can be verified using search." 242 return 1 243 } 244 245 id=`datestamp`.$RANDOM 246 c=0 247 248 notice "Backup of mails matched by search expression" 249 act "expression: $expr" 250 act "destination folder: $dst" 251 252 read_account 253 nm_setup 254 255 search ${=expr} 256 257 [[ $DRYRUN = 0 ]] && { 258 for i in ${search_results}; do 259 refile $i $dst 260 [[ $? = 0 ]] || { 261 # bail out on every single error 262 error "Error refiling emails to destination maildir" 263 error "Operation aborted" 264 return 1 265 } 266 done 267 } 268 return 0 269 }