Skip to content

JavaMail Bridge Extension Swiftlet

Overview

The JavaMail Bridge Extension Swiftlet enables integration between SwiftMQ queues/topics and email systems using the JavaMail API. It provides bidirectional bridges for both inbound (mail to JMS) and outbound (JMS to mail) message flows, supporting advanced transformation, filtering, and error handling mechanisms.

Features

Inbound Mail Bridges

Inbound bridges retrieve emails from external mail servers (POP3, IMAP, etc.) and convert them into JMS messages, which are then delivered to a configured SwiftMQ queue or topic. Each bridge can be enabled or disabled individually and supports periodic polling, message transformation, and advanced filtering.

Transformation is handled by pluggable transformer classes implementing the com.swiftmq.extension.javamail.inbound.Transformer interface. These transformers convert JavaMail messages into JMS messages (e.g., TextMessage, ObjectMessage) and can enforce maximum message size limits.

Inbound bridges can apply mail filters (header, body, attachment, size) to reject or accept messages based on configurable rules. Rejected messages can be returned to the sender or forwarded to a designated queue. Property translations and default properties allow mapping of mail headers to JMS properties and setting static properties on created messages.

Mail Filters

Mail filters are attached to inbound bridges and can be of type header, body, attachment, or size. Each filter can be configured to reject on match, return to sender, and provide a custom rejection message. Filters can have properties (e.g., regex patterns for headers or bodies, MIME types for attachments, or size limits).

Transformer Classes

Inbound transformers must implement the com.swiftmq.extension.javamail.inbound.Transformer interface, which defines methods for setting maximum message size, creating JMS messages, and transforming JavaMail messages. Built-in transformers include text and multipart handlers, but custom transformers can be provided.

Property Translations and Default Properties

Property translations map mail headers to JMS message properties, while default properties allow setting static properties on all created JMS messages. Both are managed via entity lists and can be customized per bridge.

Configuration Example:

<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="mail2queue" enabled="true" mail-host="imap.example.com" mail-host-port="993" mail-host-account-name="user@example.com" mail-host-account-password="secret" protocol="imaps" retrieveinterval="300000" retrieve-max-messages="20" target-name="orders" target-type="queue"/>
  </inbound-bridges>
</swiftlet>

Outbound Mail Bridges

Outbound bridges monitor a SwiftMQ queue or topic and convert JMS messages into emails, sending them via a configured SMTP server. Each bridge can be enabled or disabled individually and supports SMTP authentication, transport reuse, and multipart/HTML mail composition.

Outbound transformation is handled by pluggable transformer classes implementing either com.swiftmq.extension.javamail.outbound.Transformer or com.swiftmq.extension.javamail.outbound.Transformer2. These transformers extract message content and attachments for email composition. Header translations and default headers allow mapping of JMS properties to mail headers and setting static headers on outgoing emails.

Error Handling Policies

Outbound bridges support configurable error policies: delete (drop message), error_queue (forward to a designated error queue), or retry (retry sending). The error queue is created automatically if needed, and error details are attached as message properties.

Transformer Classes

Outbound transformers must implement either the Transformer interface (providing methods to extract content and attachments from JMS messages) or the Transformer2 interface (which transforms a JMS message directly into a JavaMail MimeMessage). The system supports custom implementations for advanced mail composition.

Header Translations and Default Headers

Header translations map JMS message properties to mail headers, while default headers allow setting static headers (such as From, To, Subject) on all outgoing emails. Both are managed via entity lists and can be customized per bridge.

Configuration Example:

<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="queue2mail" enabled="true" smtp-host="smtp.example.com" smtp-authentication-enabled="true" smtp-username="user" smtp-password="secret" source-name="notifications" source-type="queue"/>
  </outbound-bridges>
</swiftlet>

Usage and Monitoring

The Swiftlet maintains a usage section that tracks active inbound and outbound bridges, including the number of messages transferred and the last transfer time. This allows administrators to monitor bridge activity and performance.

Configuration Example:

<swiftlet name="xt$javamail" collect-interval="5000"/>

Job Integration for Bridge Activation

The Swiftlet registers jobs with the scheduler to allow activation or deactivation of inbound and outbound bridges via the job system. Each job can enable or disable a specific bridge by name, providing integration with automated workflows.

