SMTP Module
Content
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.
// 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 );
}
// 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];
}
// 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 );
}
// 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
-
Create a new Application, add the SMTP-Module to this backend and fill out the config-parameters according to your SMTP-Server
-
Create a new Module, download it import it into your IDE. Set the SMTP-Module as an included Module
-
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:
Attribute |
Description |
Example |
intervalMinutes |
This long value defines how often the queue sends messages. The minimum resolution is one minute. |
15 |
lastTimeTriggered |
The date value lastTimeTriggered is the base reference from which the next queue process is triggered (basically: lastTimeTriggered + intervalMinutes). Hint: You can manipulate the lastTimeTriggered value to define a specific day time for processing your Queue. |
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( );