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.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to