Internal Queue Naming

  • mail-filter-reject-queue — Queue used to forward rejected inbound emails when a mail filter triggers and is configured to return messages or forward them for further processing.
  • javamail-outbound-error — Queue used by outbound bridges to forward JMS messages that could not be sent as emails, according to the error policy.

Configuration Guide

Configure an Inbound Bridge to Forward Mail to a Queue

Use this scenario to automatically retrieve emails from a mail server and forward them as JMS messages to a SwiftMQ queue. This is useful for integrating external email-based workflows with messaging applications.

  1. Define an inbound bridge under the inbound-bridges entity list.
  2. Set the mail server connection parameters (mail-host, protocol, account name/password, etc.).
  3. Specify the target queue name and type.
  4. Optionally configure mail filters, property translations, and default properties.
<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="mail2queue" enabled="true" mail-host="imap.example.com" mail-host-port="993" mail-host-account-name="user@example.com" mail-host-account-password="secret" protocol="imaps" retrieveinterval="300000" retrieve-max-messages="20" target-name="orders" target-type="queue"/>
  </inbound-bridges>
</swiftlet>

Configure an Outbound Bridge to Send Queue Messages as Email

Use this scenario to send JMS messages from a queue as emails via an SMTP server. This is suitable for alerting, notifications, or integrating messaging with email-based systems.

  1. Define an outbound bridge under the outbound-bridges entity list.
  2. Set the SMTP server parameters (smtp-host, authentication, username/password, etc.).
  3. Specify the source queue or topic.
  4. Optionally configure header translations, default headers, and error handling policies.
<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="queue2mail" enabled="true" smtp-host="smtp.example.com" smtp-authentication-enabled="true" smtp-username="user" smtp-password="secret" source-name="notifications" source-type="queue"/>
  </outbound-bridges>
</swiftlet>

Scheduler Jobs

Inbound Bridge

Description: Activates an Inbound Bridge

Outbound Bridge

Description: Activates an Outbound Bridge

Custom Message Transformer API

The JavaMail Bridge uses transformer interfaces to convert messages between JMS and JavaMail formats. Implement a custom transformer by implementing one of the interfaces below.

Inbound Transformer

Package: com.swiftmq.extension.javamail.inbound

Converts an incoming JavaMail Message into a JMS MessageImpl. The bridge creates one instance and calls setMaxMessageSize initially. For each incoming mail, createMessage is called first to get the JMS message, then transform populates it from the JavaMail message.

public interface Transformer {

    /**
     * Sets the maximum message size in KB. The transformer must throw an
     * exception if the mail message exceeds this size.
     *
     * @param size maximum size in KB (-1 means unlimited)
     */
    void setMaxMessageSize(int size);

    /**
     * Creates the appropriate JMS message instance. Must return one of:
     *   - com.swiftmq.jms.TextMessageImpl
     *   - com.swiftmq.jms.ObjectMessageImpl
     *   - com.swiftmq.jms.MapMessageImpl
     *   - com.swiftmq.jms.StreamMessageImpl
     *   - com.swiftmq.jms.MessageImpl
     *
     * @return a new JMS message
     */
    MessageImpl createMessage();

    /**
     * Transforms the JavaMail message into the JMS message returned
     * by createMessage().
     *
     * @param jmsMessage  the JMS message to populate
     * @param mailMessage the incoming JavaMail message
     */
    void transform(MessageImpl jmsMessage, Message mailMessage)
        throws Exception;
}

Outbound Transformer

Package: com.swiftmq.extension.javamail.outbound

Converts an outgoing JMS MessageImpl into email content. The bridge calls setMessage, then getContent for the body, and getNumberAttachments / getAttachment / getAttachmentFilename for each attachment.

public interface Transformer {

    /**
     * Sets the JMS message to transform. Can be cast to the
     * appropriate javax.jms.Message type.
     *
     * @param message JMS message (SwiftMQ implementation)
     */
    void setMessage(MessageImpl message) throws Exception;

    /**
     * Returns the mail body content (MIME type text/plain).
     *
     * @return mail body text
     */
    String getContent() throws Exception;

    /**
     * Returns the number of attachments.
     *
     * @return attachment count
     */
    int getNumberAttachments() throws Exception;

    /**
     * Returns a DataSource to access the attachment at the given index.
     *
     * @param index attachment index (starts at 0)
     * @return javax.activation.DataSource for the attachment
     */
    DataSource getAttachment(int index) throws Exception;

