| <?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 2021-11-12 --> |
| <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 Project – Apache James Server 3 - Writing a Custom Mailet</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="20211112" /> |
| <meta http-equiv="Content-Language" content="en" /> |
| |
| <!-- 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="James Project" /> |
| </a> |
| <a href="https://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: 2021-11-12</span> |
| </div> |
| <div class="xright"> <a href="../index.html" title="Home">Home</a> |
| | |
| <a href="../documentation.html" title="James">James</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> |
| |
| |
| </div> |
| <div class="clear"> |
| <hr/> |
| </div> |
| </div> |
| <div id="leftColumn"> |
| <div id="navcolumn"> |
| |
| |
| <h5>James components</h5> |
| <ul> |
| <li class="collapsed"> |
| <a href="../documentation.html" title="About James">About James</a> |
| </li> |
| <li class="expanded"> |
| <a href="../server/index.html" title="Server">Server</a> |
| <ul> |
| <li class="none"> |
| <a href="../server/advantages.html" title="Advantages">Advantages</a> |
| </li> |
| <li class="none"> |
| <a href="../server/objectives.html" title="Objectives">Objectives</a> |
| </li> |
| <li class="expanded"> |
| <a href="../server/quick-start.html" title="User Manual">User Manual</a> |
| <ul> |
| <li class="collapsed"> |
| <a href="../server/features.html" title="1. Features">1. Features</a> |
| </li> |
| <li class="none"> |
| <a href="../server/packaging.html" title="2. Packaging">2. Packaging</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/install.html" title="3. Install James">3. Install James</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/config.html" title="4. Configure James">4. Configure James</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/manage.html" title="5. Manage">5. Manage</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/monitor.html" title="6. Monitor">6. Monitor</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/upgrade.html" title="7. Upgrade">7. Upgrade</a> |
| </li> |
| <li class="expanded"> |
| <a href="../server/dev.html" title="8. Developers Corner">8. Developers Corner</a> |
| <ul> |
| <li class="none"> |
| <a href="../server/dev-build.html" title="Build from source">Build from source</a> |
| </li> |
| <li class="none"> |
| <a href="../server/dev-database-schema.html" title="Database Schema">Database Schema</a> |
| </li> |
| <li class="expanded"> |
| <a href="../server/dev-extend.html" title="Develop Extensions">Develop Extensions</a> |
| <ul> |
| <li class="none"> |
| <strong>Mailet</strong> |
| </li> |
| <li class="none"> |
| <a href="../server/dev-extend-matcher.html" title="Matcher">Matcher</a> |
| </li> |
| <li class="none"> |
| <a href="../server/dev-extend-smtp-hook.html" title="SMTP Hook">SMTP Hook</a> |
| </li> |
| </ul> |
| </li> |
| <li class="collapsed"> |
| <a href="../server/dev-provided.html" title="Provided Extensions">Provided Extensions</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="none"> |
| <a href="../mail.html#James_Mailing_lists" title="Mailing Lists">Mailing Lists</a> |
| </li> |
| <li class="none"> |
| <a href="../server/release-notes.html" title="Release Notes">Release Notes</a> |
| </li> |
| <li class="none"> |
| <a href="../server/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> |
| <li class="none"> |
| <a href="https://github.com/apache/james-project" title="Sources">Sources</a> |
| </li> |
| <li class="none"> |
| <a href="../server/rfcs.html" title="RFCs">RFCs</a> |
| </li> |
| <li class="none"> |
| <a href="../download.cgi#Apache_James_Server" title="Download releases">Download releases</a> |
| </li> |
| </ul> |
| </li> |
| <li class="collapsed"> |
| <a href="../mailet/index.html" title="Mailets">Mailets</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../mailbox/index.html" title="Mailbox">Mailbox</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../protocols/index.html" title="Protocols">Protocols</a> |
| </li> |
| <li class="collapsed"> |
| <a href="../mpt/index.html" title="MPT">MPT</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"> |
| |
| |
| |
| |
| <section> |
| <h2><a name="Writing_a_Custom_Mailet"></a>Writing a Custom Mailet</h2> |
| |
| |
| <p> |
| Implementing a custom mailet is generally a simple task, most of whose complexity |
| lies in coding the actual work to be done by the mailet. This is largely due to the |
| simplicity of the Mailet interface and the fact that a GenericMailet class is provided |
| as part of the Mailet package. |
| </p> |
| |
| |
| <p> |
| In this discussion we will assume that any mailet being implemented is a subclass of |
| GenericMailet. The GenericMailet class serves to abstract away of the configuration and |
| logging details. While it provides a noop implementation of the init() and destroy() methods, |
| these can be easily overridden to provide useful functionality. |
| </p> |
| |
| |
| <p> |
| In general, the only four methods that you should need to implement are init(), destroy(), |
| getMailetInfo(), and service(Mail). And only the last is required in all cases. |
| </p> |
| |
| <section> |
| <h3><a name="Configuration"></a>Configuration</h3> |
| |
| <p> |
| As described in the <a href="config-mailetcontainer.html">SpoolManager configuration |
| section</a>, mailets are configured with a set of String (name, value) pairs. These values are |
| passed into the Mailet upon initialization (although the details of this process are hidden by |
| the GenericMailet implementation). GenericMailet provides access to this configuration |
| information through use of the getInitParameter(String) method. Passing in the name of the |
| requested configuration value will yield the value if set, and null otherwise. Configuration |
| values are available inside the init(), destroy(), and service(Mail) methods. |
| </p> |
| </section> |
| |
| <section> |
| <h3><a name="Logging"></a>Logging</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 Mailet code. |
| Logging is done by calling one of the two logging methods on GenericMailet - log(String) |
| or log(String,Throwable). Logging is available inside the init(), destroy(), and service(Mail) |
| methods. |
| </p> |
| |
| <p> |
| Please note that the log() method logs with DEBUG level. You will need to define that DEBUG level |
| in the log4j.properties. |
| </p> |
| |
| <p> |
| The value of getMailetInfo() for the Mailet is prepended to the log entries for that |
| Mailet. So it may be desirable for you to override this method so you can distinguish mailet |
| log entries by Mailet. |
| </p> |
| |
| <p> |
| Alternatively, you can instantiate your own logger and log with different level, as show in the |
| following snippet (don't forget to update the log4j.properties so you log are taken into account). |
| </p> |
| |
| |
| <div class="source"> |
| <pre> |
| package com.test; |
| |
| import javax.mail.MessagingException; |
| |
| import org.apache.mailet.Mail; |
| import org.apache.mailet.base.GenericMailet; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class MyMailet extends GenericMailet{ |
| private static final Logger logger = LoggerFactory.getLogger(MyMailet.class); |
| @Override |
| public void service(Mail mail) throws MessagingException { |
| log("log via mailet logger with INFO level"); |
| logger.info("Log via slf4j with INFO level !!! Add log4j.logger.com.test=INFO, CONS, FILE in the log4j.properties"); |
| logger.debug("Log via slf4j with DEBUG level !!! Add log4j.logger.com.test=DEBUG, CONS, FILE in the log4j.properties"); |
| } |
| } |
| </pre></div> |
| </section> |
| |
| <section> |
| <h3><a name="Initialization"></a>Initialization</h3> |
| |
| <p> |
| As part of the Mailet lifecycle, a Mailet is guaranteed to be initialized immediately after |
| being instantiated. This happens once and only once for each Mailet instance. The |
| Initialization phase is where configuration parsing and per-Mailet resource creation generally |
| take place. Depending on your Mailet, it may or may not be necessary to do any initialization |
| of the mailet. Initialization logic is implemented by overriding the init() method of |
| GenericMailet. |
| </p> |
| </section> |
| |
| <section> |
| <h3><a name="Servicing"></a>Servicing</h3> |
| |
| <p> |
| The bulk of the Mailet logic is expected to be invoked from the service(Mail) method. This |
| method is invoked each time a mail message is to be processed by the mailet. The message is |
| passed in as an instance of the Mail interface, which is part of the Mailet API.</p> |
| |
| <p>The Mail interface is essentially a light wrapper around JavaMail's MimeMessage class with a |
| few important differences. See the Javadoc for the interface for a description of the additional |
| methods available on this wrapper. |
| </p> |
| </section> |
| |
| <section> |
| <h3><a name="Destruction"></a>Destruction</h3> |
| |
| <p> |
| As part of the Mailet lifecycle, a Mailet is guaranteed to be destroyed when the container |
| cleans up the Mailet. This happens once and only once for each Mailet instance. The |
| Destruction phase is where per-Mailet resource release generally takes place. Depending |
| on your Mailet, it may or may not be necessary to do any destruction |
| of the mailet. Destruction logic is implemented by overriding the destroy() method of |
| GenericMailet. |
| </p> |
| </section> |
| |
| </section> |
| |
| <section> |
| <h2><a name="Deploying_a_Custom_Mailet"></a>Deploying a Custom Mailet</h2> |
| |
| |
| <p> |
| Once a Mailet has been successfully implemented there are only a couple of |
| additional steps necessary to actually deploy the Mailet. |
| </p> |
| |
| <section> |
| <h3><a name="Adding_Your_Mailet_to_the_Classpath"></a>Adding Your Mailet to the Classpath</h3> |
| |
| <p> |
| The Mailet must be added to James' classpath so that the Mailet can be loaded by James. There |
| are two ways to add a custom Mailet to the classpath so that James will be able to load the |
| Mailet. 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 .tar.gz/zip file by following the |
| directions <a href="build-instructions.html">here</a>. This new tar.gz/zip file will now |
| include your custom classes. |
| </p> |
| |
| <p> |
| or |
| </p> |
| |
| <p> |
| 1b. Place a jar file containing the custom class files in |
| /path/to/james/conf/lib/ subdirectory with JAMES-Spring or /path/to/james/conf/extensions-jars/ subdirectory with JAMES-Guice. |
| </p> |
| |
| <p> |
| 2. The mailetpackages entity is no longer required, the class attribute of mailets and matchers now takes a fully qualified class name e.g. |
| |
| <p> |
| </p> |
| <div class="source"> |
| <pre> |
| <mailet match="All" class="com.your.company.MyMailet"/> |
| </pre></div> |
| |
| After that, restart James server. |
| |
| </section> |
| |
| <section> |
| <h3><a name="Add_custom_Guice_injections_for_extensions"></a>Add custom Guice injections for extensions</h3> |
| |
| <p>Upon injections, the user can reference additional guice modules, that are going to be used only upon extensions instantiation. |
| In order to do that:</p> |
| |
| <p> 1. Place the jar containing the guice module that should be used to instantiate your extensions within the /extensions-jars folder</p> |
| |
| <p> 2. Register your module fully qualified class name within <a class="externalLink" href="https://github.com/apache/james-project/blob/master/server/apps/distributed-app/sample-configuration/extensions.properties"> |
| extensions.properties</a> under the guice.extension.module key.</p> |
| </section> |
| |
| <section> |
| <h3><a name="James_Configuration"></a>James Configuration</h3> |
| |
| <p>Configuration of the processor chain is discussed |
| <a href="config-mailetcontainer.html">elsewhere</a> in this documentation. The |
| details of configuring mailet deployment is discussed at length. Here we will only comment |
| that it is important to add the appropriate mailet package for your custom mailet to the |
| <mailetpackages> list and that the name of your mailet should not conflict with any of |
| the mailets described <a href="dev-provided-mailets.html">here</a>. |
| </p> |
| </section> |
| |
| </section> |
| |
| |
| |
| |
| </div> |
| </div> |
| <div class="clear"> |
| <hr/> |
| </div> |
| <div id="footer"> |
| <div class="xright">Copyright © 2006-2021 |
| <a href="https://www.apache.org/">The Apache Software Foundation</a>. |
| All Rights Reserved. |
| |
| </div> |
| <div class="clear"> |
| <hr/> |
| </div> |
| </div> |
| </body> |
| </html> |