Subject: Three new drafts and a question

From: Jutta Degener <[email-masked]>
Date: Wed, 23 Apr 2003 13:14:05 -0700

I sent out three new sieve drafts last week that may be of interest:

 <http://www.ietf.org/internet-drafts/draft-degener-sieve-copy-00.txt>
  	
	fileinto :copy, redirect :copy -- keyword parameter that
	prevents cancelling the implicit "keep".

 <http://www.ietf.org/internet-drafts/draft-degener-sieve-editheader-00.txt>

  	Deleting, adding, and changing message header fields.

 <http://www.ietf.org/internet-drafts/draft-degener-sieve-multiscript-00.txt>
  	
	Sequential execution of (unrelated) sieve scripts by the
	environment.  A meta-feature -- it doesn't define new sieve
	language elements -- that's interesting in particular in
	contrast to Cyrus's "include" draft.

There may or may not be another one for fileinto in the wings.
It's about Kjetil's open issue 0.3 b):

Some implementations of "fileinto" create IMAP folders on the
fly if they don't exist; others don't.  (They redirect to
the inbox instead.)  Sieve doesn't proscribe either way.

My own implementation used to only reuse existing folders; but now
that we're thinking about creating them on demand in conjunction
with the "variables" extension, I'm getting requests for a way
for a user to express their intention; something like 

	fileinto :create 	"If it doesn't exist, create it"
or
	fileinto :exists	"If it doesn't exist, redirect to INBOX."

or something in that area.

Is anyone hearing similar requests from their users?
Have you thought about the issue and come to conclusions for
your own releases?

Jutta

---

From: "Nigel Swinson" <[email-masked]>
Date: Thu, 24 Apr 2003 15:09:26 +0100

> I sent out three new sieve drafts last week that may be of interest:

As if this list wasn't busy enough at the moment ;o)

> prevents cancelling the implicit "keep".

Spelling mistake in first line of this paragraph... should read "possible"

   It is possibly to generate sieve code that perfectly
    <snip>

Yeah I like this idea.  I found the whole interaction between implicit keep
and discard really difficult to get my head round.  this extension sounds
like it will help.

>   Deleting, adding, and changing message header fields.

Heh, was thinking of authoring one of these soon.  Thanks for beating me to
it.  I haven't been able to digest it in detail yet but it looks ok to me on
a first pass :o)

> contrast to Cyrus's "include" draft.

When you are doing server/domain level filtering, you might want to allow a
server script to file into a specific user folder.  So you could have a user
folder called "Bulk" or "Spam" or something, and the server level script
could have ask to file a message into that users "Bulk" folder (rather than
just delete it).

In MailSite we have server and domain level scripts, and there seemed to be
a few possible interpretations of the "fileinto" command.  Either it could:

a) "fileinto" a folder on the local file system
b) file into a folder of the target user (at server/domain level there may
be many recipients in the envelope at this stage)
c) file into a folder of the server/domain postmaster.

Sadly we chose a), which I thought was going to be the most useful, but now
we have a need to do b) as well.  So we were wondering if fileinto should
have some kind of arg to say:

    fileinto :filesystem "DirectoryName";

To file into the "DirectoryName" folder on the file system of the MTA, or

    fileinto "Spam";

To fileinto the Spam folder of the recipient (if local) or

    fileinto :user "Postmaster" "Spam";

To file into the Spam folder of the Postmaster mailbox.

I know most of this is probably a spearate extension, but the draft as it
stands implies that it's only Keep and implicit Keep actions in previous
scripts that can allow subsequent scripts to be executed, and I'm not sure
that's true.

I think fileinto(s) in a previous script should "change the location" of
where implicit keep would post the message.  Explicit Keep could probably
change the filed location to Inbox (or add Inbox if there were multiple
fileintos in a previous script).  Another fileinto would change the filed
location (or add the new folder if there were multiple fileintos in a
previous script).

I think we need to think through all this pretty carefully, but it'll be
worth it...

Cheers,

Nigel

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 25 Apr 2003 01:08:52 +0200

>   	prevents cancelling the implicit "keep".

