Rewrite as module. Change
initialization of the syntax tables. (handle-exception,sieve-verbose-print): New macro (action-fileinto,action-keep,action-stop,action-discard): Produce verbose diagnostics if required. (sieve-run): Take thunk as an argument. Report implicit keep if it returns #t and the verbose mode is on. (sieve-main): Take thunk as an argument.
Showing
1 changed file
with
98 additions
and
48 deletions
... | @@ -17,23 +17,66 @@ | ... | @@ -17,23 +17,66 @@ |
17 | 17 | ||
18 | ;;;; This module provides core functionality for the sieve scripts. | 18 | ;;;; This module provides core functionality for the sieve scripts. |
19 | 19 | ||
20 | (set! %load-path (append %load-path (list sieve-libdir))) | 20 | (define-module (mailutils sieve-core)) |
21 | (use-modules (mailutils)) | 21 | |
22 | (use-modules (mailutils mailutils)) | ||
23 | |||
24 | ;;; Set to #t when parsing | ||
25 | (define-public sieve-parser #f) | ||
26 | |||
27 | ;;; Name of the input source | ||
28 | (define-public sieve-source "UNKNOWN") | ||
22 | 29 | ||
23 | ;;; The email address for originator of error messages. Should be <> | 30 | ;;; The email address for originator of error messages. Should be <> |
24 | ;;; but current mailutils API is unable to parse and handle it. | 31 | ;;; but current mailutils API is unable to parse and handle it. |
25 | ;;; Site administrators are supposed to replace it with the | 32 | ;;; Site administrators are supposed to replace it with the |
26 | ;;; actual value. | 33 | ;;; actual value. |
27 | (define sieve-daemon-email "MAILER-DAEMON@localhost") | 34 | (define-public sieve-daemon-email "MAILER-DAEMON@localhost") |
28 | 35 | ||
29 | ;;; The email address of the user whose mailbox is being processed. | 36 | ;;; The email address of the user whose mailbox is being processed. |
30 | ;;; If #f, it will be set by sieve-main | 37 | ;;; If #f, it will be set by sieve-main |
31 | (define sieve-my-email #f) | 38 | (define-public sieve-my-email #f) |
32 | 39 | ||
33 | (define SIEVE-WARNING "Warning") | 40 | (define SIEVE-WARNING "Warning") |
34 | (define SIEVE-ERROR "Error") | 41 | (define SIEVE-ERROR "Error") |
35 | (define SIEVE-NOTICE "Notice") | 42 | (define SIEVE-NOTICE "Notice") |
36 | 43 | ||
44 | (defmacro handle-exception (. expr) | ||
45 | `(catch 'mailutils-error | ||
46 | (lambda () ,@expr) | ||
47 | (lambda (key . args) | ||
48 | (runtime-message SIEVE-ERROR | ||
49 | "In function " (car args) ": " | ||
50 | (apply format #f | ||
51 | (list-ref args 1) (list-ref args 2)) | ||
52 | (let ((error-code | ||
53 | (car (list-ref args (1- (length args)))))) | ||
54 | (if (= error-code 0) | ||
55 | "" | ||
56 | (string-append | ||
57 | "; Error code: " | ||
58 | (number->string error-code) | ||
59 | " - " | ||
60 | (mu-strerror error-code)))))))) | ||
61 | |||
62 | ;;; Set to #t if verbose action listing is requested | ||
63 | (define-public sieve-verbose #f) | ||
64 | |||
65 | (defmacro sieve-verbose-print (action . rest) | ||
66 | `(if sieve-verbose | ||
67 | (let ((uid (false-if-exception | ||
68 | (mu-message-get-uid sieve-current-message)))) | ||
69 | (display ,action) | ||
70 | (display " on msg uid ") | ||
71 | (display uid) | ||
72 | (let ((args (list ,@rest))) | ||
73 | (cond ((not (null? args)) | ||
74 | (display ": ") | ||
75 | (for-each | ||
76 | display | ||
77 | args)))) | ||
78 | (newline)))) | ||
79 | |||
37 | ;;; List of open mailboxes. | 80 | ;;; List of open mailboxes. |
38 | ;;; Each entry is: (list MAILBOX-NAME OPEN-FLAGS MBOX) | 81 | ;;; Each entry is: (list MAILBOX-NAME OPEN-FLAGS MBOX) |
39 | (define sieve-mailbox-list '()) | 82 | (define sieve-mailbox-list '()) |
... | @@ -46,7 +89,7 @@ | ... | @@ -46,7 +89,7 @@ |
46 | (let ((slot (assoc name sieve-mailbox-list))) | 89 | (let ((slot (assoc name sieve-mailbox-list))) |
47 | (if slot | 90 | (if slot |
48 | (list-ref slot 2) | 91 | (list-ref slot 2) |
49 | (let ((mbox (mu-mailbox-open name flags))) | 92 | (let ((mbox (false-if-exception (mu-mailbox-open name flags)))) |
50 | (if mbox | 93 | (if mbox |
51 | (set! sieve-mailbox-list (append | 94 | (set! sieve-mailbox-list (append |
52 | sieve-mailbox-list | 95 | sieve-mailbox-list |
... | @@ -78,14 +121,14 @@ | ... | @@ -78,14 +121,14 @@ |
78 | filename))))) | 121 | filename))))) |
79 | 122 | ||
80 | ;;; Comparators | 123 | ;;; Comparators |
81 | (cond | 124 | (define-public sieve-standard-comparators |
82 | (sieve-parser | 125 | (list (list "i;octet" string=?) |
83 | (sieve-register-comparator "i;octet" string=?) | 126 | (list "i;ascii-casemap" string-ci=?))) |
84 | (sieve-register-comparator "i;ascii-casemap" string-ci=?))) | ||
85 | 127 | ||
86 | ;;; Stop statement | 128 | ;;; Stop statement |
87 | 129 | ||
88 | (define (sieve-stop) | 130 | (define-public (sieve-stop) |
131 | (sieve-verbose-print "STOP") | ||
89 | (throw 'sieve-stop)) | 132 | (throw 'sieve-stop)) |
90 | 133 | ||
91 | ;;; Basic five actions: | 134 | ;;; Basic five actions: |
... | @@ -94,14 +137,16 @@ | ... | @@ -94,14 +137,16 @@ |
94 | 137 | ||
95 | ;;; fileinto | 138 | ;;; fileinto |
96 | 139 | ||
97 | (define (action-fileinto filename) | 140 | (define-public (action-fileinto filename) |
98 | (let ((name (sieve-expand-filename filename))) | 141 | (let ((name (sieve-expand-filename filename))) |
142 | (sieve-verbose-print "FILEINTO" "delivering into " name) | ||
99 | (if (string? name) | 143 | (if (string? name) |
100 | (let ((outbox (sieve-mailbox-open name "cw"))) | 144 | (let ((outbox (sieve-mailbox-open name "cw"))) |
101 | (cond | 145 | (cond |
102 | (outbox | 146 | (outbox |
147 | (handle-exception | ||
103 | (mu-mailbox-append-message outbox sieve-current-message) | 148 | (mu-mailbox-append-message outbox sieve-current-message) |
104 | (mu-message-delete sieve-current-message)) | 149 | (mu-message-delete sieve-current-message))) |
105 | (else | 150 | (else |
106 | (runtime-message SIEVE-ERROR | 151 | (runtime-message SIEVE-ERROR |
107 | "Could not open mailbox " name)))) | 152 | "Could not open mailbox " name)))) |
... | @@ -112,20 +157,23 @@ | ... | @@ -112,20 +157,23 @@ |
112 | 157 | ||
113 | ;;; keep -- does nothing worth mentioning :^) | 158 | ;;; keep -- does nothing worth mentioning :^) |
114 | 159 | ||
115 | (define (action-keep) | 160 | (define-public (action-keep) |
116 | (mu-message-delete sieve-current-message #f)) | 161 | (sieve-verbose-print "KEEP") |
162 | (handle-exception | ||
163 | (mu-message-delete sieve-current-message #f))) | ||
117 | 164 | ||
118 | ;;; discard | 165 | ;;; discard |
119 | 166 | ||
120 | (define (action-discard) | 167 | (define-public (action-discard) |
121 | (mu-message-delete sieve-current-message)) | 168 | (sieve-verbose-print "DISCARD" "marking as deleted") |
169 | (handle-exception | ||
170 | (mu-message-delete sieve-current-message))) | ||
122 | 171 | ||
123 | ;;; Register standard actions | 172 | ;;; Register standard actions |
124 | (cond | 173 | (define-public sieve-standard-actions |
125 | (sieve-parser | 174 | (list (list "keep" action-keep '() '()) |
126 | (sieve-register-action "keep" action-keep '() '()) | 175 | (list "discard" action-discard '() '()) |
127 | (sieve-register-action "discard" action-discard '() '()) | 176 | (list "fileinto" action-fileinto (list 'string) '()))) |
128 | (sieve-register-action "fileinto" action-fileinto (list 'string) '()))) | ||
129 | 177 | ||
130 | ;;; Some utilities. | 178 | ;;; Some utilities. |
131 | 179 | ||
... | @@ -225,7 +273,7 @@ | ... | @@ -225,7 +273,7 @@ |
225 | 273 | ||
226 | ;;;; Standard tests: | 274 | ;;;; Standard tests: |
227 | 275 | ||
228 | (define (test-address header-list key-list . opt-args) | 276 | (define-public (test-address header-list key-list . opt-args) |
229 | (let ((comp (find-comp opt-args)) | 277 | (let ((comp (find-comp opt-args)) |
230 | (match (find-match opt-args)) | 278 | (match (find-match opt-args)) |
231 | (part (cond | 279 | (part (cond |
... | @@ -275,7 +323,7 @@ | ... | @@ -275,7 +323,7 @@ |
275 | key-list) | 323 | key-list) |
276 | #f)))) | 324 | #f)))) |
277 | 325 | ||
278 | (define (test-size key-size . comp) | 326 | (define-public (test-size key-size . comp) |
279 | (let ((size (mu-message-get-size sieve-current-message))) | 327 | (let ((size (mu-message-get-size sieve-current-message))) |
280 | (cond | 328 | (cond |
281 | ((null? comp) ;; An extension. | 329 | ((null? comp) ;; An extension. |
... | @@ -287,7 +335,7 @@ | ... | @@ -287,7 +335,7 @@ |
287 | (else | 335 | (else |
288 | (runtime-message SIEVE-ERROR "test-size: unknown comparator " comp))))) | 336 | (runtime-message SIEVE-ERROR "test-size: unknown comparator " comp))))) |
289 | 337 | ||
290 | (define (test-envelope part-list key-list . opt-args) | 338 | (define-public (test-envelope part-list key-list . opt-args) |
291 | (let ((comp (find-comp opt-args)) | 339 | (let ((comp (find-comp opt-args)) |
292 | (match (find-match opt-args))) | 340 | (match (find-match opt-args))) |
293 | (call-with-current-continuation | 341 | (call-with-current-continuation |
... | @@ -309,7 +357,7 @@ | ... | @@ -309,7 +357,7 @@ |
309 | part-list) | 357 | part-list) |
310 | #f)))) | 358 | #f)))) |
311 | 359 | ||
312 | (define (test-exists header-list) | 360 | (define-public (test-exists header-list) |
313 | (call-with-current-continuation | 361 | (call-with-current-continuation |
314 | (lambda (exit) | 362 | (lambda (exit) |
315 | (for-each (lambda (hdr) | 363 | (for-each (lambda (hdr) |
... | @@ -319,7 +367,7 @@ | ... | @@ -319,7 +367,7 @@ |
319 | header-list) | 367 | header-list) |
320 | #t))) | 368 | #t))) |
321 | 369 | ||
322 | (define (test-header header-list key-list . opt-args) | 370 | (define-public (test-header header-list key-list . opt-args) |
323 | (let ((comp (find-comp opt-args)) | 371 | (let ((comp (find-comp opt-args)) |
324 | (match (find-match opt-args))) | 372 | (match (find-match opt-args))) |
325 | (call-with-current-continuation | 373 | (call-with-current-continuation |
... | @@ -360,45 +408,46 @@ | ... | @@ -360,45 +408,46 @@ |
360 | (cons "over" #f))) | 408 | (cons "over" #f))) |
361 | (define comparator (list (cons "comparator" 'string))) | 409 | (define comparator (list (cons "comparator" 'string))) |
362 | 410 | ||
363 | (cond | 411 | (define-public sieve-standard-tests |
364 | (sieve-parser | 412 | (list |
365 | (sieve-register-test "address" | 413 | (list "address" |
366 | test-address | 414 | test-address |
367 | (list 'string-list 'string-list) | 415 | (list 'string-list 'string-list) |
368 | (append address-part comparator match-type)) | 416 | (append address-part comparator match-type)) |
369 | (sieve-register-test "size" | 417 | (list "size" |
370 | test-size | 418 | test-size |
371 | (list 'number) | 419 | (list 'number) |
372 | size-comp) | 420 | size-comp) |
373 | (sieve-register-test "envelope" | 421 | (list "envelope" |
374 | test-envelope | 422 | test-envelope |
375 | (list 'string-list 'string-list) | 423 | (list 'string-list 'string-list) |
376 | (append comparator address-part match-type)) | 424 | (append comparator address-part match-type)) |
377 | (sieve-register-test "exists" | 425 | (list "exists" |
378 | test-exists | 426 | test-exists |
379 | (list 'string-list) | 427 | (list 'string-list) |
380 | '()) | 428 | '()) |
381 | (sieve-register-test "header" | 429 | (list "header" |
382 | test-header | 430 | test-header |
383 | (list 'string-list 'string-list) | 431 | (list 'string-list 'string-list) |
384 | (append comparator match-type)) | 432 | (append comparator match-type)) |
385 | (sieve-register-test "false" #f '() '()) | 433 | (list "false" #f '() '()) |
386 | (sieve-register-test "true" #t '() '()))) | 434 | (list "true" #t '() '()))) |
387 | 435 | ||
388 | ;;; runtime-message | 436 | ;;; runtime-message |
389 | 437 | ||
390 | (define (runtime-message level . text) | 438 | (define-public (runtime-message level . text) |
391 | (let ((msg (apply string-append | 439 | (let ((msg (apply string-append |
392 | (map (lambda (x) | 440 | (map (lambda (x) |
393 | (format #f "~A" x)) | 441 | (format #f "~A" x)) |
394 | (append | 442 | (append |
395 | (list "(in " sieve-source ") ") | 443 | (list "(in " sieve-source ") ") |
396 | text))))) | 444 | text))))) |
445 | (if sieve-current-message | ||
397 | (mu-message-set-header sieve-current-message | 446 | (mu-message-set-header sieve-current-message |
398 | (string-append "X-Sieve-" level) | 447 | (string-append "X-Sieve-" level) |
399 | msg) | 448 | msg)) |
400 | (if (isatty? (current-output-port)) | 449 | (if (isatty? (current-error-port)) |
401 | (display (string-append level ": " msg "\n"))))) | 450 | (display (string-append level ": " msg "\n") (current-error-port))))) |
402 | 451 | ||
403 | (define (guimb?) | 452 | (define (guimb?) |
404 | (catch #t | 453 | (catch #t |
... | @@ -411,7 +460,7 @@ | ... | @@ -411,7 +460,7 @@ |
411 | (define sieve-mailbox #f) | 460 | (define sieve-mailbox #f) |
412 | (define sieve-current-message #f) | 461 | (define sieve-current-message #f) |
413 | 462 | ||
414 | (define (sieve-run) | 463 | (define (sieve-run thunk) |
415 | (if (not sieve-my-email) | 464 | (if (not sieve-my-email) |
416 | (set! sieve-my-email (mu-username->email))) | 465 | (set! sieve-my-email (mu-username->email))) |
417 | ; (DEBUG 1 "Mailbox: " sieve-mailbox) | 466 | ; (DEBUG 1 "Mailbox: " sieve-mailbox) |
... | @@ -421,10 +470,11 @@ | ... | @@ -421,10 +470,11 @@ |
421 | ((> n count) #f) | 470 | ((> n count) #f) |
422 | (set! sieve-current-message | 471 | (set! sieve-current-message |
423 | (mu-mailbox-get-message sieve-mailbox n)) | 472 | (mu-mailbox-get-message sieve-mailbox n)) |
424 | (catch 'sieve-stop | 473 | (and (catch 'sieve-stop |
425 | sieve-process-message | 474 | thunk |
426 | (lambda args | 475 | (lambda args |
427 | #f))) | 476 | #f)) |
477 | (sieve-verbose-print "IMPLICIT KEEP"))) | ||
428 | (sieve-close-mailboxes))) | 478 | (sieve-close-mailboxes))) |
429 | 479 | ||
430 | (define (sieve-command-line) | 480 | (define (sieve-command-line) |
... | @@ -434,7 +484,8 @@ | ... | @@ -434,7 +484,8 @@ |
434 | (append (list "<temp-file>") args))) | 484 | (append (list "<temp-file>") args))) |
435 | (lambda args (command-line)))) | 485 | (lambda args (command-line)))) |
436 | 486 | ||
437 | (define (sieve-main) | 487 | (define-public (sieve-main thunk) |
488 | (handle-exception | ||
438 | (cond | 489 | (cond |
439 | ((not (guimb?)) | 490 | ((not (guimb?)) |
440 | (let* ((cl (sieve-command-line)) | 491 | (let* ((cl (sieve-command-line)) |
... | @@ -443,13 +494,12 @@ | ... | @@ -443,13 +494,12 @@ |
443 | (cadr cl) | 494 | (cadr cl) |
444 | (string-append (mu-mail-directory) "/" | 495 | (string-append (mu-mail-directory) "/" |
445 | (passwd:name (mu-getpwuid (getuid))))))) | 496 | (passwd:name (mu-getpwuid (getuid))))))) |
446 | ; (DEBUG 2 "mailbox name " name) | 497 | |
447 | (set! sieve-mailbox (mu-mailbox-open name "rw")) | 498 | (set! sieve-mailbox (mu-mailbox-open name "rw")) |
448 | (sieve-run) | 499 | (sieve-run thunk) |
449 | (mu-mailbox-expunge sieve-mailbox) | 500 | (mu-mailbox-expunge sieve-mailbox) |
450 | (mu-mailbox-close sieve-mailbox))) | 501 | (mu-mailbox-close sieve-mailbox))) |
451 | (else | 502 | (else |
452 | ; (DEBUG 1 "Using current-mailbox") | ||
453 | (set! sieve-mailbox current-mailbox) | 503 | (set! sieve-mailbox current-mailbox) |
454 | (sieve-run)))) | 504 | (sieve-run thunk))))) |
455 | 505 | ... | ... |
-
Please register or sign in to post a comment