blob: 23c6677abeb54d914629746c49388630465582cc [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- Generated by Apache Maven Doxia at 2016-10-20 -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Apache James Server 3.0 -
Apache James Server 3 - Writing a Custom Matcher</title>
<style type="text/css" media="all">
@import url("./css/james.css");
@import url("./css/maven-base.css");
@import url("./css/maven-theme.css");
@import url("./css/site.css");
@import url("./js/jquery/css/custom-theme/jquery-ui-1.8.5.custom.css");
@import url("./js/jquery/css/print.css");
@import url("./js/fancybox/jquery.fancybox-1.3.4.css");
</style>
<script type="text/javascript" src="./js/jquery/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="./js/jquery/js/jquery-ui-1.8.5.custom.min.js"></script>
<script type="text/javascript" src="./js/fancybox/jquery.fancybox-1.3.4.js"></script>
<link rel="stylesheet" href="./css/print.css" type="text/css" media="print" />
<meta name="Date-Revision-yyyymmdd" content="20161020" />
<meta http-equiv="Content-Language" content="en" />
<link title="DOAP" rel="meta" type="application/rdf+xml" href="http://james.apache.org//doap_james-project.rdf"/>
<!-- Google Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1384591-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script').item(0); s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body class="composite">
<div id="banner">
<a href="../index.html" id="bannerLeft" title="james-logo.png">
<img src="images/logos/james-logo.png" alt="Apache James Server 3.0" />
</a>
<a href="http://www.apache.org/index.html" id="bannerRight">
<img src="images/logos/asf_logo_small.png" alt="The Apache Software Foundation" />
</a>
<div class="clear">
<hr/>
</div>
</div>
<div id="breadcrumbs">
<div class="xleft">
<span id="publishDate">Last Published: 2016-10-20</span>
</div>
<div class="xright"> <a href="../../index.html" title="Home">Home</a>
|
<a href="../index.html" title="Server">Server</a>
|
<a href="../../hupa/index.html" title="Hupa">Hupa</a>
|
<a href="../../protocols/index.html" title="Protocols">Protocols</a>
|
<a href="../../mailet/index.html" title="Mailets">Mailets</a>
|
<a href="../../mailbox/index.html" title="Mailbox">Mailbox</a>
|
<a href="../../mime4j/index.html" title="Mime4J">Mime4J</a>
|
<a href="../../jsieve/index.html" title="jSieve">jSieve</a>
|
<a href="../../jspf/index.html" title="jSPF">jSPF</a>
|
<a href="../../jdkim/index.html" title="jDKIM">jDKIM</a>
|
<a href="../../mpt/index.html" title="MPT">MPT</a>
|
<a href="../../postage/index.html" title="Postage">Postage</a>
</div>
<div class="clear">
<hr/>
</div>
</div>
<div id="leftColumn">
<div id="navcolumn">
<h5>Overview</h5>
<ul>
<li class="none">
<a href="index.html" title="Introduction">Introduction</a>
</li>
<li class="none">
<a href="release-notes.html" title="Release Notes">Release Notes</a>
</li>
</ul>
<h5>Features</h5>
<ul>
<li class="none">
<a href="feature-mailetcontainer.html" title="Mailet Container">Mailet Container</a>
</li>
<li class="none">
<a href="feature-queue-priority.html" title="Queue Priority">Queue Priority</a>
</li>
<li class="none">
<a href="feature-persistence.html" title="Persistence">Persistence</a>
</li>
<li class="none">
<a href="feature-protocols.html" title="Protocols">Protocols</a>
</li>
<li class="none">
<a href="feature-smtp-hooks.html" title="SMTP Hooks">SMTP Hooks</a>
</li>
<li class="none">
<a href="feature-performance.html" title="Performance">Performance</a>
</li>
<li class="none">
<a href="feature-security.html" title="Security">Security</a>
</li>
</ul>
<h5>User Manual</h5>
<ul>
<li class="none">
<a href="quick-start.html" title="1. Quick Start">1. Quick Start</a>
</li>
<li class="none">
<a href="install.html" title="2. Install James">2. Install James</a>
</li>
<li class="collapsed">
<a href="config.html" title="3. Configure James">3. Configure James</a>
</li>
<li class="collapsed">
<a href="manage.html" title="4. Manage">4. Manage</a>
</li>
<li class="collapsed">
<a href="monitor.html" title="5. Monitor">5. Monitor</a>
</li>
<li class="collapsed">
<a href="upgrade.html" title="6. Upgrade">6. Upgrade</a>
</li>
</ul>
<h5>Developers Corner</h5>
<ul>
<li class="none">
<a href="dev.html" title="Architecture">Architecture</a>
</li>
<li class="none">
<a href="dev-build.html" title="Build from source">Build from source</a>
</li>
<li class="none">
<a href="dev-database-schema.html" title="Database Schema">Database Schema</a>
</li>
<li class="expanded">
<a href="dev-extend.html" title="Develop Extensions">Develop Extensions</a>
<ul>
<li class="none">
<a href="dev-extend-mailet.html" title="Mailet">Mailet</a>
</li>
<li class="none">
<strong>Matcher</strong>
</li>
<li class="none">
<a href="dev-extend-smtp-hook.html" title="SMTP Hook">SMTP Hook</a>
</li>
</ul>
</li>
<li class="collapsed">
<a href="dev-provided.html" title="Provided Extensions">Provided Extensions</a>
</li>
</ul>
<h5>References</h5>
<ul>
<li class="none">
<a href="apidocs/index.html" title="Javadoc">Javadoc</a>
</li>
<li class="none">
<a href="https://issues.apache.org/jira/browse/JAMES" title="Issue Tracker">Issue Tracker</a>
</li>
</ul>
<h5>About James</h5>
<ul>
<li class="none">
<a href="../../index.html" title="Overview">Overview</a>
</li>
<li class="none">
<a href="../../newsarchive.html" title="News">News</a>
</li>
<li class="none">
<a href="../../mail.html" title="Mailing Lists">Mailing Lists</a>
</li>
<li class="none">
<a href="../../contribute.html" title="Contributing">Contributing</a>
</li>
<li class="none">
<a href="../../guidelines.html" title="Guidelines">Guidelines</a>
</li>
<li class="none">
<a href="http://wiki.apache.org/james" title="Wiki">Wiki</a>
</li>
<li class="none">
<a href="../../team-list.html" title="Who We Are">Who We Are</a>
</li>
<li class="none">
<a href="../../license.html" title="License">License</a>
</li>
<li class="none">
<a href="../../thanks.html" title="Thanks">Thanks</a>
</li>
<li class="none">
<a href="../../support.html" title="Professional support">Professional support</a>
</li>
</ul>
<h5>Download</h5>
<ul>
<li class="none">
<a href="../../download.cgi" title="Releases">Releases</a>
</li>
</ul>
<h5>Apache Software Foundation</h5>
<ul>
<li>
<strong>
<a title="ASF" href="http://www.apache.org/">ASF</a>
</strong>
</li>
<li>
<a title="Get Involved" href="http://www.apache.org/foundation/getinvolved.html">Get Involved</a>
</li>
<li>
<a title="FAQ" href="http://www.apache.org/foundation/faq.html">FAQ</a>
</li>
<li>
<a title="License" href="http://www.apache.org/licenses/" >License</a>
</li>
<li>
<a title="Sponsorship" href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
</li>
<li>
<a title="Thanks" href="http://www.apache.org/foundation/thanks.html">Thanks</a>
</li>
<li>
<a title="Security" href="http://www.apache.org/security/">Security</a>
</li>
</ul>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy">
<img class="poweredBy" alt="Built by Maven" src="./images/logos/maven-feather.png" />
</a>
</div>
</div>
<div id="bodyColumn">
<div id="contentBox">
<!-- Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. -->
<div class="section">
<h2>Writing a Custom Matcher<a name="Writing_a_Custom_Matcher"></a></h2>
<p>Implementing a custom matcher is generally a simple task, most of whose complexity
lies in coding the actual work to be done by the matcher. This is largely due to the
simplicity of the Matcher interface and the fact that a couple of abstract Matcher template
classes are provided in the Mailet package. These two classes, GenericMatcher and
GenericRecipientMatcher, greatly simplfy the task of Matcher authoring.</p>
<p>As discussed elsewhere in this manual, the Matcher interface does not simply match
or not match a particular message. Rather, it returns some subset of the original message
recipients as a result of the match(Mail) method. This leads to the two different abstract
Matcher implementations.</p>
<p>The first, GenericMatcher, is intended for matchers where recipient evaluation is not
necessary. Basically, you should subclass this implementation if your matcher is going to
return all or none of the recipients.</p>
<p>When subclassing this class, there are four methods that potentially need to be
overridden. These are getMatcherInfo(), init(), match(Mail), and destroy(). More on these
anon.</p>
<p>The second implementation, GenericRecipientMatcher, is intended for those matchers where
each recipient is evaluated individually. It is a subclass of GenericMatcher, and inherits
most of its behavior from that class. The only major difference is that subclasses are
expected to override matchRecipient(MailAddress) rather than match(Mail).</p>
<div class="section">
<h3>Configuration<a name="Configuration"></a></h3>
<p>Matchers are passed a single String as part of their configuration. Interpretation of this
list is left entirely to the body of the Matcher. This String value is available in
the body of the Matcher through use of the getCondition() method of the
GenericMatcher class. This method returns the String value passed to the Matcher, and returns
null if no value is set. The method getCondition() is available inside the init(), destroy(), match(Mail),
and matchRecipient(MailAddress) methods.</p>
</div>
<div class="section">
<h3>Logging<a name="Logging"></a></h3>
<p>There is a simple logging mechanism provided by the Mailet API. It does not support
logging levels, so any log filtering will have to be implemented in the Matcher code.
Logging is done by calling one of the two logging methods on GenericMatcher/GenericRecipientMatcher - log(String)
or log(String,Throwable). Logging is available inside the init(), destroy(), match(Mail),
and matchRecipient(MailAddress) methods.</p>
<p>The value of getMatcherInfo() for the Matcher is prepended to the log entries for that
Matcher. So it may be desirable for you to override this method so you can distinguish Matcher
log entries by Matcher.</p>
</div>
<div class="section">
<h3>Initialization<a name="Initialization"></a></h3>
<p>As part of the Matcher lifecycle, a Matcher is guaranteed to be initialized immediately after
being instantiated. This happens once and only once for each Matcher instance. The
Initialization phase is where configuration parsing and per-Matcher resource creation generally
take place. Depending on your Matcher, it may or may not be necessary to do any initialization
of the Matcher. Initialization logic is implemented by overriding the init() method of
GenericMatcher/GenericRecipientMatcher.</p>
</div>
<div class="section">
<h3>Matching<a name="Matching"></a></h3>
<p>It is the matching phase where the Matcher's work is done. The exact form of this phase largely
depends on which Matcher superclass is subclassed.</p>
<p>If GenericMatcher is being subclassed, it is the match(Mail) that is implemented. As described
above, this method returns a Collection of MailAddresses that is a subset of the original
recipients for the Mail object.</p>
<p>If it is a purely recipient-filtering Matcher, then the GenericRecipientMatcher should be
subclassed. In this case, developers must provide an implementation of the
matchRecipient(MailAddress) method. This method returns true if the recipient matches,
and false otherwise.</p>
</div>
<div class="section">
<h3>Destruction<a name="Destruction"></a></h3>
<p>As part of the Matcher lifecycle, a Matcher is guaranteed to be destroyed when the container
cleans up the Matcher. This happens once and only once for each Matcher instance. The
Destruction phase is where per-Matcher resource release generally takes place. Depending
on your Matcher, it may or may not be necessary to do any destruction
of the Matcher. Destruction logic is implemented by overriding the destroy() method of
GenericMatcher/GenericRecipientMatcher.</p>
</div>
</div>
<div class="section">
<h2>Deploying a Custom Matcher<a name="Deploying_a_Custom_Matcher"></a></h2>
<p>Once a Matcher has been successfully implemented there are only a couple of
additional steps necessary to actually deploy the Matcher.</p>
<div class="section">
<h3>Adding Your Matcher to the Classpath<a name="Adding_Your_Matcher_to_the_Classpath"></a></h3>
<p>
The Matcher must be added to James' classpath so that the Matcher can be loaded by James. There
are two ways to add a custom Matcher to the classpath so that James will be able to load the
Matcher. These are:
</p>
<p>
1a. Download the source distribution, add a jar file containing the custom files to the lib
directory of the unpacked source distribution, and build a new .sar file by following the
directions <a href="build-instructions.html">here</a>. This new .sar file will now
include your custom classes.
</p>
<p>
or
</p>
<p>
1b. Place a jar file containing the custom class files in the lib subdirectory of the James
installation. It will also be necessary to unpack the JavaMail and James jar files from
the provided .sar file and add them to this directory.
</p>
<p>
or
</p>
<p>
1c. Place a jar file containing the custom class files in
/path/to/james/conf/lib/ subdirectory.
</p>
<p>
2. After this is done get sure you add the matcher package to the mailetcontainer.xml. For example:
<p>
</p>
<div class="source">
<pre>
&lt;!-- Set the Java packages from which to load mailets and matchers --&gt;
&lt;matcherpackages&gt;
&lt;matcherpackage&gt;org.apache.james.transport.matchers&lt;/matcherpackage&gt;
&lt;matcherpackage&gt;org.apache.james.transport.matchers.smime&lt;/matcherpackage&gt;
&lt;matcherpackage&gt;your.costum.package.transport-matchers&lt;/matcherpackage&gt;
&lt;/matcherpackages&gt;
</pre></div>
After that restart james.
</div>
<div class="section">
<h3>James Configuration<a name="James_Configuration"></a></h3>
<p>Configuration of the processor chain is discussed
<a href="config-mailetcontainer.html">elsewhere</a> in this documentation. The
details of configuring matcher deployment is discussed at length. Here we will only comment
that it is important to add the appropriate matcher package for your custom matcher to the
&lt;matcherpackages&gt; list and that the name of your matcher should not conflict with any of
the matchers described <a href="dev-provided-matchers.html">here</a>.
</p>
</div>
</div>
</div>
</div>
<div class="clear">
<hr/>
</div>
<div id="footer">
<div class="xright">Copyright &#169; 2002-2016
<a href="http://www.apache.org/">The Apache Software Foundation</a>.
All Rights Reserved.
</div>
<div class="clear">
<hr/>
</div>
</div>
</body>
</html>