great idea!  a small typo, quotes are missing around ":copy" in

   Syntax:
        "fileinto" [:copy] <folder: string>
        "redirect" [:copy] <folder: string>

>     	Deleting, adding, and changing message header fields.

| 5. Action replaceheader
|    [...]
|    The field-name is mandatory and always matched as a
|    case-insensitive us-ascii string.

I take it you mean an exact match (:is) ?  the following shouldn't
work:

   replaceheader "Original-*" :newname "${1}"

but it would be interesting, eh?  actually, :matches could be the
mandatory match type for the field-name, I don't think it influences
the rest.  if you do

   replaceheader "Original-*" :newname "${1}" :matches "*foo" :newvalue "${1}"

this will _not_ work, since the value match will run after the field
name match, and thus destroy the contents of the back references.

btw, it is interesting that this extension requires variable
references in strings to be resolved inside the action itself.  it
makes me wonder if I should add a "Note to implementers" in the
variables draft about this.

| 7. Security Considerations
|    [...]
|    A sieve filter that removes headers may unwisely destroy
|    evidence about the path a header has taken.

perhaps tampering with "Received" should be explicitly forbidden.
(even with that restriction, the above warning must be kept.)

>   	contrast to Cyrus's "include" draft.

yes, I think they both are useful.  this is for site configuration,
"include" is for user convenience.

| 4. Locality of script actions
|    [...]
|    For sieve engines that implement the "variables" extension,
|    variable state is not carried over between scripts.

I think this is the right choice, since a set of scripts using
"include" should be considered _one_ script and variable state thus
carry over in that single script.  this also fits in with:

|    The "stop;" command ends the execution of its single
|    containing script, not of scripts in general.

so the "return" in Cyrus's draft is still useful.

I agree that a capability string is unnecessary.

>   with the "variables" extension, I'm getting requests for a way for
>   a user to express their intention; something like
>   

it is unfortunate that behaviour is undefined.  both behaviours are
useful, so I think both should be in the draft.  well, the draft could
instead mandate fileinto to file into INBOX if the folder doesn't
exist and ":create" isn't specified.  this can also serve as a hint to
new implementers of Sieve.

-- 
Kjetil T.

---

From: [email-masked]
Date: Thu, 24 Apr 2003 11:08:49 -0700 (PDT)

> 	prevents cancelling the implicit "keep".

This isn't a problem I've seen myself, but it seems like a reasonable
thing to have and the implementation burden should be low.

>   	Deleting, adding, and changing message header fields.

I see several issues here:

(1) The use of separate field-name/field-value arguments to specify a header
    field matches up nicely with the header test. But it effectively precludes
    specification of more than one header in a single addheader or
    deleteheader command. I prefer the approach of having a single argument,
    which can either be a string specifying a single field or a list
    specifying multiple fields.

(2) I sure wish we'd allowed signed integers as numbers in the base sieve
    specification. If we had them available we could use negative indices
    to represent offsets from the last occurence of a given field. This in
    turn would make it possible to specify ranges of fields in deleteheader
    fairly easily. I wish I had an alternative to suggest here that would
    give us this functionality, but I don't.

(3) I see considerable value in addheader and deleteheader. Replaceheader,
    however, goes a bit too far for my tastes. Do we really need this? Is
    it worth the complexity?

> 	contrast to Cyrus's "include" draft.

Hmm. The approach taken here is very similar but not quite identical to the
approach I've used to combine multiple scripts. We agree in that any script
that ends in an implicit keep in effect cedes control to the next script in the
sequence, and that the explicit actions reject, fileinto, and redirect that
cancel implicit keep prevent subsequent scripts from running.

The place where we differ is in the handling of explicit keep. The draft calls
for subsequent scripts to be called. I don't do that; in my implementation an
explicit keep prevents subsequent scripts from acting.

I don't think this is something I can change at this point either. One of the
things that's often done is to have some kind of filtering in a system-level
sieve script. That script may elect to discard a message. I wanted the ability
for users to override such system-level decisions by issuing an explicit "keep"
in their scripts. This trick got documented and is now in use.

