// get Ogham instance
MessagingService service = builder.build();
// use Ogham to send messages
service.send(new Email());
service.send(new Sms());
...
// cleanup
((CleanableMessagingService) service).clean();
Release notes
3.0.0
This is a major release that drops support of Java 7, upgrade all dependencies to be up-to-date with latest library, tools and Spring versions.
There are also API and internal improvements.
This version introduces breaking changes. See detailed migration guide to upgrade from 2.0.0 to 3.0.0.
Updates
Java support
Upgrade minimum Java version to Java 8 i.e. drop support of Java 7.
Ogham now supports all Java versions from 8 and up to 15.
Newer Java versions
Ogham should support newer Java versions in the future without any changes. Currently, the latest tested version through compatibility checks is Java 15. |
Spring Boot support
Ogham 3.0+ drops support of Spring Boot 1.3.x.
Ogham is compatible with Spring Boot 1.4.x+ and up to 2.4.x.
Compatibility check
Spring Boot is pluggable. You can start with the basic and add some additional features to your project easily. Ogham is also pluggable and also tries to use Spring Boot features when they are available. To ensure that everything works as expected with any version of Spring Boot, the CI runs automatic compatibility checks (tests to find possible classpath issues). |
Newer versions of Spring Boot
New Spring Boot versions may be supported. As no tests are made, it is not possible to guarantee that you don’t experience a classpath issue due to upgrade of Spring Boot dependencies and code. |
Spring Boot 1.3.x
Ogham doesn’t support Spring Boot 1.3.x anymore. It doesn’t mean that Ogham doesn’t work with Spring Boot 1.3.x but it is no more tested through automatic compatibility checks. |
API changes
Fluent builder consistency for property configuration
As Ogham is fully extensible, there could be an issue of priority due to registration order using previous Ogham version. Therefore a developer could set a configuration value in its code but it could be overridden by an external property. This could be particularly annoying in tests.
Developers that use Ogham have now a dedicated method to set the value with the right type.
For extension developers, all builders now have a consistent API for configuration of values and properties. They all use ConfigurationValueBuilder
that provides the following methods:
-
properties(String…)
that lets extension developers register property names to configure the value externally. -
defaultValue(V)
for extension developers that want to set a default value. -
defaultValue(MayOverride<V>)
for extension developers to provide a value if no default value has been already set for example. -
value(Optional<V>)
for extension developers to set the value. It overrides any value that could be set throughproperties()
ordefaultValue()
.
Rename inlining attributes
-
Rename attribute for image inlining (
ogham-inline-mode
→data-inline-image
) -
Change attributes for CSS inlining to align with image inlining behavior:
-
remove
data-skip-inline
attribute -
use
data-inline-styles
attribute and use the value to select strategy. Currently onlyskip
exists but in future versions other may come.
-
Properties consistency
Rename some properties to be more consistent:
-
ogham.email.bcc
renamed toogham.email.bcc.default-value
-
ogham.email.cc
renamed toogham.email.cc.default-value
-
ogham.email.from
renamed toogham.email.from.default-value
-
ogham.email.sengrid.api-key
renamed toogham.email.sendgrid.api-key
(fix misspelling) -
ogham.email.subject
renamed toogham.email.subject.default-value
-
ogham.email.subject.text.first-line-prefix
renamed toogham.email.subject.extract-from-text.first-line-prefix
-
ogham.email.to
renamed toogham.email.to.default-value
-
ogham.sms.cloudhopper.bind-timeout
renamed toogham.sms.cloudhopper.session.bind-timeout
-
ogham.sms.cloudhopper.connect-max-retry
renamed toogham.sms.cloudhopper.session.connect-retry.max-attempts
-
ogham.sms.cloudhopper.connect-retry-delay
renamed toogham.sms.cloudhopper.session.connect-retry.delay-between-attempts
-
ogham.sms.cloudhopper.connect-timeout
renamed toogham.sms.cloudhopper.session.connect-timeout
-
ogham.sms.cloudhopper.request-expiry-timeout
renamed toogham.sms.cloudhopper.session.request-expiry-timeout
-
ogham.sms.cloudhopper.response-timeout
renamed toogham.sms.cloudhopper.session.response-timeout
-
ogham.sms.cloudhopper.session-name
renamed toogham.sms.cloudhopper.session.name
-
ogham.sms.cloudhopper.unbind-timeout
renamed toogham.sms.cloudhopper.session.unbind-timeout
-
ogham.sms.cloudhopper.window-monitor-interval
renamed toogham.sms.cloudhopper.session.window-monitor-interval
-
ogham.sms.cloudhopper.window-size
renamed toogham.sms.cloudhopper.session.window-size
-
ogham.sms.cloudhopper.window-wait-timeout
renamed toogham.sms.cloudhopper.session.window-wait-timeout
-
ogham.sms.cloudhopper.write-timeout
renamed toogham.sms.cloudhopper.session.write-timeout
-
ogham.sms.freemarker.prefix
renamed toogham.sms.freemarker.path-prefix
-
ogham.sms.freemarker.suffix
renamed toogham.sms.freemarker.path-suffix
-
ogham.sms.from-format-enable-alphanumeric
renamed toogham.sms.from.alphanumeric-code-format.enable
-
ogham.sms.from-format-enable-international
renamed toogham.sms.from.international-format.enable
-
ogham.sms.from-format-enable-shortcode
renamed toogham.sms.from.short-code-format.enable
-
ogham.sms.from
renamed toogham.sms.from.default-value
-
ogham.sms.ovh.no-stop
renamed toogham.sms.ovh.options.no-stop
-
ogham.sms.ovh.sms-coding
renamed toogham.sms.ovh.options.sms-coding
-
ogham.sms.ovh.tag
renamed toogham.sms.ovh.options.tag
-
ogham.sms.to-format-enable-international
renamed toogham.sms.to.international-format.enable
-
ogham.sms.to
renamed toogham.sms.to.default-value
Align Spring property names to Ogham property names.
Samples, tests and documentation are updated.
SMS
In previous version, a conversion from a Java charset into a Cloudhopper charset was configured using a static mapping using ogham.sms.cloudhopper.default-app-charset
and ogham.sms.cloudhopper.smpp-charset
properties.
This behavior has been removed in favor to a better auto-detection mechanism. Therefore the ogham.sms.cloudhopper.default-app-charset
and ogham.sms.cloudhopper.smpp-charset
properties have been removed.
See new SMS encoding features for more details about the new behavior.
New features
Fluent API for message construction
In previous version, developer had to search for implementations of the Content
interface or read the whole documentation. This is great for extensibility but not for ease of use.
The version 3.0 introduces a fluent API for content building. The aim is to guide developer using code autocomplete.
The documentation and samples have been updated to use the fluent API.
See how to use new API.
Auto-configuration lifecycle
Ogham v3.0.0 introduces configuration phases in the configuration lifecycle for MessagingBuilder.standard()
and MessagingBuilder.minimal()
factories:
-
ConfigurationPhase.AFTER_INIT
that is triggered as soon as theMessagingBuilder
is created and instantiate allMessagingConfigurer
classes found for that phase. -
ConfigurationPhase.BEFORE_BUILD
that is triggered when developer callsMessagingBuilder.build()
method. It instantiates allMessagingConfigurer
classes found for that phase.
See automatic configuration section for more details about the concepts and how they interact together.
CSS inlining
Ogham can inline CSS rules to apply styles directly on the HTML tags (see CSS and image inlining).
However, if a CSS file contains at-rules (@
rules such as @import
, @media
, @charset
, …), the file was unparseable in previous versions.
Since v3.0.0, the at-rules are simply ignored instead of failing. Therefore, the valid styles are inlined.
Ogham can now also inline images that are referenced by the following CSS properties:
-
background
-
background-image
-
list-style
-
list-style-image
-
cursor
Images are inline only if url()
points to a relative image.
Relative resources
Ogham now supports relative resource resolution. A template can reference resources like CSS files and images. Relative resources also work for inclusion of template parts.
See resource resolution section for more details.
CSS images inlining
As mentioned above, Ogham can also inline images that are referenced by CSS rules (such as |
Templating
Ogham adds several properties to enable/disable cache for template parsing:
-
ogham.email.thymeleaf.cache
: enable/disable cache for email Thymeleaf templates -
ogham.sms.thymeleaf.cache
: enable/disable cache for SMS Thymeleaf templates
This is currently only available for Thymeleaf but Ogham also provides aliases for later support of template engines:
-
ogham.email.template.cache
: enable/disable cache for email templates (any template engine) -
ogham.sms.template.cache
: enable/disable cache for SMS templates (any template engine) -
ogham.template.cache
: enable/disable cache for all templates
SMS
There are many improvements for the SMPP protocol implementation.
Message encoding
Ogham now supports different encodings for SMPP messages. It means that a SMPP message can be sent using different character encodings.
Developer should not have to read about SMPP protocol and encodings to be able to send a simple SMS. That’s why Ogham provide automatic guessing to use the best encoding. It scans the characters used in the message to use the encoding that uses the minimum bytes while ensuring that received message is readable. The supported encodings are:
-
GSM 7-bit (packed)
-
GSM 8-bit
-
UCS-2
-
Latin-1
In addition to automatic guessing, Ogham also provides a way to define a default encoding (using either ogham.sms.cloudhopper.encoder.default-charset
or ogham.sms.smpp.encoder.default-charset
properties). It is also possible to disable automatic guessing or to enable/disable some encodings:
-
ogham.sms.cloudhopper.encoder.auto-guess.enable
(or its more general aliasogham.sms.smpp.encoder.auto-guess.enable
) to enable/disable automatic guessing. -
ogham.sms.cloudhopper.encoder.gsm7bit-packed.priority
(or its more general aliasogham.sms.smpp.encoder.gsm7bit-packed.priority
) to enable/disable and set priority of GSM 7-bit packed encoding. -
ogham.sms.cloudhopper.encoder.gsm8bit.priority
(or its more general aliasogham.sms.smpp.encoder.gsm8bit.priority
) to enable/disable and set priority of GSM 8-bit encoding. -
ogham.sms.cloudhopper.encoder.ucs2.priority
(or its more general aliasogham.sms.smpp.encoder.ucs2.priority
) to enable/disable and set priority of UCS-2 encoding. -
ogham.sms.cloudhopper.encoder.latin1.priority
(or its more general aliasogham.sms.smpp.encoder.latin1.priority
) to enable/disable and set priority of Latin-1 encoding.
GSM 7-bit packed disabled by default
As many SMPP services doesn’t correctly handle GSM 7-bit packed encoding, this encoding is disabled by default. |
SMPP protocol has a field name Data Coding Scheme. to indicate how the recipient handset should process the received message. The value depends on the character table used to encode the text message. That’s why Ogham also automatically adapts the Data Coding Scheme value according to selected encoding (either using automatic guessing or manually specified).
The automatic algorithm to determine the Data Coding Scheme value can be disabled using either ogham.sms.cloudhopper.data-coding-scheme.auto.enable
or ogham.sms.smpp.data-coding-scheme.auto.enable
. Developer can also provide a fixed value instead using either ogham.sms.cloudhopper.data-coding-scheme.value
or ogham.sms.smpp.data-coding-scheme.value
.
See SMS encoding section for more details.
Carry message using message_payload
field
In initial SMPP protocol, the message text data is carried by short message
field. Since SMPP v3.4, the message text data can be carried by message_payload
TLV (Tag Value Length) field.
Ogham lets developer choose which field to use to carry the text message using configuration properties:
-
ogham.sms.cloudhopper.user-data.use-short-message
(or its more general aliasogham.sms.smpp.user-data.use-short-message
) to useshort message
standard field. -
ogham.sms.cloudhopper.user-data.use-tlv-message-payload
(or its more general aliasogham.sms.smpp.user-data.use-tlv-message-payload
) to usemessage_payload
field.
Short message by default
As |
Automatic split of messages
When a message is too long to fit in one SMS (140 octets including headers and payload), the message is automatically split into segments. The number of characters that can fit in one segment depends on the encoding.
Once again, developer should not have to handle that complexity that’s why Ogham automatically uses the right algorithm to split correctly according to the encoding.
If you are using message_payload
field to carry the message text data (as mentioned above), you may need to disable automatic split of message using one of ogham.sms.cloudhopper.split.enable
, ogham.sms.smpp.split.enable
or ogham.sms.split.enable
.
Session management
Ogham adds several algorithms to handle SMPP session:
-
either create a new session for each message
-
or reuse the current session if still opened
-
or reuse existing session and actively maintain it opened
Contribution
Many thanks to dainv85 for his contribution to keep the session open. |
SmsGlobal
Ogham now provides automatic configuration for well-known services like SmsGlobal.
SmsGlobal handles SMPP protocol. However, this service has some specific features. Therefore, Ogham detects that smpp.smsglobal.com
is used as host and automatically apply a different configuration than the default one:
-
Use
message_payload
TLV field to carry message text data -
Disable split as
message_payload
field is used -
Only enable GSM 8-bit and UCS-2 encodings as others are not supported
-
Use a specific Data Coding Scheme value
-
Automatically adapt SMPP port (1775 instead of 2775 by default)
-
Use interface version 3.4 of the SMPP protocol
Spring integration
Ogham better integrates with Spring Boot features especially regarding templating features:
-
Ogham supports access to Spring beans from templates
-
Ogham correctly handle Spring additional features in a web context
FreeMarker integration
Ogham supports calls to static methods from FreeMarker templates.
Static method calls
Calls to static methods is enabled by default. This can lead to security risks if templates can be modified by a person with malicious intents. Static method calls can be disabled using |
Change variable name for static method calls
The default variable name to access static method calls using FreeMarker is named This can be changed by setting |
FreeMarker now adds .ftlh
extension to activate HTML auto-escaping. Ogham now supports .ftlh
extension.
SendGrid
SendGrid API v3 has changed, Ogham aligns to new SendGrid API and sendgrid-java
features:
-
ogham.email.sendgrid.unit-testing
has been added -
ogham.email.sendgrid.username
is now deprecated -
ogham.email.sendgrid.password
is now deprecated
Ogham now supports attachments through SendGrid.
Auto-cleanup
To release opened resources, Ogham provides automatic cleanup. The MessagingService
is decorated with CleanableMessagingService
to provide the additional clean()
method. It also implements Closable
interface for try-with-resource capabilities.
try (CleanableMessagingService service = (CleanableMessagingService) builder.build()) {
service.send(new Email());
}
// get Ogham instance
MessagingService service = builder.build();
// use Ogham to send messages
service.send(new Email());
service.send(new Sms());
...
// unreference service
service = null;
... after some time the JVM will call finalize() method to cleanup resources
Miscellaneous
Add some properties:
-
ogham.mimetype.tika.fail-if-octet-stream
: Tika doesn’t fail if it can’t detect mimetype accurately. It returnsapplication/octet-stream
instead. As Ogham rely on an exception to try another detection algorithm, this property has been added to force to fail if Tika returnsoctet-stream
. This istrue
by default. -
ogham.wrap-uncaught-exceptions.enable
: Ogham always throw checked exceptions. However, libraries that are used by Ogham may throw unchecked exceptions (RuntimeException
). To avoid your application to fail unexpectedly due to uncaught error, Ogham catchesRuntimeException
and wrap them with a checked exception. This istrue
by default.
Test utilities
Test utilities have been reorganized and new features have been added.
Logging
When running many tests, it may be difficult to find logs corresponding to a particular test. Especially in a Continuous Integration environment.
Ogham provides rules and extensions to help visualize quickly start and end of a test:
-
LoggingTestRule
: JUnit 4 rule -
LoggingTestExtension
: JUnit 5 extension -
LoggingTestExtension
: Spock extension
11:37:20.443 [main] INFO -
╔══════════════════════════════════════════════════════════════════════════════════════════════════╗
║MultiContentTranslatorTest.textTemplateNotFoundShouldSkipTheErrorAndReturnOneParsedContent ║
╚══════════════════════════════════════════════════════════════════════════════════════════════════╝
11:37:20.445 [main] DEBUG f.s.o.c.t.c.MultiContentTranslator - Translate the sub content using templateParser
11:37:20.458 [main] INFO f.s.o.c.t.c.MultiContentTranslator - null => ignoring
fr.sii.ogham.core.exception.handler.TemplateNotFoundException: null
11:37:20.458 [main] DEBUG f.s.o.c.t.c.MultiContentTranslator - Translate the sub content using templateParser
11:37:20.458 [main] DEBUG f.s.o.c.t.c.MultiContentTranslator - Sub content added
11:37:20.458 [main] INFO -
┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│MultiContentTranslatorTest.textTemplateNotFoundShouldSkipTheErrorAndReturnOneParsedContent │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
│SUCCESS │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
SMS
It is now possible to simulate a slow SMPP server by annotating the test with @SmppServerConfig
:
@Rule public final SmppServerRule<SubmitSm> smppServer = new JsmppServerRule();
@Test
@SmppServerConfig(slow = @Slow(sendBindRespDelay = 500L)) (1)
public void connectionTimeout() throws MessagingException {
// send a SMS here
}
1 | This adds 500ms to the response of a bind request |
Make several assertions at once
Instead of failing on first assertion, Ogham provides OghamAssertions.assertAll
method to execute all assertions and make a complete report.
Use random ports
To test that emails or SMS are correctly received, Ogham starts local servers. To run all tests in parallel, using random ports are required (otherwise tests will fail indicating that port is already in use).
Ogham provides JUnit rules to start on random ports:
-
Using
RandomPortGreenMailRule
(instead ofGreenMailRule
) for testing email in JUnit 4 -
Using
JsmppServerRule
for testing SMS
Ogham also provides extensions for Spring Boot tests:
-
GreenMailRandomSmtpPortInitializer
for starting GreenMail on random port, makeGreenMailRule
instance injectable in the test (with@Autowired
) and providegreenmail.smtp.port
property that is usable in Spring test and application. -
JsmppServerInitializer
for starting JSMPPServer on random port, makeJsmppServerRule
instance injectable in the test (with@Autowired
) and providejsmpp.server.port
property that is usable in Spring test and application. -
WireMockInitializer
for starting WireMockServer on random port, makeWireMockRule
instance injectable in the test (with@Autowired
) and providewiremock.server.port
property that is usable in Spring test and application.
Internal improvements
Java Mail structure
Improve Mime Message structures according to included parts.
If the source email has only one textual content (text/html for example), the structure is now:
[text/html] (root/body)
If the source email has HTML content with embedded attachments (images for example), the structure is:
[multipart/related] (root/body)
[text/html]
[image/png] (embedded image 1)
[image/gif] (embedded image 2)
If the source email has HTML content with attachments, the structure is:
[multipart/mixed] (root)
[text/html] (body)
[application/pdf] (attached file 1)
[application/octet-stream] (attached file 2)
If the source email has HTML content with embedded attachments (images for example) and additional attachments, the structure is:
[multipart/mixed] (root)
[multipart/related] (body)
[text/html]
[image/png] (embedded image 1)
[image/gif] (embedded image 2)
[application/pdf] (attached file 1)
[application/octet-stream] (attached file 2)
If the source email has several textual contents (text/html and text/plain for example), the structure is:
[multipart/alternative] (root/body)
[text/plain] (alternative body)
[text/html] (main body)
If the source email has several textual contents (text/html and text/plain for example) and embedded attachments (images for example), the structure is:
[multipart/related] (root/body)
[multipart/alternative]
[text/plain] (alternative body)
[text/html] (main body)
[image/png] (embedded image 1)
[image/gif] (embedded image 2)
If the source email has several textual contents (text/html and text/plain for example) and attachments, the structure is:
[multipart/mixed] (root)
[multipart/alternative] (body)
[text/plain] (alternative body)
[text/html] (main body)
[application/pdf] (attached file 1)
[application/octet-stream] (attached file 2)
If the source email has several textual contents (text/html and text/plain for example), embedded attachment (images for example) and attachments, the structure is:
[multipart/mixed] (root)
[multipart/related] (body)
[multipart/alternative]
[text/plain] (alternative body)
[text/html] (main body)
[image/png] (embedded image 1)
[image/gif] (embedded image 2)
[application/pdf] (attached file 1)
[application/octet-stream] (attached file 2)
Continuous Integration
As mentioned above, CI automatically performs many compatibility checks to ensure that Ogham is compatible with Java and Spring Boot versions:
-
Include (or not) some Ogham features
-
Sender implementations (Jakarta Mail, SendGrid, Cloudhopper, …)
-
Template engine integrations (Thymeleaf, FreeMarker, …)
-
-
Include (or not) some Spring Boot features
-
Web application
-
Template engine (Thymeleaf, FreeMarker, …)
-
Spring Mail (Jakarta Mail)
-
-
Spring Boot versions
-
1.4.x
-
1.5.x
-
2.1.x
-
2.2.x
-
2.3.x
-
2.4.x
-
-
Java versions
-
8 (Oracle and OpenJDK)
-
9 (Oracle and OpenJDK)
-
10 (OpenJDK)
-
11 (Oracle and OpenJDK)
-
12 (OpenJDK)
-
13 (OpenJDK)
-
14 (OpenJDK)
-
15 (OpenJDK)
-
It means that Ogham checks compatibility over more than 2000 combinations.
2.0.0 / 2018-01-03
Features
-
New builder API
-
Only fluent API (remove all Email/SMS constructors)
-
Follow Spring Boot starter conventions
-
Better Spring Boot integration with existing module (spring-boot-start-mail, spring-boot-starter-thymeleaf, spring-boot-starter-freemarker, spring-boot-starter-sendgrid)
-
Add possibility to create its own configurer
1.0.0 / 2015-10-08
Features
-
[Add Spring integration with Spring Boot](usage/integration.html#integrate-with-spring-boot)
-
[Add Spring integration using Java config or XML config](usage/integration.html#manual-integration-with-spring)
-
Add fluent API
-
Service now wrap all exceptions (even runtime exceptions) into checked exception
-
Add OVH implementation for sending SMS
-
Add basic i18n support
-
Allow to configure different template prefixes/suffixes for each kind of message
0.0.1 / 2015-06-22
Features
-
[APIs for multi-implementation support](config/select-implementation.html)
-
[APIs for multi-channel support](usage/index.html)
-
[Send emails using Java Mail API (first implementation)](config/select-implementation.html#email)
-
[Send SMS using Cloudhopper SMPP (first implementation)](config/select-implementation.html#sms)
-
Integrate Thymeleaf as template engine (first integration)
-
[Manage both html and text emails](usage/how-to-send-email.html#both-html-and-text)
-
[Automatically fill email/sms with information from properties](config/properties.html)
-
[Automatically fill subject for emails provided directly in template](usage/how-to-send-email.html#sending-email-with-subject-from-template)
-
[Handle email attachments](usage/how-to-send-email.html#attachments)
-
[Apply basic HTML transformations to make the email work on several email clients](features/hidden-complexity.html)
-
Detect mimetype automatically
-
Simple lookup management for finding templates and template resources