. . .

SMTP Module

Introduction

The SMTP module enables app developers to send emails to MTAs via the middleware. In future, it will also support messages with templates using the FreeMarker template engine.

Configuration

Configuration-option

Description

Default value

Example

SMTP Host

Hostname of the SMTP server

localhost

localhost

Encoding

The encoding used to send the mails

UTF-8

UTF-8

Port

The port of the SMTP server

25

25

Uses SMTP Authorization

Indicates whether SMTP-Authorization will be used

true

false

SMTP Username

The username of the SMTP-account, will be ignored if authorization is set to false

 

username

SMTP Password

The password of the SMTP-account, will be ignored if authorization is set to false

 

password

Uses StartTLS

Indicates whether the server uses StartTLS

true

false

Uses SSL

Indicates whether the server uses SSL

true

false

Uses Debug

Indicates whether the server uses Debug

true

false

Use

The SMTP module provides you the class message, a container for an email containing all data which may be included. You can also use the attachment class to attach files and images to your e-mail message. In future versions you can also use the TemplateMessage and Template-classes to comfortably create messages with a predefined text. The snippets below give you an example to handle the messages and attachments in your app.

Android
// At first configure the datastore and create or load a user:
private void start( )
{
//load a existing user and configure the datastore
final User user = new User( );
final String userName = "john.doe@apiomat.com"; // NOTE: we use
user.setUserName( userName );
user.setPassword( "123456" );
Datastore.configureWithCredentials( user );
/* save user (if it does not exist)*/
final AOMEmptyCallback saveCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
loadMessages( userName );
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
AOMEmptyCallback loadMeCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
loadMessages( userName );
}
else
{
/* create new apiomat user*/
user.saveAsync( saveCB );
}
}
};
user.loadMeAsync( loadMeCB );
}
 