I suppose I could always implement an option to control how explicit keeps
affect the operation of multiple scripts.

There's also one semantics issue I see here: RFC 3028 says that fileinto
"INBOX" and "keep" are equivalent in an IMAP environment. This specification
tweaks that equivalence somewhat.

> Have you thought about the issue and come to conclusions for

We opted for the other course: We create new folders on demand. Thus far I
don't believe we've gotten requests for "only file to folders that already
exist", but of course that could change once variables support is available.

I have no problem with implementing such an extension in any case.

				Ned

---

From: Jutta Degener <[email-masked]>
Date: Thu, 24 Apr 2003 19:19:31 -0700

On Thu, Apr 24, 2003 at 11:08:49AM -0700, [email-masked] wrote:
[editheader]
>     I prefer the approach of having a single argument,

Hm, you mean a real ["foo", "bar"] list, or a chunk of text
that becomes the header?

If you're using ["foo", "bar"], you'll quickly run into the
lack of list operations and -variables.

If you're using a big chunk of text, I think it will still have
to be parsed into names and values and checked or, more likely,
reformatted.  I don't like doing that, not so much for efficiency
reasons but because it pretends to the script writer that they're
touching the true outgoing header when I really can't let them
do that.

Do you have a usage scenario where a single string vs. multiple
makes a big difference?

>     to represent offsets from the last occurence of a given field.

Yeah, that would be nice, but I couldn't get it to work either.

>     however, goes a bit too far for my tastes. Do we really need this? Is

The "replaceheader" command started out as a "tagheader" command
that just gave its user a choice of adding a prefix or a suffix.

The original audience for this was users with message stores that
don't support direct fileinto.  They can tag their messages by adding
or changing the Subject: line, and then filter based on the Subject
line in their browsers.

Then people wanted an "untagheader" command, and didn't generally
respond well to the complexity of picking a header vs. the simplicity
of what I let them do it once they had it, so "replaceheader"
replaced the "tag" and "untag" versions and got a little more solid.

We can argue whether :newname has any business being there, though.

> that ends in an implicit keep in effect cedes control to the next script
> in the sequence, and that the explicit actions reject, fileinto, and
> redirect that cancel implicit keep prevent subsequent scripts from running.
> 

Interesting.  I've had some push-back about that, too, where colleagues
felt (and probably still feel) uncomfortable that the system would react
to an explicit command with this big-brotheresque "well, you're saying you
want to keep the message, but what you _really_ may want is to give it the
default trailing script treatment".

> for users to override such system-level decisions by issuing an explicit
> "keep" in their scripts. This trick got documented and is now in use.

We'd just have used "fileinto "INBOX"" for that, but okay.  And of
course you might not have "fileinto".

> tweaks that equivalence somewhat.

Yeah, I know...

I guess the alternative here is to make explicit keep and implicit
keep once again behave differently.  That's ugly, but it does seem
to be closer to expectations.

Did you ever run into a situation where that gave you trouble --
where you wished you could have an explicit implicit keep?

Jutta

---

From: [email-masked]
Date: Thu, 24 Apr 2003 21:20:54 -0700 (PDT)

> Hm, you mean a real ["foo", "bar"] list, or a chunk of text

I mean ["Comment: 1", "Comment: 2"].

> lack of list operations and -variables.

I don't think so. But we can handle that fairly easily by saying empty
strings add nothing.

> touching the true outgoing header when I really can't let them

I agree. I don't think the chunk of text approach is appropriate.

> Do you have a usage scenario where a single string vs. multiple

Not really. It just looks better to have all of the fields added in a
single operation.

> Yeah, that would be nice, but I couldn't get it to work either.

OK. Just wanted to check and see if there was something I was missing.

> We can argue whether :newname has any business being there, though.

Good point. Even if we retain replaceheader I'd argue that :newname should
go. You can always get the effect by deleting and adding.

There's also the question of the interaction of a replaceheader
aimed at the third instance of one field being renamed to a field that
already exists.

> course you might not have "fileinto".

Good point. Since I implement it I tend to forget it is optional...

