@@ -105,12 +105,16 @@ update_filters() {
105105 newlock " $ff "
106106 cat << EOF >> "$ff "
107107# generated on ` date`
108- typeset -Al filter_from
109- typeset -alU filter_own
110- typeset -Al filter_to
108+ typeset -gAl filter_from
109+ typeset -galU filter_own
110+ typeset -gAl filter_to
111+ typeset -galU filter_whitelist
112+ typeset -galU filter_blacklist
111113filter_from=()
112114filter_own=()
113115filter_to=()
116+ filter_whitelist=()
117+ filter_blacklist=()
114118
115119EOF
116120
@@ -587,10 +591,16 @@ if header :contains "Sender" "mailman-bounce" {
587591
588592EOF
589593
590- set -A sieve_filter_map ${(kv)filter_to}
594+ sieve_filter_map=()
595+ for fil in ${(k)filter_to} ; do
596+ sieve_filter_map[$fil ]=" ${filter_to[$fil]} "
597+ done
591598 sieve_complex_filter ' if header :contains [ "To","Cc" ] '
592599
593- set -A sieve_filter_map ${(kv)filter_from}
600+ sieve_filter_map=()
601+ for fil in ${(k)filter_from} ; do
602+ sieve_filter_map[$fil ]=" ${filter_from[$fil]} "
603+ done
594604 sieve_complex_filter ' if header :contains [ "From","Sender" ] '
595605
596606 # #############################################################
@@ -635,6 +645,164 @@ EOF
635645 return 0
636646} # end of update()
637647
648+ sieve_import_addressbook_entry () {
649+ local target_list=" $1 "
650+ local raw_address=" $2 "
651+ local old_list=" $list "
652+ local old_addressbook=" $ADDRESSBOOK "
653+
654+ list=" $target_list "
655+ ADDRESSBOOK=" ${target_list} .abook"
656+ [[ -r " $MAILDIRS /$ADDRESSBOOK " ]] || create_addressbook
657+
658+ e_addr=()
659+ print - " From: $raw_address " | e_parse From > /dev/null || {
660+ list=" $old_list "
661+ ADDRESSBOOK=" $old_addressbook "
662+ return 1
663+ }
664+
665+ local email name
666+ for email in ${(k)e_addr} ; do
667+ name=" ${e_addr[$email]} "
668+ [[ -z " $name " ]] && name=" $email "
669+ lookup_email " $email "
670+ [[ $? = 0 ]] || insert_address " $email " " $name " > /dev/null
671+ done
672+
673+ list=" $old_list "
674+ ADDRESSBOOK=" $old_addressbook "
675+ return 0
676+ }
677+
678+ sieve_import_grouped_values () {
679+ local sieve_file=" $1 "
680+ awk '
681+ /^# / {
682+ section=substr($0, 3)
683+ next
684+ }
685+ /^[[:space:]]*"/ {
686+ value=$0
687+ sub(/^[[:space:]]*"/, "", value)
688+ sub(/".*/, "", value)
689+ print section "|" value
690+ }
691+ ' " $sieve_file "
692+ }
693+
694+ sieve_import_route_rules () {
695+ local sieve_file=" $1 "
696+ awk '
697+ /header :contains/ && /fileinto :create/ {
698+ destination=$0
699+ sub(/^.*fileinto :create "/, "", destination)
700+ sub(/".*/, "", destination)
701+
702+ if (destination == "INBOX" || destination == "priv" ||
703+ destination == "Spam" || destination == "unsorted" ||
704+ destination == "zz.blacklist" || destination == "zz.bounces") {
705+ next
706+ }
707+
708+ if ($0 ~ /\[ "To","Cc" \]/) {
709+ header="to"
710+ } else if ($0 ~ /\[ "From","Sender" \]/) {
711+ header="from"
712+ } else {
713+ next
714+ }
715+
716+ pattern=$0
717+ sub(/^.*\][[:space:]]*"/, "", pattern)
718+ sub(/".*/, "", pattern)
719+ if (pattern != "") {
720+ print header " " pattern " move " destination
721+ }
722+ }
723+ ' " $sieve_file "
724+ }
725+
726+ sieve_import_append_unique () {
727+ local target_file=" $1 "
728+ local line=" $2 "
729+
730+ touch " $target_file "
731+ grep -Fqx " $line " " $target_file " 2> /dev/null || print - " $line " >> " $target_file "
732+ }
733+
734+ sieve_import_is_account_address () {
735+ local needle=" ${1: l} "
736+
737+ [[ -d " $MAILDIRS /Accounts" ]] || return 1
738+ find " $MAILDIRS /Accounts" -type f -exec awk ' /^email/ { print tolower($2) }' {} \; | \
739+ grep -Fqx " $needle "
740+ }
741+
742+ sieve_import_alias_entry () {
743+ local raw_address=" $1 "
744+
745+ e_addr=()
746+ print - " From: $raw_address " | e_parse From > /dev/null || return 1
747+
748+ local email
749+ for email in ${(k)e_addr} ; do
750+ sieve_import_is_account_address " $email " && continue
751+ sieve_import_append_unique " $MAILDIRS /Aliases.txt" " $email "
752+ done
753+ return 0
754+ }
755+
756+ sieve_import () {
757+ fn sieve_import $*
758+ local sieve_file=" $1 "
759+ req=(MAILDIRS sieve_file)
760+ freq=($sieve_file )
761+ ckreq || return 1
762+
763+ [[ -r " $sieve_file " ]] || {
764+ error " Sieve file not readable: $sieve_file "
765+ return 1
766+ }
767+
768+ notice " Import Sieve filters from $sieve_file "
769+ local section value entry
770+ local imported_blacklist=0
771+ local imported_whitelist=0
772+ local imported_filters=0
773+ local imported_aliases=0
774+
775+ for entry in ${(f)" $( sieve_import_grouped_values " $sieve_file " ) " } ; do
776+ section=" ${entry%% |* } "
777+ value=" ${entry#* |} "
778+ case " $section " in
779+ zz.blacklist)
780+ sieve_import_addressbook_entry blacklist " $value " && \
781+ imported_blacklist=$(( $imported_blacklist + 1 ))
782+ ;;
783+ INBOX)
784+ sieve_import_addressbook_entry whitelist " $value " && \
785+ imported_whitelist=$(( $imported_whitelist + 1 ))
786+ ;;
787+ priv)
788+ sieve_import_alias_entry " $value " && \
789+ imported_aliases=$(( $imported_aliases + 1 ))
790+ ;;
791+ esac
792+ done
793+
794+ for entry in ${(f)" $( sieve_import_route_rules " $sieve_file " ) " } ; do
795+ sieve_import_append_unique " $MAILDIRS /Filters.txt" " $entry "
796+ imported_filters=$(( $imported_filters + 1 ))
797+ done
798+
799+ act " blacklist addresses imported: $imported_blacklist "
800+ act " whitelist addresses imported: $imported_whitelist "
801+ act " aliases imported: $imported_aliases "
802+ act " filter rules imported: $imported_filters "
803+ return 0
804+ }
805+
638806cmd_filter () {
639807 filter_maildir ${option_params}
640808 exitcode=$?
0 commit comments