This is an automated email from the ASF dual-hosted git repository.
chibenwa pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-jsieve.git
commit aebeaef874de22b24f5194df2ab7992caabee0ba
Author: Benoit TELLIER <[email protected]>
AuthorDate: Sun Aug 23 23:41:47 2026 +0700
[DOC] Antora site: add simple usage
---
docs/antora.yml | 4 +
docs/modules/ROOT/nav.adoc | 1 +
docs/modules/ROOT/pages/index.adoc | 4 +-
docs/modules/ROOT/pages/usage.adoc | 192 +++++++++++++++++++++++++++++++++++++
4 files changed, 199 insertions(+), 2 deletions(-)
diff --git a/docs/antora.yml b/docs/antora.yml
index 5c310c2..003650b 100644
--- a/docs/antora.yml
+++ b/docs/antora.yml
@@ -4,3 +4,7 @@ version: '0.9-SNAPSHOT'
prerelease: true
nav:
- modules/ROOT/nav.adoc
+asciidoc:
+ attributes:
+ # Latest released version, as published on Maven central. Bump on release.
+ jsieve-version: '0.8@'
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index d11ec72..e89be0d 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -1,6 +1,7 @@
* xref:index.adoc[Overview]
* xref:features.adoc[Sieve Features]
* xref:getting-started.adoc[Getting Started]
+* xref:usage.adoc[Usage]
* xref:utils.adoc[jSieve Utilities]
* xref:specifications.adoc[Specifications]
* xref:release-notes.adoc[Release Notes]
diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc
index 5f18407..a235906 100644
--- a/docs/modules/ROOT/pages/index.adoc
+++ b/docs/modules/ROOT/pages/index.adoc
@@ -14,8 +14,8 @@ https://james.apache.org/mail.html[mailing lists].
jSieve consists of two products:
-* *Apache JSieve* is a Sieve library coded in Java. See xref:getting-started.adoc[Getting Started]
-and xref:features.adoc[Sieve Features].
+* *Apache JSieve* is a Sieve library coded in Java. See xref:getting-started.adoc[Getting Started],
+xref:usage.adoc[Usage] and xref:features.adoc[Sieve Features].
* xref:utils.adoc[*Apache JSieve Utilities*] contains utility classes helpful when using Sieve
but not considered sufficiently core to be included in the main library.
diff --git a/docs/modules/ROOT/pages/usage.adoc b/docs/modules/ROOT/pages/usage.adoc
new file mode 100644
index 0000000..d8dca7a
--- /dev/null
+++ b/docs/modules/ROOT/pages/usage.adoc
@@ -0,0 +1,192 @@
+= Usage
+
+This page walks through the day to day use of the jSieve library: adding it to a project,
+running a script against a message, and reading back the resulting actions.
+
+For the design rationale behind the extension points touched on here, see
+xref:getting-started.adoc[Getting Started].
+
+== Adding jSieve to your project
+
+The parsing and evaluation engine lives in `apache-jsieve-core`:
+
+[source,xml,subs=attributes+]
+----
+<dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>apache-jsieve-core</artifactId>
+ <version>{jsieve-version}</version>
+</dependency>
+----
+
+The optional helpers described in xref:utils.adoc[jSieve Utilities] are shipped separately:
+
+[source,xml,subs=attributes+]
+----
+<dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>apache-jsieve-util</artifactId>
+ <version>{jsieve-version}</version>
+</dependency>
+----
+
+== Building a SieveFactory
+
+`org.apache.jsieve.SieveFactory` is the entry point for every Sieve operation. You do not
+instantiate it directly: `ConfigurationManager` reads the command, test and comparator maps
+from the classpath and builds a configured factory for you.
+
+[source,java]
+----
+ConfigurationManager configurationManager = new ConfigurationManager();
+SieveFactory sieveFactory = configurationManager.build();
+----
+
+Both the `ConfigurationManager` and the `SieveFactory` it builds are thread safe, provided the
+managers they wrap are. Build the factory once and share it.
+
+To discover which extensions the current configuration supports:
+
+[source,java]
+----
+List<String> extensions = sieveFactory.getExtensions();
+----
+
+== Running a script
+
+`SieveFactory` exposes three operations.
+
+`parse(InputStream)`:: Parses a script into a hierarchy of nodes and validates it against the
+configured commands, tests and comparators. It returns the start `Node`, which is reusable and
+should be cached for subsequent evaluations of the same script. A `ParseException` signals an
+invalid script.
+`evaluate(MailAdapter, Node)`:: Evaluates a message, wrapped in a `MailAdapter`, against a
+previously parsed start node.
+`interpret(MailAdapter, InputStream)`:: A convenience concatenation of the two. Handy for tests,
+but prefer parsing once and evaluating many times in production.
+
+Scripts are read as `UTF-8`, as mandated by RFC 5228.
+
+The typical production shape is parse once, evaluate per message:
+
+[source,java]
+----
+// At script registration time
+Node startNode = sieveFactory.parse(new ByteArrayInputStream(script.getBytes(StandardCharsets.UTF_8)));
+
+// For every incoming message
+MailAdapter mail = new MyMailAdapter(message);
+sieveFactory.evaluate(mail, startNode);
+----
+
+Or, in one step:
+
+[source,java]
+----
+sieveFactory.interpret(mail, new ByteArrayInputStream(script.getBytes(StandardCharsets.UTF_8)));
+----
+
+== Reading back the actions
+
+Evaluation does not modify the message. It accumulates ``Action``s on the `MailAdapter`, then
+calls `MailAdapter.executeActions()` once evaluation completes — it is your adapter that decides
+what an action actually does.
+
+An `implicitKeep` state is set at the start of evaluation. Unless a command cancels it, an
+`ActionKeep` is appended to the list before the actions are executed. This is why a script that
+matches nothing still delivers the mail.
+
+The actions jSieve can produce:
+
+[cols="1,1"]
+|===
+|Action |Meaning
+
+|`ActionKeep` |Deliver to the default mailbox
+|`ActionFileInto` |Deliver to `getDestination()`
+|`ActionRedirect` |Forward to `getAddress()`
+|`ActionDiscard` |Drop the message silently
+|`ActionReject` |Refuse the message with `getMessage()`
+|`ActionVacation` |Send an auto-reply (RFC 5230)
+|===
+
+After evaluation, `getActions()` returns what the script decided:
+
+[source,java]
+----
+for (Action action : mail.getActions()) {
+ if (action instanceof ActionFileInto) {
+ String destination = ((ActionFileInto) action).getDestination();
+ // ...
+ }
+}
+----
+
+== Wrapping your messages in a MailAdapter
+
+`org.apache.jsieve.mail.MailAdapter` is the interface through which jSieve reaches your mail
+server. It wraps one message and exposes what scripts need to test:
+
+* Header access — `getHeader(String)`, `getMatchingHeader(String)` (case and whitespace
+insensitive, as RFC 5228 requires) and `getHeaderNames()`
+* Message properties — `getSize()`, `getContentType()`
+* Body searches backing the `body` test — `isInBodyText`, `isInBodyRaw`, `isInBodyContent`
+* Address parsing — `parseAddresses(String)`, returning ``MailAdapter.Address``es
+* Action handling — `addAction(Action)`, `getActions()` and `executeActions()`
+
+Implement `getEnvelopeFrom()` and `getEnvelopeTo()` from
+`org.apache.jsieve.mail.optional.EnvelopeAccessors` to support the optional `envelope` test.
+
+Two points deserve attention when implementing one:
+
+`setContext` and thread safety:: The engine sets the context before the run and clears it
+(passing `null`) at the end, including on failure. An adapter shared between threads must scope
+that context per thread — for example in a `ThreadLocal` — and all calls for a given script
+execution must happen on the same thread.
+`parseAddresses`:: https://james.apache.org/mime4j[Apache Mime4J] parses an address header into
+mailboxes with little effort; wrap its `ParseException` into an `InternetAddressException`.
+
+Existing implementations to read: `ScriptCheckMailAdapter` in the utilities module (a
+non-destructive one, backed by a `javax.mail.Message`), and `SieveMailboxMailet` in the
+James server code base.
+
+== Checking a script without a mail server
+
+The utilities module ships a `ScriptChecker` that runs a script against a message and reports
+the actions it would have executed — useful for tests, or for validating a script a user just
+submitted:
+
+[source,java]
+----
+ScriptChecker.Results results = new ScriptChecker().check(messageFile, scriptFile);
+
+if (results.isPass()) {
+ List actions = results.getActionsExecuted();
+} else {
+ Exception failure = results.getException();
+}
+----
+
+`Results` also offers shorthands such as `isActionFileInto(destination, n)` to assert on the
+n-th executed action.
+
+== Registering an extension command
+
+Commands, tests and comparators are looked up by name in three properties files loaded from the
+classpath:
+
+* `org/apache/jsieve/commandsmap.properties`
+* `org/apache/jsieve/testsmap.properties`
+* `org/apache/jsieve/comparatorsmap.properties`
+
+Each entry maps the name used in scripts to an implementation class:
+
+[source,properties]
+----
+log=org.apache.jsieve.commands.extensions.Log
+----
+
+Registering programmatically is possible through `ConfigurationManager.getCommandMap()` and its
+siblings, but overriding these resource files is the recommended route. See
+xref:getting-started.adoc#_implementing_extension_commands[Implementing Extension Commands] for
+how to write the implementation itself.
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.