> where you wished you could have an explicit implicit keep?

I don't believe I ever have. But it is hard to predict what is going to
happen once variables are available. I suspect they are going to
change usage patterns fairly substantially, and it is hard to know which
of these little quirks of the language are going to prove problematic.

				Ned

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 26 Apr 2003 23:54:44 +0200

>   > [editheader]

interesting, the draft says "replaceheader".  "editheader" is a better
name, especially if :newname goes away.

>   > [Ned Freed]:

I don't follow.  could you write an example?

list of header names makes sense with deleteheader, but for addheader
I think it makes more sense to only support a list of values.

  addheader "Comment" ["1", "2"];

you could do a list of header names with replaceheader as well, but
the counting is a bit tricky, and I think it's complex enough already.
you can always do N separate replaceheader instead.

>   Good point. Even if we retain replaceheader I'd argue that
>   :newname should go. You can always get the effect by deleting and
>   adding.

if there is only one header, yes.

   if header "Message-ID" :matches "<*@*>" {
       deleteheader "Message-ID";
       addheader "Old-Message-ID" "<${1}@${2}>";
       addheader "Message-ID" "<[email-masked]>";
   }

if there is more than one instance of a header, you can't get at one
of them in particular.  the content in ${N} could be from the first or
last or a random one.

this might be an issue for the variables draft, it could say that the
search must be short-circuited (given, but perhaps not strongly enough
worded in existing documents), and the search done in first to last
order.  would that be appropriate?

-- 
Kjetil T.

---

From: [email-masked]
Date: Sun, 27 Apr 2003 10:17:49 -0700 (PDT)

> I don't follow.  could you write an example?

addheader ["Comment: 1", "Comment: 2"];

>   addheader "Comment" ["1", "2"];

Ick. This merely adds complexity without actually adding the issue:

addheader ["Comment: 1", "Content-description: 2"];

> you can always do N separate replaceheader instead.

I think replaceheader is too complex. Think for a bit about the right way to
handle modifications to encoded words. It gets very very nasty in a great big
hurry.  For example, suppose I have an encoded-word in iso-8859-1 and I use
replaceheader to change an a with an accent grave to an a with an ogonek.
What does the result look like? Are adjacent encoded-words affected? Should
they be?

> of them in particular.  the content in ${N} could be from the first or

This argues for adding index capabilites to header, which is something we
need independently of this facility.

> order.  would that be appropriate?

I have no problem with nailing down first to last scanning order for multiple
versions of the same field. But keep in mind that this doesn't solve the entire
problem: You can potentially have three iterates in a header operation: A list
of field names, a list of field values, and more then one instance of a given
field. I suspect different implementations organize their iterates differently
(I iterate on field, field instance and finally field value myself). I don't
think we want to mandate a particular way of ordering  the iterates.

Of course you can work around the iteration order by using simpler tests,
whereas you can't work around the problem of multiple fields other than
by specifying the short-circuit behavior to some extent.

				Ned

---

From: Jutta Degener <[email-masked]>
Date: Mon, 28 Apr 2003 10:48:06 -0700

> name, especially if :newname goes away.

The extension is "editheader",  comprising the three commands
"addheader", "deleteheader", and "replaceheader".

>   addheader "Comment" ["1", "2"];

Sorry, but I'd rather stick to simple name/value pairs.

> order.  would that be appropriate?

I'd rather leave it undefined, so that people have more freedom
in how to implement their search.  If a script writer needs a
specific order, they can always force it by separating the statements.

Jutta

---

From: Marc Mutz <[email-masked]>
Date: Mon, 28 Apr 2003 20:02:24 +0200

On Sunday 27 April 2003 19:17, [email-masked] wrote:
<snip>
> I think replaceheader is too complex.

But it's needed in the real world. Adding/removing the [mailing list] 
tag to/from the subject line and fixing mangled/mangling reply-to 
headers is popular among people who need to handle large (or large 
amounts of) mailing list traffic.