// Now load an existing message model:
private void loadMessages( final String userName )
{
final String subject = "Test subject";
AOMCallback<List<Message>> getMessagesCB = new AOMCallback<List<Message>>( )
{
@Override
public void isDone( List<Message> objects, boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
if ( objects.size( ) == 0 )
{
/* no models found -> create a new message */
createMessage( userName, subject );
}
else if ( objects.size( ) == 1 )
{
/* found message --> create a new attachment */
createAttachment( objects.get( 0 ) );
}
else
{
Log.e( TAG, "Too many messages." );
}
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
Message.getMessagesAsync( "", getMessagesCB );
}
 
// create a new conversation model:
// You can either set the HTML-text-attribute or plain-text-attribute to
// create a message that contains HTML or plain-text. If you set both, the
// HTML-text will be set as last part of the email and plain-text as alternative part
// (according to RFC1341 clients should display the last part if they are capable to display
// this mime-type, otherwise they should fall back to alternatives like plain-text).
private void createMessage( final String userName, final String subject )
{
final Message message = new Message( );
message.setSubject( subject );
message.setFrm( "testsender@apiomat.com" );
message.setHtmlText( "<!DOCTYPE html><html><body>Testmessage</body></html>" );
message.setPlainText( "Testmessage" );
List<String> recipients = new ArrayList<String>( );
recipients.add( userName );//NOTE: at this point, the username should be a valid email, you have to check this by yourself
message.setTo( recipients );
AOMEmptyCallback saveCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
createAttachment( message );
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
message.saveAsync( saveCB );
}
 
// After a message exists, an attachment can be attached to the message
// (but you can also leave this out) and the message can be sent afterwards
// by setting the attribute "sendMessage" to the long value of 1.
private void createAttachment( final Message message )
{
final Attachment attachment = new Attachment();
attachment.setFileName( "myFileName.jpg" );
attachment.setMimeType( "image/jpg" );
AOMEmptyCallback saveCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
postAttachmentData( message, attachment );
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
attachment.saveAsync( saveCB );
}
// add the attachment data to the attachment-model
private void postAttachmentData(final Message message, final Attachment attachment)
{
 
byte[] data = new byte[100];//NOTE: at this point, you should load your data from elsewhere
 
final AOMCallback<String> postAttachmentCB = new AOMCallback<String>( )
{
@Override public void isDone( String resultObject, boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
sendMessage( message );
}
};
 
final AOMEmptyCallback postDataCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
message.postAttachmentAsync( attachment, postAttachmentCB );
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
 
attachment.postFileAsync( data, postDataCB );
}
 
private void sendMessage(final Message message)
{
final AOMEmptyCallback messageSendCB = new AOMEmptyCallback( )
{
@Override
public void isDone( boolean wasLoadedFromStorage, ApiomatRequestException exception )
{
if ( exception == null )
{
Log.i(TAG, "successfully saved and sent the message");
}
else
{
Log.e( TAG, exception.getMessage( ) );
}
}
};
message.setSendMessage( 1L );
message.saveAsync( messageSendCB );
}
Objective-C
// At first configure the datastore and create or load a user:
- (void) start {
 
NSString *userName = @"john.doe@apiomat.com";
AOMUser *user = [[AOMUser alloc] initWithUserName:userName andPassword:@"123456"];
[AOMDatastore configureWithCredentials:user];
 
/* Login user */
[user loadMeAsyncWithFinishingBlock:^(NSError *error) {
 
if(error == false)
{
[self loadMessages:userName];
}
else
{
/* Try to create new user */
[user saveAsyncWithBlock:^(NSError *error) {
[self loadMessages:userName];
}];
}
}];
}
 
// Now load an existing message model:
- (void) loadMessages:(NSString*) userName {
 
NSString *subject = @"Test subject";
NSString *query = [NSString stringWithFormat:@"subject==\"%@\"", subject ];
AOMBlockWithResults getMessagesCB = ^(NSMutableArray *models, NSError *error) {
if(error == FALSE)
{
if([models count] == 0)
{
[self createMessage:userName withSubject:subject ];
}
else if ([models count] == 1)
{
[self createAttachment:[models objectAtIndex:0]];
}
else
{
NSLog(@"Too many messages.");
}
}
};
[Message getAsyncWithQuery:query withBlock:getMessagesCB];
}
 
// create a new conversation model:
// You can either set the HTML-text-attribute or plain-text-attribute to
// create a message that contains HTML or plain-text. If you set both, the
// HTML-text will be set as last part of the email and plain-text as alternative part
// (according to RFC1341 clients should display the last part if they are capable to display
// this mime-type, otherwise they should fall back to alternatives like plain-text).
 
- (void) createMessage:(NSString *)userName withSubject:(NSString *)subject{
 
Message *message = [Message new];
[message setSubject:subject];
[message setFrm:@"testsender@apiomat.com"];
[message setHtmlText:@"<!DOCTYPE html><html><body>Testmessage</body></html>"];
[message setPlainText:@"Testmessage"];
[message setTo:[[NSMutableArray alloc] initWithObjects:userName, nil]];
[message saveAsyncWithBlock:^(NSError *error) {
if(error == FALSE)
{
[self createAttachment:message];
}
}];
}
// After a message exists, an attachment can be attached to the message
// (but you can also leave this out) and the message can be sent afterwards
// by setting the attribute "sendMessage" to the long value of 1.
- (void) createAttachment:(Message *)message {
 
Attachment *attachment = [Attachment new];
[attachment setFileName:@"myFilename.jpg"];
[attachment setMimeType:@"image/jpg"];
AOMEmptyBlock saveCB =^(NSError *error) {
if(error == FALSE)
{
[self postAttachmentData:message withAttachment:attachment];
}
};
[attachment saveAsyncWithBlock:saveCB];
}
 
- (void) postAttachmentData:(Message *)message withAttachment:(Attachment *)attachment{
NSData *data = [[NSData alloc] init];//NOTE: at this point, you should load your data from elsewhere
AOMEmptyBlock postAttachmentCB =^(NSError *error ) {
if ( error == FALSE )
{
[self sendMessage: message];
}
};
AOMEmptyBlock postDataCB =^(NSError *error ) {
if ( error == FALSE )
{
[message postAttachmentAsync: attachment andWithBlock:postAttachmentCB];
}
};
[attachment postFileAsync:data andWithBlock:postDataCB];
}
- (void) sendMessage: (Message *)message {
AOMEmptyBlock messageSendCB =^(NSError *error) {
if ( error == FALSE )
{
NSLog(@"successfully saved and sent the message");
}
};
//send the message by setting the sendMessage attribute to 1
[message setSendMessage:1];
[message saveAsyncWithBlock: messageSendCB];
}

JavaScript
// At first configure the datastore and create or load a user:
function start() {
//load a existing user and configure the datastore
var user=new Apiomat.User();
var userName="john.doe@apiomat.com";
user.setUserName(userName);
user.setPassword("123456");
Apiomat.Datastore.configureWithCredentials(user);
/* save user */
var saveCB= {
onOk:function () {
loadMessages(userName);
},
onError:function(error) {
console.log(error);
}
};
/* load user */
var loadMeCB={
onOk:function () {
loadMessages(userName);
},
onError:function (error) {
if (error.statusCode==840) {
/* create a new Apiomat.User */
user.save(saveCB);
}
console.log(error);
}
};
user.loadMe(loadMeCB);
}
 
// Now load an existing message model:
function loadMessages(userName) {
var subject="Test subject";
//first, get all messages
var getMessageCB={
onOk:function (objects) {
if (objects.length==0) {
/* no models found -> create a new message */
createMessage(userName,subject);
} else if(objects.length==1) {
/* found message --> create a new attachment */
createAttachment(objects[0]);
} else {
console.log("Too many messages.");
}
},
onError:function (error) {
console.log(error);
}
}
Apiomat.Message.getMessages ("", getMessageCB);
}
 
// create a new conversation model:
// You can either set the HTML-text-attribute or plain-text-attribute to
// create a message that contains HTML or plain-text. If you set both, the
// HTML-text will be set as last part of the email and plain-text as alternative part
// (according to RFC1341 clients should display the last part if they are capable to display
// this mime-type, otherwise they should fall back to alternatives like plain-text).
 
function createMessage(userName, subject) {
var message=new Apiomat.Message();
var userNames=[userName,"username1","username2"];
message.setSubject(subject);
message.setFrm( "testsender@apiomat.com" );
message.setHtmlText( "<!DOCTYPE html><html><body>Testmessage</body></html>" );
message.setPlainText( "Testmessage" );
var recipients = [ userName ]; //NOTE: at this point, the username should be a valid email, you have to check this by yourself
message.setTo( recipients );
var saveCB={
onOk:function () {
/* create a new message */
createAttachment(message);
},
onError: function (error) {
console.log(error);
}
};
message.save(saveCB);
}
 
 
// After a message exists, an attachment can be attached to the message
// (but you can also leave this out) and the message can be sent afterwards
// by setting the attribute "sendMessage" to the long value of 1.
function createAttachment(message) {
var attachment=new Apiomat.Attachment();
attachment.setFileName( "myFileName.jpg" );
attachment.setMimeType( "image/jpg" );
var saveCB = {
onOk:function () {
/* add attachment and send */
postAttachmentData(message, attachment);
},
onError:function (error) {
console.log(error);
}
}
/* save attachment */
message.save(saveCB);
}
function postAttachmentData( message, attachment )
{
var data = [];//NOTE: at this point, you should load your data from elsewhere
var postAttachmentCB = {
onOk: function() {
sendMessage(message);
},
onError:function (error) {
console.log(error);
}
};
var postDataCB = {
onOk: function() {
message.postAttachment( attachment, postAttachmentCB );
}
onError:function() {
console.log( error );
}
};
attachment.postFile( data, postDataCB );
}
function sendMessage( message )
{
var messageSendCB = {
onOk: function(){
Log.i(TAG, "successfully saved and sent the message");
}
onError: function() {
Log.e( TAG, exception.getMessage( ) );
}
};
//send the message by setting the sendMessage attribute to 1
message.setSendMessage( 1L );
message.saveAsync( messageSendCB );
}
Swift
// At first configure the datastore and create or load a user:
func start() {
 
let userName = "john.doe@apiomat.com
let user = User(userName: userNamer, password: "123456")
DataStore.configureWithCredentials(user:user)
 
/* Login user */
user.loadMe { (error) in
 
if error == false {
 
self.loadMessages(userName)
} else {
/* Try to create new user */
user.save { (error) in
self.loadMessages(userName)
}
}
}
}
 
// Now load an existing message model:
func loadMessages(userName: String) {
 
let subject = @"Test subject";
let query = "subject==\(subject)")
let cbMessage : CompletionHandlerWithResults = {(models, error) in
if error == false {
if models.count == 0 {
self.createMessage(username, withSubject:subject)
} else if ([models count] == 1) {
self.createAttachment(models[0])
} else {
print("Too many messages.")
}
}
}
Message.loadList(query: query, usePersistentStorage: false, completion: cbMessage)
}
 
// create a new conversation model:
// You can either set the HTML-text-attribute or plain-text-attribute to
// create a message that contains HTML or plain-text. If you set both, the
// HTML-text will be set as last part of the email and plain-text as alternative part
// (according to RFC1341 clients should display the last part if they are capable to display
// this mime-type, otherwise they should fall back to alternatives like plain-text).
 
func createMessage(userName:String, withSubject subject:String){
 
var message = Message()
message.subject = subject
message.frm = "testsender@apiomat.com"
message.htmlText "<!DOCTYPE html><html><body>Testmessage</body></html>"
message.plainText = "Testmessage"
message.to = [userName]
message.save { (error) in
if error == false {
self.createAttachment(message)
}
}
}
// After a message exists, an attachment can be attached to the message
// (but you can also leave this out) and the message can be sent afterwards
// by setting the attribute "sendMessage" to the long value of 1.
func createAttachment(message: Message) {
 
var attachment = Attachment()
attachment.fileName = "myFilename.jpg"
attachment.mimeType = "image/jpg"
let saveCB: CompletionHandler = {(error) in
if error == false {
 
self.postAttachmentData(message, withAttachment:attachment)
}
}
attachment.save(saveCB)
}
 
func postAttachmentData(message: Message, withAttachment attachment: Attachment) {
let data = NSData() //NOTE: at this point, you should load your data from elsewhere
let postAttachmentCB: CompletionHandler = {(error) in
if error == false {
self.sendMessage(message)
}
}
 
let postDataCB: CompletionHandler = {(error) in
if error == false {
message.post(attachment, completion:postAttachmentCB)
}
}
attachment.postFile(data, completion:postDataCB)
}
 
func sendMessage(message: Message) {
let messageSendCB: CompletionHandler = {(error) in
if error == false {
 
print("successfully saved and sent the message"
}
}
//send the message by setting the sendMessage attribute to 1
message.sendMessage = 1
message.save(messageSendCB)
}

You can also send messages via dashboard, by creating a new Message-Object there, filling all fields and finally set the sendMessage-Attribute to "1".

How to send a message from a module

  1. Create a new Application, add the SMTP-Module to this backend and fill out the config-parameters according to your SMTP-Server

  2. Create a new Module, download it import it into your IDE. Set the SMTP-Module as an included Module

  3. You can send an Mail using the following code:

    Message message = new Message();
    List<String> toList = new ArrayList<String>();
    toList.add( "customer@customerMail.com" );
     
     
    message.setTo( toList );
    message.setFrm( "apinaut@apiomat.com" );
    message.setSubject( "Subject of the Test-Mail" );
    message.setPlainText( "This is the Text inside the Mail. Greetings, Apinaut" );
     
    try
    {
    MailCreationHelper.sendMessage( message, null, r );
    }
    catch ( Exception e )
    {
    e.printStackTrace();
    }

Message Queues

ApiOmat version 2.6.4 provides a new way to send messages. The idea is to bundle multiple messages in a queue to send them via batch process through one single SMTP connection. This helps to improve general performance such as network traffic optimization.

The message Queue is a new SMTP module class which references one or more Message objects. The Queue has the following attributes:

images/download/attachments/27722214/Queue_dataEditor.PNG

Attribute

Description

Example

intervalMinutes

This long value defines how often the queue sends messages. The minimum resolution is one minute.
The queue is triggered every specified intervalMinutes if it contains unsent messages.

15

lastTimeTriggered

The date value lastTimeTriggered is the base reference from which the next queue process is triggered (basically: lastTimeTriggered + intervalMinutes).
An empty value means that the queue wasn't triggered yet. In that case the creation date will be picked as base reference.

Hint: You can manipulate the lastTimeTriggered value to define a specific day time for processing your Queue.
E.g. if you want to sent queued messages once a day on 03:00 AM you just need to set lastTimeTriggered to yesterdays 03:00 AM and intervalMinutes to 1440.

Mar 04, 2018 12:00:00 PM

sentImmediatly

This flag triggers the queue manually. Every containing unsent Message will be sent immediatly. The sentImmediatly has to be set from 0 or empty to 1.

1

messages

This attributes contains a collection of referenced message objects. Queued messages will be removed automatically if they have been sent.

<message References>

How to create Queues (Native Module)

/* create Queue */
Queue queue = ( Queue ) MyModule.AOM.createObject( "applicationName", "moduleName", "modelName", request );
queue.setIntervalMinutes( 15L );
queue.save( );
 
/* set messages to Queue */
queue.postMessages( message );
queue.postMessages( message2 );
queue.postMessages( message3 );
 
/* trigger Queue manually */
queue.setSendImmediately( 1L );
queue.save( );