Commit cdb95d01 cdb95d01e4ead871b5d10543a32dd28ea5740a0d by Sergey Poznyakoff

vacation: read message body from the file

* doc/texinfo/sieve.texi: Document recent changes to vacation.
* libmu_sieve/extensions/vacation.c (vacation_reply): Handle
the "rfc2822" tag: if set together with :file, treat the file
as the RFC2822 message.  Otherwise, read message body from it.
* sieve/tests/vacation.at: Add test for :rfc2822
1 parent 42ca2c2e
......@@ -1453,20 +1453,35 @@ pipe "/usr/sbin/maidag --url smtp://gray@@mail.gnu.org"
@deftypefn Action {} vacation [:days @var{ndays}(number)] @
[:subject @var{subject}(string)] @
[:aliases @var{addrlist}(string-list)] @
[:addresses @var{noreply-address}(string-list)] @
[:noreply @var{noreply-address}(string-list)] @
[:reply_regex @var{expr}(string)] @
[:reply_prefix @var{prefix}(string)] @
@var{reply-text}(string)
[:sender @var{email}(string)] @
[:database @var{path}(string)] @
[:return_address @var{email}(string)] @
[:header @var{headers}(string-list)] @
[:mime] @
[:always_reply] @
[:rfc2822] @
[:file] @
@var{text}(string)
@*Syntax:
@smallexample
require "vacation";
vacation @var{args};
@end smallexample
@*Description:
The @code{vacation} action returns a message with @var{reply-text} to
The @code{vacation} action returns a message with @var{text} to
the sender. It is intended to inform the sender that the recipient is
not currently reading his mail.
If the @code{:file} tag is present, @var{text} is treated as the name
of the file to read the body of the reply message from. When used together
with tag @code{:rfc2822}, the file should be formatted as a valid RFC
2822 message, i.e. headers followed by empty line and body. Headers
must not contain @samp{To}, @samp{From}, and @samp{Subject}, as these
will be generated automatically.
If the @code{:subject} tag is given, its argument sets the subject of
the message. Otherwise, the subject is formed by prefixing original
subject with @samp{Re:}, or @var{prefix}, given with the
......@@ -1475,6 +1490,11 @@ matching extended regular expression @var{expr} (@code{:reply_regex}
tag) are stripped from the subject line. If @code{:reply_regex} is not
specified, the default regexp is @samp{^re: *}.
Another headers can be added using the @code{:header} tag. Its
argument is a list of header strings, each one having the form
@samp{"@var{name}:@var{value}"}. Additional whitespace is allowed on
both sides of the colon.
The @code{:aliases} tag instructs @code{vacation} to handle messages
for any address in @var{addrlist} in the same manner as those received
for the user's principal email.
......@@ -1496,13 +1516,17 @@ exclusion list is:
^MAILER-DAEMON@@.*
@end smallexample
New entries can be added to this list using @code{:addresses} tag.
New entries can be added to this list using @code{:noreply} tag.
The @code{:days} tag sets the @dfn{reply interval}. A reply is sent to
each sender once in @var{ndays} days. GNU Sieve keeps track of
sender addresses and dates in a DBM file @file{.vacation} stored in
the user's home directory. This tag is available only if Mailutils is
compiled with DBM support.
sender addresses and dates in file @file{.vacation} stored in
the user's home directory. The file name can be changed using the
@code{:database} tag.
The tag @code{:always_reply} instructs vacation to respond to the
message regardless of whether the user email is listed as a recipient
for the message.
@end deftypefn
@node GNU Extensions
......
......@@ -93,7 +93,7 @@ enum mu_buffer_type
If pat==NULL, any reads from that stream will return EOF. */
#define MU_IOCTL_NULLSTREAM_SET_PATTERN 0
/* Set pattern class for reads: Argument int *pclass (a class mask
from mailutils/cctype.h */
from mailutils/cctype.h) */
#define MU_IOCTL_NULLSTREAM_SET_PATCLASS 1
/* Limit stream size. Argument: mu_off_t *psize; */
#define MU_IOCTL_NULLSTREAM_SETSIZE 2
......
......@@ -24,6 +24,7 @@
[:reply_prefix <prefix: string>]
[:sender <email: string>]
[:database <path: string>]
[:rfc2822]
[:file]
[:mime]
[:always_reply]
......@@ -637,6 +638,9 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
mu_strerror (rc));
return -1;
}
if (mu_sieve_tag_lookup (tags, "rfc2822", NULL))
{
rc = mu_stream_to_message (instr, &newmsg);
mu_stream_unref (instr);
if (rc)
......@@ -651,6 +655,58 @@ vacation_reply (mu_sieve_machine_t mach, mu_list_t tags, mu_message_t msg,
}
else
{
mu_stream_t text_stream;
mu_transport_t trans[2];
rc = mu_memory_stream_create (&text_stream, MU_STREAM_RDWR);
if (rc)
{
mu_stream_unref (instr);
mu_sieve_error (mach,
_("%lu: cannot create memory stream: %s"),
(unsigned long) mu_sieve_get_message_num (mach),
mu_strerror (rc));
return -1;
}
rc = mu_stream_copy (text_stream, instr, 0, NULL);
mu_stream_unref (instr);
if (rc == 0)
rc = mu_stream_write (text_stream, "", 1, NULL);
if (rc)
{
mu_sieve_error (mach,
_("%lu: failed reading from %s: %s"),
(unsigned long) mu_sieve_get_message_num (mach),
text,
mu_strerror (rc));
return -1;
}
rc = mu_stream_ioctl (text_stream, MU_IOCTL_TRANSPORT,
MU_IOCTL_OP_GET, trans);
if (rc)
{
mu_stream_unref (text_stream);
mu_sieve_error (mach,
"%lu: mu_stream_ioctl: %s",
(unsigned long) mu_sieve_get_message_num (mach),
mu_strerror (rc));
return -1;
}
if (build_mime (mach, tags, &mime, msg, (char const *) trans[0]))
{
mu_stream_unref (text_stream);
return -1;
}
mu_mime_get_message (mime, &newmsg);
mu_message_unref (newmsg);
mu_stream_unref (text_stream);
}
}
else
{
if (build_mime (mach, tags, &mime, msg, text))
return -1;
mu_mime_get_message (mime, &newmsg);
......@@ -814,6 +870,7 @@ static mu_sieve_tag_def_t vacation_tags[] = {
{"always_reply", SVT_VOID},
{"return_address", SVT_STRING},
{"header", SVT_STRING_LIST},
{"rfc2822", SVT_VOID},
{NULL}
};
......
......@@ -253,10 +253,10 @@ VACATION on msg uid 2
VACATION on msg uid 3
])
MUT_SIEVE_EXT_TEST([reply from file],[vac05],
MUT_SIEVE_EXT_TEST([reply from RFC2822 file],[vac05],
[require "vacation";
vacation :database "vacation.db" :always_reply :file "reply";
vacation :database "vacation.db" :always_reply :rfc2822 :file "reply";
],
[AT_DATA([reply],[X-Mail-Processor: sieve
......@@ -320,5 +320,79 @@ VACATION on msg uid 2
VACATION on msg uid 3
])
MUT_SIEVE_EXT_TEST([reply body from file],[vac06],
[require "vacation";
vacation :database "vacation.db" :always_reply :file "reply";
],
[AT_DATA([reply],[I'm on vacation right now.
I will attend to your message as soon as I'm back.
Best regards,
Ty Coon
])
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/sieve.mbox,mailbox)
MTA_DIAG=`pwd`/mta.diag
MTA_APPEND=1
export MTA_DIAG MTA_APPEND
sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -f ./mailbox prog || exit 1
cat ./mta.diag
],
[ENVELOPE FROM: foobar@nonexistent.net
ENVELOPE TO: <coyote@desert.example.org>
0: In-Reply-To: Your message of Sun May 6 22:16:47 2001
1: Subject: =?UTF-8?Q?Re:_I_have_a_present_for_you?=
2: To: coyote@desert.example.org
3: Content-Transfer-Encoding: 8bit
4: Content-Type: text/plain;charset=UTF-8
5: MIME-Version: 1.0
6:
7: I'm on vacation right now.
8: I will attend to your message as soon as I'm back.
9:
10: Best regards,
11: Ty Coon
12:
END OF MESSAGE
ENVELOPE FROM: foobar@nonexistent.net
ENVELOPE TO: <b1ff@de.res.example.com>
0: In-Reply-To: Your message of TBD
1: Subject: =?UTF-8?Q?Re:_$$$_YOU,_TOO,_CAN_BE_A_MILLIONAIRE!_$$$?=
2: To: b1ff@de.res.example.com
3: Content-Transfer-Encoding: 8bit
4: Content-Type: text/plain;charset=UTF-8
5: MIME-Version: 1.0
6:
7: I'm on vacation right now.
8: I will attend to your message as soon as I'm back.
9:
10: Best regards,
11: Ty Coon
12:
END OF MESSAGE
ENVELOPE FROM: foobar@nonexistent.net
ENVELOPE TO: <bar@dontmailme.org>
0: References: <200112232808.fERKR9N16790@dontmailme.org>
1: In-Reply-To: Your message of Fri, 28 Dec 2001 23:28:08 +0200
2: <200112232808.fERKR9N16790@dontmailme.org>
3: Subject: =?UTF-8?Q?Re:_Coffee?=
4: To: bar@dontmailme.org
5: Content-Transfer-Encoding: 8bit
6: Content-Type: text/plain;charset=UTF-8
7: MIME-Version: 1.0
8:
9: I'm on vacation right now.
10: I will attend to your message as soon as I'm back.
11:
12: Best regards,
13: Ty Coon
14:
END OF MESSAGE
],
[VACATION on msg uid 1
VACATION on msg uid 2
VACATION on msg uid 3
])
m4_popdef([MUT_SIEVE_EXT_NAME])
......