> Think for a bit about the right
> way to handle modifications to encoded words. It gets very very nasty
> in a great big hurry.  For example, suppose I have an encoded-word in
> iso-8859-1 and I use replaceheader to change an a with an accent
> grave to an a with an ogonek. What does the result look like? Are
> adjacent encoded-words affected? Should they be?

The base Sieve spec deals with recognizing encoded-words and IMO all 
that this extension needs to say is that if the result of the 
replaceheader action needs encoding, the Sieve implementation MUST do 
so.

The _how_ is up to the implementation and can range from re-encoding 
only the affected (encoded-)words using a minimal charset (for a 
certain definition of that) to brutally encoding the whole result in 
=?utf-8?b?...?= chunks unconditionally.

One could add a :preferred_charsets option that takes a stringlist as 
parameter, but I think that's hacky. One could specify a preferred 
algorithm that SHOULD be followed along the lines of

1. Only touch encoded-words that are affected.
2. If the affected portions of the result are US-ASCII, remove the 
encoding, else
3. If the affected portions of the result can be represented in one of 
the charsets already used in encoded-words in the original form of the 
header, encode using that charset, else
4. If they can be represented in iso-8859-1 or the server's locale 
charset or any site-defined sorted list of charsets, use the best 
(latin-1, locale, first in the list), else
5. use utf-8.

but I don't see the need to require a particular behavior when encoding.

Marc

-- 
Silent leges inter arma      -- Cicero

---

From: [email-masked]
Date: Mon, 28 Apr 2003 16:43:02 -0700 (PDT)

> amounts of) mailing list traffic.

Please explain why you cannot use deleteheader/addheader for this.

> replaceheader action needs encoding, the Sieve implementation MUST do

This is not even close to sufficient. The interaction with existing
encoded words also has to be considered.

> =?utf-8?b?...?= chunks unconditionally.

A cure that is worse than the disease given the state of many clients today.

> (latin-1, locale, first in the list), else

Yeah, and given past experience with encoded-word handling, how many
implementations do you think are going to get this right?

> but I don't see the need to require a particular behavior when encoding.

I'm afraid I do.

					Ned

---

From: Simon Josefsson <[email-masked]>
Date: Tue, 29 Apr 2003 02:33:23 +0200

> Please explain why you cannot use deleteheader/addheader for this.

I don't think this is the example Marc had in mind, but anyway:

Consider if you want to replace the obscure MTA identification strings
in Received: headers with the full name of the MTA product.

Deleteheader/addheader will likely not maintain sort order, but a
replaceheader ought to (which is useful).

I agree it is complex, but I have always wanted Sieve to be a real
language (= complex) so I don't consider that a problem.

---

From: Marc Mutz <[email-masked]>
Date: Tue, 29 Apr 2003 02:38:20 +0200

On Tuesday 29 April 2003 01:43, [email-masked] wrote:
<snip>
<snip>

OK, if the variables extension is present, you can of course emulate 
this with a :regex/:matches test and a deleteheader/addheader pair.

If the variables extension isn't available, the replaceheader itself is 
pretty limited, too, since
  replaceheader :newvalue "" :regex "Subject" "^\[ml-name\] *";
doesn't work (should it? Probably, since without it, how does one write 
the equivalent of perl's s///g?).

The arguments that remains, then, is that replaceheader is easier to 
write for a script author and that it can't be that complex if it's 
functionality is already present in addheader/deleteheader/variables... 
In addition, replaceheader :index <num> has no equivalent due to lack 
of indexing support in the header test.

Marc

-- 
The first casualty of war is the truth.

---

From: [email-masked]
Date: Mon, 28 Apr 2003 19:42:21 -0700 (PDT)

> in Received: headers with the full name of the MTA product.

I'm afraid I don't find this to be a credible example. Sieve is intended to be
a language used in or around delivery time so users can exercise some control
over delivery processing. It is not intended to be a general purpose message
alteration facility.

> language (= complex) so I don't consider that a problem.

This is not a desire I share. In fact one of the original design goals of sieve
was that it not be "a real language". If I want a real language I'll use one.
There are plenty of them around; no need to invent another.

				Ned

---

