Commit 6a3c9b1f 6a3c9b1f4cbe71a4013f4218d438e0fd68b05a3b by Sergey Poznyakoff

Implementation of sieve "redirect" action. Kept apart from other actions due to …

…the lack of API support.
1 parent be88df89
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 sieve's "redirect" action.
19
20 (use-modules (ice-9 popen))
21
22 (define PATH-SENDMAIL "/usr/lib/sendmail")
23 (define sieve-my-email "")
24
25 ;;; Bounce a message.
26 ;;; Current mailutils API does not provide a way to send a message
27 ;;; specifying its recipients (like "sendmail -t foo@bar.org" does),
28 ;;; hence the need for this function.
29 (define (sieve-message-bounce message addr-list)
30 (catch #t
31 (lambda ()
32 (let ((port (open-output-pipe
33 (apply string-append
34 (append
35 (list
36 PATH-SENDMAIL
37 " -oi -t ")
38 (map
39 (lambda (addr)
40 (string-append addr " "))
41 addr-list))))))
42 ;; Write headers
43 (for-each
44 (lambda (hdr)
45 (display (string-append (car hdr) ": " (cdr hdr)) port)
46 (newline port))
47 (mu-message-get-header-fields message))
48 (newline port)
49 ;; Write body
50 (let ((body (mu-message-get-body message)))
51 (do ((line (mu-body-read-line body) (mu-body-read-line body)))
52 ((eof-object? line) #f)
53 (display line port)))
54 (close-output-port port)))
55 (lambda args
56 (runtime-error LOG_ERR "redirect: Can't send message")
57 (write args))))
58
59 ;;; rfc3028 says:
60 ;;; "Implementations SHOULD take measures to implement loop control,"
61 ;;; We do this by appending an "X-Sender" header to each message
62 ;;; being redirected. If one of the "X-Sender" headers of the message
63 ;;; contains our email address, we assume it is a loop and bail out.
64
65 (define (sent-from-me? msg)
66 (call-with-current-continuation
67 (lambda (x)
68 (for-each
69 (lambda (hdr)
70 (if (and (string=? (car hdr) "X-Sender")
71 (string=? (mu-address-get-email (cdr hdr))
72 sieve-my-email))
73 (x #t)))
74 (mu-message-get-header-fields sieve-current-message))
75 #f)))
76
77 ;;; redirect action
78 (define (action-redirect address)
79 (if sieve-my-email
80 (cond
81 ((sent-from-me? sieve-current-message)
82 (runtime-error LOG_ERR "redirect: Loop detected"))
83 (else
84 (let ((out-msg (mu-message-copy sieve-current-message)))
85 (mu-message-set-header out-msg "X-Sender" sieve-my-email)
86 (sieve-message-bounce out-msg (list address)))))
87 (sieve-message-bounce out-msg (list address))))
88
89 ;;; Register action
90 (if sieve-parser
91 (sieve-register-action "redirect" action-redirect 'string))
92
93