    /**
     * Returns the filename of the attachment at the given index.
     *
     * @param index attachment index (starts at 0)
     * @return filename, or null if not specified
     */
    String getAttachmentFilename(int index) throws Exception;
}

Outbound Transformer (Alternative)

Package: com.swiftmq.extension.javamail.outbound

An alternative interface that gives full control over the JavaMail MimeMessage creation. The bridge calls transform once per JMS message.

public interface Transformer2 {

    /**
     * Transforms a JMS message into a JavaMail MimeMessage.
     *
     * @param session the JavaMail session
     * @param message the JMS message (SwiftMQ implementation)
     * @return the constructed MimeMessage
     */
    MimeMessage transform(javax.mail.Session session, MessageImpl message)
        throws Exception;
}

Built-in Transformers

Transformer Direction Description
inbound.TextMessageTransformer Inbound Converts text/plain mail content into a JMS TextMessage
inbound.MultipartTransformer Inbound Converts multipart mail with attachments into a JMS ObjectMessage containing an ArrayList of HashMap entries
inbound.GenericTextMessageTransformer Inbound Like TextMessageTransformer but accepts any text/* MIME type
inbound.GenericMultipartTransformer Inbound Like MultipartTransformer but accepts any text/* MIME type for the body part
outbound.TextMessageTransformer Outbound Extracts text from a JMS TextMessage as mail body (no attachments)
outbound.MultipartTransformer Outbound Extracts content and attachments from a JMS ObjectMessage (ArrayList of HashMap entries with keys: content-type, content, filename)

Configuring a Custom Transformer

Set the transformer-class property on an inbound or outbound bridge:

<swiftlet name="xt$javamail">
  <bridges>
    <outbound-bridges>
      <outbound-bridge name="my-bridge"
        transformer-class="com.example.MyOutboundTransformer"
        .../>
    </outbound-bridges>
    <inbound-bridges>
      <inbound-bridge name="my-bridge"
        transformer-class="com.example.MyInboundTransformer"
        transformer-max-message-size="-1"
        .../>
    </inbound-bridges>
  </bridges>
</swiftlet>

Configuration Reference

The top-level entity in routerconfig.xml is <swiftlet name="xt$javamail">.

<swiftlet name="xt$javamail"> Properties

These properties are attributes of the <swiftlet name="xt$javamail"> entity.

Parameter Type Default Mandatory Reboot Required Description
collect-interval Long 10000 No No Collect Interval (ms) for the Usage Section
<swiftlet name="xt$javamail" collect-interval="10000"/>

<outbound-bridges> in <swiftlet name="xt$javamail">

Outbound Bridges

Each <outbound-bridge> entry is identified by its name attribute (the Outbound Bridge).

Parameter Type Default Mandatory Reboot Required Description
enabled Boolean false No No Enables/Disables this Bridge
maillog-enabled Boolean false No No Enables/Disables this the Mail Log of this Bridge
smtp-host String Yes No DNS Name of the SMTP Host
smtp-authentication-enabled Boolean false No No Enables/Disables SMTP Authentication
smtp-username String No No SMTP Username
reuse-transport Boolean true No No Specifies whether the SMTP Transport is reused
send-multipart-text-as-html Boolean false No No Specifies whether multipart mail text should be send as text/html
smtp-password String No No SMTP Password
error-policy String error_queue Yes No How to handle errorneous Input Messages (choices: delete, error_queue, retry)
error-queue String javamail-outbound-error Yes No Name of the Error Queue for this Bridge
retryinterval Long 60000 No No Retry Interval (ms) for Re-Connect
source-name String Yes No Name of the Source
source-type String queue No No Type of the Source (choices: queue, topic)
transformer-class String com.swiftmq.extension.javamail.outbound.TextMessageTransformer No No Name of the Transformer Class
<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="..." smtp-host="..." error-policy="..." error-queue="..." source-name="..."/>
  </outbound-bridges>
</swiftlet>

<header-translations> in <outbound-bridges>

Header Translations

Each <header-translation> entry is identified by its name attribute (the Header Translation).

Parameter Type Default Mandatory Reboot Required Description
message-property String Yes No Message Property Name
mail-header String from Yes No Mail Header Name
<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="...">
      <header-translations>
        <header-translation name="..." message-property="..." mail-header="..."/>
      </header-translations>
    </outbound-bridge>
  </outbound-bridges>
</swiftlet>

<default-headers> in <outbound-bridges>

Default Headers

Each <default-header> entry is identified by its name attribute (the Default Header).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Value
<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="...">
      <default-headers>
        <default-header name="..." value="..."/>
      </default-headers>
    </outbound-bridge>
  </outbound-bridges>
</swiftlet>

<javamail-properties> in <outbound-bridges>

JavaMail Properties

Each <javamail-property> entry is identified by its name attribute (the JavaMail Property).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Value
<swiftlet name="xt$javamail">
  <outbound-bridges>
    <outbound-bridge name="...">
      <javamail-properties>
        <javamail-property name="..." value="..."/>
      </javamail-properties>
    </outbound-bridge>
  </outbound-bridges>
</swiftlet>

<inbound-bridges> in <swiftlet name="xt$javamail">

Inbound Bridges

Each <inbound-bridge> entry is identified by its name attribute (the Inbound Bridge).

Parameter Type Default Mandatory Reboot Required Description
enabled Boolean false No No Enables/Disables this Bridge
maillog-enabled Boolean false No No Enables/Disables this the Mail Log of this Bridge
error-policy String flag Yes No How to handle errorneous Input Mails (choices: delete, flag)
mail-host String Yes No DNS Name of the Mail Host
mail-host-port Integer 110 Yes No Port Number (pop3: 110, pop3s: 995, imap: 143, imaps: 993)
mail-host-account-name String No No Mail Host Account Name
mail-host-account-password String No No Mail Host Account Password
mail-host-account-folder String INBOX No No Mail Host Account Folder
protocol String pop3 No No Protocol (choices: pop3, pop3s, imap, imaps)
retrieveinterval Long 600000 Yes No Retrieve Interval (ms)
retrieve-max-messages Integer 10 Yes No Max. Messages to process per Interval
target-name String Yes No Name of the Target
target-type String queue No No Type of the Target (choices: queue, topic)
target-message-deliverymode String persistent No No Target Message Delivery Mode (choices: persistent, non-persistent)
target-message-ttl Long 0 No No Target Message Time To Live (min: 0)
target-message-priority Integer 4 No No Target Message Priority (range: 0–9)
target-respect-flowcontrol Boolean true No No Respect Flow Control of the Target
transformer-class String com.swiftmq.extension.javamail.inbound.TextMessageTransformer No No Name of the Transformer Class
transformer-max-message-size Integer 1024 No No Max Message Size (KB) (min: -1)
<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="..." error-policy="..." mail-host="..." mail-host-port="..." retrieveinterval="..." retrieve-max-messages="..." target-name="..."/>
  </inbound-bridges>
</swiftlet>

<property-translations> in <inbound-bridges>

Property Translations

Each <property-translation> entry is identified by its name attribute (the Property Translation).

Parameter Type Default Mandatory Reboot Required Description
message-property String Yes No Message Property Name
mail-header String from Yes No Mail Header Name
<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="...">
      <property-translations>
        <property-translation name="..." message-property="..." mail-header="..."/>
      </property-translations>
    </inbound-bridge>
  </inbound-bridges>
</swiftlet>

<default-properties> in <inbound-bridges>

Default Properties

Each <default-property> entry is identified by its name attribute (the Default Property).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Value
<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="...">
      <default-properties>
        <default-property name="..." value="..."/>
      </default-properties>
    </inbound-bridge>
  </inbound-bridges>
</swiftlet>

<javamail-properties> in <inbound-bridges>

JavaMail Properties

Each <javamail-property> entry is identified by its name attribute (the JavaMail Property).

Parameter Type Default Mandatory Reboot Required Description
value String Yes No Value
<swiftlet name="xt$javamail">
  <inbound-bridges>
    <inbound-bridge name="...">
      <javamail-properties>
        <javamail-property name="..." value="..."/>
      </javamail-properties>
    </inbound-bridge>
  </inbound-bridges>
</swiftlet>

<mail-filter-definition> in <inbound-bridges>

Definitions of inbound Mail Filters

Parameter Type Default Mandatory Reboot Required Description
mail-filter-reject-from-address String noreply@domain.com Yes No The Mail Address used as from in rejected Messages
mail-filter-reject-queue String mail-filter-reject-queue Yes No Name of the Queue to forward rejected Messages