From: Marc Mutz <[email-masked]>
Date: Tue, 29 Apr 2003 10:14:18 +0200

On Tuesday 29 April 2003 04:42, [email-masked] wrote:
<snip>
> I'm afraid I don't find this to be a credible example. Sieve is
> intended to be a language used in or around delivery time so users
> can exercise some control over delivery processing. It is not
> intended to be a general purpose message alteration facility.
<snip>

It isn't? The whitepaper mentions not only final delivery uses, but also 
periodic sweeps through a message store for administrative purposes 
(aka cron jobs) as well as client-side filtering.

Esp. the editheader draft is one that is mandatory for client-side 
filtering, b/c many clients provide that functionality now and it is 
used where offered.

I'd even welcome a shell-out (execute_command/pipe_trough) extension, 
even if it was never ever implemented on a server (and shouldn't), but 
only in clients and local tools (like GNU mailutils' sieve).

Marc

-- 
Eternal vigilance is the price of liberty   -- Thomas Jefferson

---

From: "Nigel Swinson" <[email-masked]>
Date: Tue, 29 Apr 2003 10:52:23 +0100

> I don't think this is the example Marc had in mind, but anyway:

One other thing to say is complexity for guis.  If the intention is to
"replace header" and you have to do this via removeheader and addheader,
then it becomes much more difficult to "extract" from the script.  The
intention being to populate a control that has an array of desired actions,
one of which is "Prepend the following substring to the Subject line".

ie either:

if spamtest :value "ge" :comparator "i;ascii-numeric" "3" {
    replaceheader :newvalue "[SPAM] ${1}" :matches "Subject" "*";
}

or:

if spamtest :value "ge" :comparator "i;ascii-numeric" "3" {
    deleteheader :matches "Subject" "*";
    addheader "Subject" "[SPAM] ${1}";
}

Cheers

Nigel

---

From: [email-masked]
Date: Tue, 29 Apr 2003 08:28:31 -0700 (PDT)

Content-transfer-encoding: 7BIT

> (aka cron jobs) as well as client-side filtering.

This was for filtering and redirection purposes, not for message alteration.

> only in clients and local tools (like GNU mailutils' sieve).

I object in the strongest possible terms to this.

				Ned

---

From: [email-masked]
Date: Tue, 29 Apr 2003 08:32:08 -0700 (PDT)

>     addheader "Subject" "[SPAM] ${1}";

I actually prefer the second. It makes it clear a new header is being
generated with all that implies (changes to encoded words, etc.). The
former implies that the operation may only be a simple prepend. The 
world isn't this simple.

				Ned

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 30 Apr 2003 00:25:54 +0200

> There are plenty of them around; no need to invent another.

The only standardized language, used for mail handling, which has
multi-vendor support in MUAs and MTAs, that I know of, is Sieve.
There are not plenty of them around.

I agree with you that there is no need to invent another language,
fortunately, but my reason is that I believe Sieve is being enhanced
into a complex language.

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 30 Apr 2003 00:52:06 +0200

>   addheader ["Comment: 1", "Comment: 2"];

I don't like mixing the header name and the content.  I don't see what
this buys you compared to two calls to addheader.

>   > list of header names makes sense with deleteheader, but for
>   > addheader I think it makes more sense to only support a list of
>   > values.
>   >

see above :-).  adding two instances of a header is very uncommon, so
it's not a very useful feature.  it's more of a general design
principle: do we want to support lists rather than single strings
wherever we can give the action a useful meaning?

I do feel that keeping the header name separate is best, if only for
consistency with deleteheader and replaceheader.

>   I think replaceheader is too complex. Think for a bit about the
>   right way to handle modifications to encoded words. It gets very
>   very nasty in a great big hurry.  For example, suppose I have an
>   encoded-word in iso-8859-1

"invisible" to Sieve.  the string will be in Unicode.

>   and I use replaceheader to change an a with an accent grave to an
>   a with an ogonek.  What does the result look like?  Are adjacent
>   encoded-words affected? Should they be?

I think a fresh re-encoding is the way to go.  regrettably there are
some clients with limited support for charsets, so it would be nice if
the Sieve implementation tried to use the same charset as was used
originally, if only one charset suffices.  encoding it all as UTF-8
should be good enough, though.  remember that the user must explicitly
request this munging.  if his e-mail client can't handle it, he should
turn it off.

-- 
Kjetil T.

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 30 Apr 2003 01:07:02 +0200

[Ned Freed]:
>   [Nigel Swinson]:

>   > One other thing to say is complexity for guis.  If the intention
>   > is to "replace header" and you have to do this via removeheader
>   > and addheader, then it becomes much more difficult to "extract"
>   > from the script.

good point.  most GUI's will only need to understand their own Sieve
code, but it is important that the constructs we provide lend
themselves easily to common idioms.

>   > The intention being to populate a control that has an array of
>   > desired actions, one of which is "Prepend the following
>   > substring to the Subject line".
>   >
>   > ie either:
>   >
>   I actually prefer the second. It makes it clear a new header is
>   being generated with all that implies (changes to encoded words,
>   etc.). The former implies that the operation may only be a simple
>   prepend. The world isn't this simple.

Nigel's second example is quite clever.  the reverse, removing a
prefix, exposes unintuitive behaviour in my draft, though:

    deleteheader :matches "Subject" "[ietf] *";
    addheader "Subject" "${1}";
    fileinto "INBOX.lists.ietf";

consider this message:

    Subject: [ietf] meeting on Thursday
    Subject: buggy header

the result will actually be:

    Subject: buggy header
    Subject: 

since the failed match will empty the numeric variables.  two Subject
headers is a bit obscure, so a better example may be:

    deleteheader :matches "Subject" "[ietf] *";
    deleteheader :matches "Subject" "Re: [ietf] *";
    addheader "Subject" "${1}";

I know you wanted a failed match to not influence the numeric
variables, Ned, it seems like you were right.

-- 
Kjetil T.

---

From: [email-masked]
Date: Tue, 29 Apr 2003 16:22:28 -0700 (PDT)

> There are not plenty of them around.

That's not an excuse for turning sieve so heavy that many if not most service
providers will be unwilling to provide support for it.

> fortunately, but my reason is that I believe Sieve is being enhanced

Not if I have anything to say about it.

				Ned

---

From: [email-masked]
Date: Tue, 29 Apr 2003 16:29:20 -0700 (PDT)

> this buys you compared to two calls to addheader.

OK, I'm now convinced this was a bad idea on my part. Having multiple
addheaders also seems preferable to me given that we don't really want
to encourage wholesalle header additions.

> consistency with deleteheader and replaceheader.

Consistency with header is actually more important IMO.

> "invisible" to Sieve.  the string will be in Unicode.

Yes, that's one way to implement it, and probably the approach I'd take. But
now when you apply replaceheader it ends up affecting parts of the field that
weren't specified in the action. Least astonishment principle and all that.

Of course a deleteheader/addheader sequence has the same characteristics.
But in this case it is very clear that the old header is gone and has 
been replaced with something else.

> request this munging.  if his e-mail client can't handle it, he should

I agree with this implementation choice, but it begs the question of why
deleteheader/addheader aren't sufficient in the same way that
a sequence of addheader actions is sufficient to avoid the use of lists
in addheader.

				Ned

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 30 Apr 2003 02:02:21 +0200

[Ned Freed]:
>   [Kjetil T Homme]:

agreed, but I don't think a list of header names is very useful.  the
following is the best I can come up with :-)

    addheader ["Precedence", "X-Priority"] "cosmic top important";

>   [...] it begs the question of why deleteheader/addheader aren't
>   sufficient in the same way that a sequence of addheader actions is
>   sufficient to avoid the use of lists in addheader.

the only point I can see in favour of keeping replaceheader, is
Nigel's (general) point on idioms for GUIs.  and it doesn't seem very
compelling here.

-- 
Kjetil T.

---

From: Marc Mutz <[email-masked]>
Date: Wed, 30 Apr 2003 09:43:19 +0200

On Wednesday 30 April 2003 01:07, Kjetil Torgrim Homme wrote:
<snip>
<snip>

Well, _obviously_ this particular problem stems from unconditionally 
executing deleteheader+addheader. The correct way to do this would be:

if header :matches "Subject" "[ietf] *" {
	deleteheader "Subject";
	addheader "Subject" "${1}";
}

Marc

-- 
If free-software authors lose the right to disclaim all warranties and
find themselves getting sued over the performance of the programs
they've written, they'll stop contributing free software to the world.
 -- Bruce Perens: Open Sources: Voices from the Open Source Revolution

---

From: Marc Mutz <[email-masked]>
Date: Wed, 30 Apr 2003 10:11:02 +0200

On Wednesday 30 April 2003 01:22, [email-masked] wrote:
<snip>
> That's not an excuse for turning sieve so heavy that many if not most
> service providers will be unwilling to provide support for it.
<snip>

Not every ISP will want to support all Sieve extensions. They don't need 
to. Many ISP will probably refrain from allowing regex use, of 
variables, for that matter. I think it's perfectly OK to create Sieve 
extensions that are explicitely not suitable for all Sieve use cases. 
E.g. the envelope extension can't be used in MUAs since that 
information in general is lost on final delivery. OTOH, people will 
want to have execute command/play sound actions (the latter could be 
added to notify) on the client.

I agree, though, that the I-Ds currently floating around should first be 
advanced to RFCs before proposing even more extensions. It's a bit too 
much currently ;-)

