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.
- Define an inbound bridge under the inbound-bridges entity list.
- Set the mail server connection parameters (mail-host, protocol, account name/password, etc.).
- Specify the target queue name and type.
- 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.
- Define an outbound bridge under the outbound-bridges entity list.
- Set the SMTP server parameters (smtp-host, authentication, username/password, etc.).
- Specify the source queue or topic.
- 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 |