New file. Implements "vacation" extension.
Showing
1 changed file
with
201 additions
and
0 deletions
guimb/scm/vacation.scm
0 → 100644
1 | ;;;; GNU mailutils - a suite of utilities for electronic mail | ||
2 | ;;;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. | ||
3 | ;;;; | ||
4 | ;;;; This program is free software; you can redistribute it and/or modify | ||
5 | ;;;; it under the terms of the GNU General Public License as published by | ||
6 | ;;;; the Free Software Foundation; either version 2, or (at your option) | ||
7 | ;;;; any later version. | ||
8 | ;;;; | ||
9 | ;;;; This program is distributed in the hope that it will be useful, | ||
10 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | ;;;; GNU General Public License for more details. | ||
13 | ;;;; | ||
14 | ;;;; You should have received a copy of the GNU General Public License | ||
15 | ;;;; along with this program; if not, write to the Free Software | ||
16 | ;;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | |||
18 | ;;;; This module provides "vacation" extension | ||
19 | |||
20 | ;;; vacation example: | ||
21 | ;;; vacation :days 18 | ||
22 | ;;; :aliases ["gray@gnu.org", "gray@mirddin.farlep.net"] | ||
23 | ;;; :addresses ["bug-mailutils@gnu.org","bug-inetutils@gnu.org"] | ||
24 | ;;; :subject "I'm on vacation" | ||
25 | ;;; :mime | ||
26 | ;;; text: | ||
27 | ;;; I am on vacation until July 22. I'll attend your message as soon | ||
28 | ;;; as I'm back. | ||
29 | ;;; . | ||
30 | ;;; | ||
31 | ;;; Additionally, the :sender flag may be used to debug the script. | ||
32 | |||
33 | ;; Debugging flag | ||
34 | (define vacation-debug #f) | ||
35 | |||
36 | ;; Each entry is (cons SENDER DATE), where SENDER is the sender email | ||
37 | ;; address (lowercase) and DATE is the date where the first message | ||
38 | ;; from this sender was received. | ||
39 | (define vacation-db '()) | ||
40 | |||
41 | (define (vacation-downcase name) | ||
42 | (let ((len (string-length name))) | ||
43 | (do ((i 0 (1+ i))) | ||
44 | ((= i len) name) | ||
45 | (string-set! name i (char-downcase (string-ref name i)))))) | ||
46 | |||
47 | (define (vacation-db-name) | ||
48 | (let ((pwd (mu-getpwuid (getuid)))) | ||
49 | (string-append (vector-ref pwd 5) "/.vacation.db"))) | ||
50 | |||
51 | (define (vacation-db-load) | ||
52 | (catch #t | ||
53 | (lambda () | ||
54 | (call-with-input-file (vacation-db-name) | ||
55 | (lambda (port) | ||
56 | (set! vacation-db (read port))))) | ||
57 | (lambda args args))) | ||
58 | |||
59 | (define (vacation-db-save) | ||
60 | (catch #t | ||
61 | (lambda () | ||
62 | (let ((mask (umask #o077))) | ||
63 | (call-with-output-file (vacation-db-name) | ||
64 | (lambda (port) | ||
65 | (display ";; Vacation database file\n" port) | ||
66 | (display ";; Generated automatically. Please do not edit\n" | ||
67 | port) | ||
68 | (write vacation-db port))) | ||
69 | (umask mask))) | ||
70 | (lambda args args))) | ||
71 | |||
72 | (define (vacation-db-lookup sender days) | ||
73 | (vacation-db-load) | ||
74 | (let ((val (assoc (vacation-downcase sender) vacation-db))) | ||
75 | (cond | ||
76 | (val | ||
77 | (cond | ||
78 | ((and days (> days 0)) | ||
79 | (<= (- (car (gettimeofday)) (cdr val)) (* days 86400))) | ||
80 | (else | ||
81 | #t))) | ||
82 | (else | ||
83 | #f)))) | ||
84 | |||
85 | (define (vacation-db-update msg) | ||
86 | (let* ((sender (vacation-downcase (mu-message-get-sender msg))) | ||
87 | (date (car (gettimeofday))) | ||
88 | (val (assoc sender vacation-db))) | ||
89 | (cond | ||
90 | (val | ||
91 | (set-cdr! val date)) | ||
92 | (else | ||
93 | (set! vacation-db (append vacation-db (list | ||
94 | (cons sender date))))))) | ||
95 | (vacation-db-save)) | ||
96 | |||
97 | (define vacation-noreply-senders | ||
98 | (list | ||
99 | ".*-REQUEST@.*" | ||
100 | ".*-RELAY@.*" | ||
101 | ".*-OWNER@.*" | ||
102 | "OWNER-.*" | ||
103 | "postmaster@.*" | ||
104 | "UUCP@.*" | ||
105 | "MAILER@.*" | ||
106 | "MAILER-DAEMON@.*")) | ||
107 | |||
108 | (define (vacation-reply? msg aliases addresses days) | ||
109 | (let ((sender (mu-message-get-sender msg))) | ||
110 | (and | ||
111 | ;; No message will be sent unless an alias is part of either | ||
112 | ;; the "To:" or "Cc:" headers of the mail. | ||
113 | (call-with-current-continuation | ||
114 | (lambda (exit) | ||
115 | (for-each | ||
116 | (lambda (hdr) | ||
117 | (cond | ||
118 | (hdr | ||
119 | (let ((count (mu-address-get-count hdr))) | ||
120 | (do ((i 1 (1+ i))) | ||
121 | ((> i count) #f) | ||
122 | (let ((email (mu-address-get-email hdr i))) | ||
123 | (for-each | ||
124 | (lambda (alias) | ||
125 | (if (string-ci=? alias email) | ||
126 | (exit #t))) | ||
127 | aliases))))))) | ||
128 | (list (mu-message-get-header msg "To") | ||
129 | (mu-message-get-header msg "Cc"))) | ||
130 | #f)) | ||
131 | |||
132 | ;; Messages sent from one of the vacation-noreply-senders are not | ||
133 | ;; responded to | ||
134 | (call-with-current-continuation | ||
135 | (lambda (exit) | ||
136 | (do ((explist (append vacation-noreply-senders addresses) | ||
137 | (cdr explist))) | ||
138 | ((null? explist) #t) | ||
139 | (let ((rx (make-regexp (car explist) regexp/icase))) | ||
140 | (if (regexp-exec rx sender) | ||
141 | (exit #f)))))) | ||
142 | |||
143 | ;; Messages with Precedence: bulk or junk are not responded to | ||
144 | (let ((prec (mu-message-get-header msg "Precedence"))) | ||
145 | (not (and prec (or (string-ci=? prec "bulk") | ||
146 | (string-ci=? prec "junk"))))) | ||
147 | |||
148 | ;; Senders already in the database get no response | ||
149 | (not (vacation-db-lookup sender days))))) | ||
150 | |||
151 | (define (vacation-send-reply subject text sender) | ||
152 | (let ((sender "root@localhost") | ||
153 | (mesg (mu-message-create))) | ||
154 | (let ((port (mu-message-get-port mesg "w"))) | ||
155 | (display text port) | ||
156 | (close-output-port port)) | ||
157 | (mu-message-set-header mesg "X-Sender" | ||
158 | (string-append "vacation.scm, " mu-package-string) | ||
159 | #t) | ||
160 | (mu-message-send mesg #f #f sender))) | ||
161 | |||
162 | (define (action-vacation text . opt) | ||
163 | (set! vacation-debug (member #:debug opt)) | ||
164 | (if vacation-debug | ||
165 | (begin | ||
166 | (display sieve-current-message)(display ": "))) | ||
167 | (cond | ||
168 | ((vacation-reply? sieve-current-message | ||
169 | (append (list sieve-my-email) | ||
170 | (sieve-get-opt-arg opt #:aliases '())) | ||
171 | (sieve-get-opt-arg opt #:addresses '()) | ||
172 | (sieve-get-opt-arg opt #:days #f)) | ||
173 | (vacation-send-reply (sieve-get-opt-arg | ||
174 | opt #:subject | ||
175 | (string-append "Re: " | ||
176 | (mu-message-get-header | ||
177 | sieve-current-message | ||
178 | "Subject"))) | ||
179 | text | ||
180 | (sieve-get-opt-arg | ||
181 | opt #:sender | ||
182 | (mu-message-get-sender sieve-current-message))) | ||
183 | (vacation-db-update sieve-current-message) | ||
184 | (if vacation-debug | ||
185 | (display "WILL REPLY\n"))) | ||
186 | (vacation-debug | ||
187 | (display "WILL NOT REPLY\n")))) | ||
188 | |||
189 | ;;; Register action | ||
190 | (if sieve-parser | ||
191 | (sieve-register-action "vacation" | ||
192 | action-vacation | ||
193 | (list 'string) | ||
194 | (list (cons "days" 'number) | ||
195 | (cons "addresses" 'string-list) | ||
196 | (cons "aliases" 'string-list) | ||
197 | (cons "subject" 'string) | ||
198 | (cons "sender" 'string) | ||
199 | (cons "mime" #f) | ||
200 | (cons "debug" #f)))) | ||
201 |
-
Please register or sign in to post a comment