Marc

-- 
They [RIAA,MPAA] are trying to invent a new crime:
interference with a business model.
                           --Bruce Schneier, Crypto-Gram 08/2002

---

From: Arnt Gulbrandsen <[email-masked]>
Date: Wed, 30 Apr 2003 10:41:04 +0200

Kjetil Torgrim Homme writes:
> good point. most GUI's will only need to understand their own Sieve code,

Oh?

When a program is about to parse a sieve script, it cannot know whether 
that script was written by itself. Right? That's more or less a design 
decision. There's nothing like the postscript Creator field in sieve.

Because of that, a program cannot enable or disable its 'parse existing 
sieve script' command depending on who wrote the sieve script.

> but it is important that the constructs we provide lend themselves 
> easily to common idioms.

Agree wholeheartedly.

--Arnt

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 30 Apr 2003 11:56:33 +0200

[Marc Mutz]:
>   Well, _obviously_ this particular problem stems from
>   unconditionally executing deleteheader+addheader. The correct way
>   to do this would be:
>   

it is always possible to add code to avoid the problem, e.g.,

   set "oldsubj" "${1}"

the question is which behaviour is more convenient.  my previous
example omitted the classifying test, it could look like this:

   if header :contains "List-ID" "ietf" {
      deleteheader :matches "Subject" "[ietf] *";
      deleteheader :matches "Subject" "Re: [ietf] *";
      addheader "Subject" "${1}";
   }

another test inside the block is a bit more verbose, but it may be
clearer code.
-- 
Kjetil T.

---

From: Kjetil Torgrim Homme <[email-masked]>
Date: 30 Apr 2003 12:12:30 +0200

>   > good point. most GUI's will only need to understand their own

sorry, I should say "their own idioms".

>   When a program is about to parse a sieve script, it cannot know
>   whether that script was written by itself. Right? That's more or
>   less a design decision. There's nothing like the postscript
>   Creator field in sieve.
>   
>   Because of that, a program cannot enable or disable its 'parse
>   existing sieve script' command depending on who wrote the sieve
>   script.

agreed, it must _always_ give a functionally equivalent
representation.  if you select "lower case Subject" in one editor, it
may emit

    if header :matches "Subject" "*" {
        set :lower "_lc" "${1}";
        deleteheader "Subject";
        addheader "Subject" "${_lc}";
    }

it is OK for a different editor to present this differently, say:

   lower case content of header Subject and store in variable _lc
   delete header Subject
   add header Subject with content from variable _lc

I think most users will stick to one editor, or edit the code
directly, so they will be happy even if it lacks advanced code pattern
matching.

-- 
Kjetil T.