JavaMail Bridge Extension Swiftlet
Overview
The JavaMail Bridge Extension Swiftlet provides integration between SwiftMQ queues/topics and email systems using the JavaMail API. It enables bidirectional message exchange: inbound bridges retrieve emails and convert them into JMS messages, while outbound bridges consume JMS messages and send them as emails via SMTP.
Features
Inbound Mail Bridges
Inbound bridges poll a configured mail server (using POP3, IMAP, or their secure variants) and convert incoming emails into JMS messages, which are then delivered to a specified queue or topic. Each bridge is highly configurable, supporting custom property mappings, default properties, and mail filtering.
Mail filters can be defined to reject or accept messages based on header values, body content, attachment MIME types, or message size. Filters can be set to reject on match or not, return rejected messages to the sender, and specify custom rejection messages. When a message is rejected, it can be optionally forwarded to a configured queue for further processing or auditing.
Transformers are used to convert email content into JMS messages. Several built-in transformers are provided (e.g., text-only, multipart), and custom transformers can be implemented by extending the Transformer interface. The transformer is responsible for enforcing maximum message size and for mapping email content to the appropriate JMS message type.
Mail Filters
Mail filters can be defined per inbound bridge to validate incoming emails before they are converted to JMS messages. Filter types include header, body, attachment, and size. Each filter supports properties relevant to its type (e.g., regex for headers, MIME type for attachments, max size for size filter). Filters can be set to reject on match or not, and can optionally return rejected messages to the sender with a custom message.
Property Translations and Default Properties
Property translations allow mapping of email headers (such as from, to, subject) to JMS message properties. Default properties can be set to assign constant values to JMS properties for all messages processed by the bridge.
Custom Transformers
Inbound bridges use a transformer class to convert emails into JMS messages. The transformer must implement the com.swiftmq.extension.javamail.inbound.Transformer interface, which defines methods for setting the maximum message size, creating a JMS message, and transforming the email into the JMS message. Built-in transformers include text and multipart variants, but users can supply their own for specialized processing.
Configuration Example:
<swiftlet name="xt$javamail">
<inbound-bridges>
<inbound-bridge name="mail2queue" enabled="true" mail-host="mail.example.com" mail-host-account-name="user" mail-host-account-password="secret" target-name="orders"/>
</inbound-bridges>
</swiftlet>
Outbound Mail Bridges
Outbound bridges consume JMS messages from a configured queue or topic and send them as emails via SMTP. Each bridge can be configured with SMTP server details, authentication, and message transformation logic. Outbound bridges support error handling policies that determine what happens if a message cannot be sent (delete, retry, or forward to an error queue).
Transformers are used to convert JMS messages into email content and attachments. Built-in transformers handle text and multipart messages, and users can implement custom transformers by extending the com.swiftmq.extension.javamail.outbound.Transformer or Transformer2 interfaces. Header translations and default headers allow mapping JMS properties to email headers and setting constant header values.
Error Handling Policies
Outbound bridges support three error handling policies: delete (discard the message), retry (attempt to resend after a configured interval), and error_queue (forward the message to a designated error queue for further analysis).
Header Translations and Default Headers
Header translations map JMS message properties to email headers, allowing for flexible integration with external email systems. Default headers can be set to assign constant values to email headers for all outgoing messages.
Custom Transformers
Outbound bridges use a transformer class to convert JMS messages into email format. The transformer must implement the com.swiftmq.extension.javamail.outbound.Transformer interface (for message/attachment extraction) or the Transformer2 interface (for full control over JavaMail message creation).
Configuration Example:
<swiftlet name="xt$javamail">
<outbound-bridges>
<outbound-bridge name="queue2mail" enabled="true" smtp-host="smtp.example.com" source-name="alerts"/>
</outbound-bridges>
</swiftlet>
Job Integration for Bridge Activation
The Swiftlet registers jobs for activating and deactivating inbound and outbound bridges with the SwiftMQ Scheduler Swiftlet. These jobs can be triggered manually or scheduled, enabling dynamic control over bridge operation without requiring a router restart.
Usage and Statistics Collection
The Swiftlet maintains a usage section that tracks active inbound and outbound bridges, including statistics such as the number of messages transferred and the last transfer time. The collection interval for these statistics can be configured globally.
Configuration Example:
<swiftlet name="xt$javamail" collect-interval="20000"/>
Custom Transformer Interfaces
For inbound bridges, custom transformers must implement the com.swiftmq.extension.javamail.inbound.Transformer interface, which requires methods for setting the maximum message size, creating a JMS message, and transforming a JavaMail message into a JMS message. For outbound bridges, custom transformers must implement either the com.swiftmq.extension.javamail.outbound.Transformer interface (for extracting content and attachments from JMS messages) or the Transformer2 interface (for full JavaMail message creation).
Inbound Transformer Interface
Implement com.swiftmq.extension.javamail.inbound.Transformer with methods:
- void setMaxMessageSize(int size): Enforce maximum allowed message size (in KB).
- MessageImpl createMessage(): Create a new JMS message instance (e.g., TextMessageImpl, ObjectMessageImpl).
- void transform(MessageImpl jmsMessage, Message mailMessage): Convert the JavaMail message into the JMS message, throwing an exception if conversion fails or size is exceeded.
Outbound Transformer Interfaces
Implement either:
- com.swiftmq.extension.javamail.outbound.Transformer with methods for setting the JMS message, extracting content, counting and retrieving attachments, and getting filenames.
- Or Transformer2, which defines MimeMessage transform(Session session, MessageImpl message), allowing full control over JavaMail message creation.
Internal Queue Naming
mail-filter-reject-queue— Queue to which rejected inbound emails are forwarded when a mail filter rejects a message and forwarding is enabled.javamail-outbound-error— Default error queue for outbound bridges when error-policy is set to error_queue.
Configuration Guide
Configure an Inbound Bridge to Forward Emails 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 email-based workflows with messaging applications.
- Define an inbound bridge under the xt$javamail swiftlet.
- Set the mail server connection properties (mail-host, mail-host-account-name, mail-host-account-password, protocol, etc.).
- Specify the target queue name in target-name and set enabled="true".
<swiftlet name="xt$javamail">
<inbound-bridges>
<inbound-bridge name="mail2queue" enabled="true" mail-host="mail.example.com" mail-host-account-name="user" mail-host-account-password="secret" target-name="orders"/>
</inbound-bridges>
</swiftlet>
Configure an Outbound Bridge to Send Queue Messages as Email
Use this scenario to consume messages from a SwiftMQ queue and send them as emails via SMTP. This is commonly used for alerting or notification systems.
- Define an outbound bridge under the xt$javamail swiftlet.
- Set the SMTP server properties (smtp-host, smtp-authentication-enabled, smtp-username, smtp-password, etc.).
- Specify the source queue name in source-name and set enabled="true".
<swiftlet name="xt$javamail">
<outbound-bridges>
<outbound-bridge name="queue2mail" enabled="true" smtp-host="smtp.example.com" source-name="alerts"/>
</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 |