Introduction
OSA-Mailer engine allows you to send dynamic and sophisticated E-mails, using Smart Templates
O.S.A stands for: Open Smart Alert
Open
It is a free and open-source feature-rich backend engine for sending automated E-mails.
Smart
It is using sophisticated, programable HTML templates ("Smart Templates") that can provide advanced capabilities when producing E-mails.
Alert
It is designed in the context of alerting or notifying about events and elegantly providing relevant context about them. (It can also be used to send newsletters, but for now you'll have to handle your own subscriptions backend services).
Main Features
- Manages different smart templates for different categories of your choice
- Identifies a common denominator for multiple E-mails and merges them into a single E-mail with accumulated context as an optional feature to reduce spam
- Supports multiple template engines with large communities and great support:
Tera
,Liquid
andHandlebars
- (To be implemented) Allowing custom functionalities such as embedding dynamic QRCodes or defanging untrusted URLs, IP Addresses and E-mail addresses
- More community ideas to follow...
Smart Templates & Marketplace
Logically separates the front-end, back-end and data layers which should allow for easier community adaption (one is not required to understand all layers when using, maintaining or configuring the tool)
-
Develop or use ready Smart Templates that are programmed to act differently upon varying data inputs
-
(WIP) Download or share Smart Templates with the community marketplace
Minimalist & Reliable
It is written in the Rust programming language which is both highly reliable and packs all mentioned capabilities in a single, small, high-performing executable (Cloud friendly).
MVP Status
The project is still in Minimum Viable Product state and is subject to constant change.
OSA-Mailer Setup
Preface
Currently, OSA-Mailer simply checks its outbox
directory each time it is executed. As the development is proceeding towards a stable, complete version, OSA-Mailer is currently built only for Windows (i686 to support both 32bit and 64bit architectures) but of course the source code could be built into any architecture that is supported by LLVM & Rust.
If you wish for an early build for Linux, or any other architectural build, feel free to open a discussion about it.
Since at this stage there is no point to invest in an installer, nothing special is required but to extract OSA-Mailer from its 7zip archive and to execute the binary on regular cycles (1 minute, 10 minutes, etc.).
The following chapters will provide step-by-step instructions on how to configure and deploy OSA-Mailer.
Download the most current 7zip archive (.7z) asset of OSA-Mailer from the releases page (e.g. osamailer-alpha-3_windows-pc-i686.7z
) and follow the instructions in the following chapters.
Roadmap
- Windows Service (Installer)
- *nix Service (Package)
Windows Setup
Preface
At this stage of the development, there is no installer.
Currently the way to use OSA-Mailer is it have an external system to run its run script osa_mailer.cmd
Preparations
Download
Steps:
- Get to the releases page
- Pick the latest version of OSA-Mailer
- Expand the
Assets
title by clicking on it- Pick the
.7z
7-zip archive file for Windows and click on it to start downloading
Extract
In order to extract a 7-zip archive, you need an extractor that supports it. Your best bet is probably to download the official 7-zip from its website https://www.7-zip.org/
Steps:
- Extract the archived file from the
Download
section anywhere you like, but make sure you will have controlled access to the extractedoutbox
directory as this directory serves clients as a gateway for sending E-mails
Configure
osa_mailer.cmd
::: Configurations SET SERVER=localhost SET PORT=25 SET AUTH=noauth ::SET USERNAME=username ::SET PASSWORD=password
Steps:
- Edit the script file
osa_mailer.cmd
with your favorite text editor- Look for the
:: Configurations
comment- Notice the
SET
statements which set each environment variable for OSA-Mailer- Configure each environment variable accordingly
Environment Variable Description Mandatory SERVER
SMTP server IP address or hostname (e.g. Gmail, Outlook, SMTP relay-proxy, etc.) ✅ PORT
The TCP port number for the SERVER
variable✅ AUTH
Authentication method: TLS
,STARTTLS
orNOAUTH
✅ USERNAME
Provides the username when using an authentication method other than NOAUTH
❌ PASSWORD
Provides the password when using an authentication method other than NOAUTH
❌
- To uncomment a variable, remove the double-colons
::
from itsSET
statement (e.g.::SET USERNAME=username
becomesSET USERNAME=username
)
Setup a Task for Windows Task Scheduler
Windows Task Scheduler can be used as a means to trigger and activate OSA-Mailer, but it is not a requirement in case it doesn't fit your use-case.
Open the Windows Task Scheduler
Here are a few links to external articles on different methods to launch the Windows Task Schedular:
Here is one way to do this:
In order to open the Windows Task Schedular, we will use aRun
command:
- Hold the
Windows
button + press theR
button- This should open the
Run
window- Type in:
taskschd.msc
and either click theOK
button or press theENTER
key
Create a new Task
It is recommended to create the task within a dedicated folder so it will be easier to maintain and not mix-up with other unrelated tasks.
Steps:
- On the left pane, select the
Task Scheduler Library
directory by clicking on it once with theLEFT MOUSE BUTTON
- Once selected,
RIGHT MOUSE BUTTON
click on the already selectedTask Scheduler Library
, to open the actions menu- Select
New Folder...
from the actions menu
- Pick a proper name (
OSA-Mailer
is recommended) and either click on theOK
button or press theENTER
key
- Select the newly created folder by a single
LEFT MOUSE BUTTON
click
- Once selected,
RIGHT MOUSE BUTTON
click on it again to pop the actions menu- Select the
Create Task...
from the actions menu
- The
Create Task
window will pop-up- Provide the name for the task:
Check Outbox
(recommended)- Under
Security options
, select theRun whether user is logged on or not
and check theDo not store password. The task will only have access to local computer resources.
checkbox- Click on the
Triggers
tab
- On the
Triggers
tab, click on theNew...
button to create a new trigger
- The
New Trigger
window will pop-up- Make sure that
Begin the task:
is set toOn a schedule
- Make sure that
Settings
is set onOne time
- Under
Advanced settings
, make sure that theRepeat task every:
checkbox is checked- (Recommended): Manually copy the value
1 minute
and assign it- Make sure that
for a duration of:
is set toIndefinitely
- Make sure that the
Enabled
checkbox is checked- Click on the
OK
button to the add the trigger
- Click on the
Actions
tab
- On the
Actions
tab, click on theNew...
button to create a new action
- The
New Action
window will pop-up- Under the
Program/script:
textbox, assign the path to where theosa_mailer.cmd
file is located
- Optional: You can click on the
Browse...
button to locate theosa_mailer.cmd
file
- Click on the
OK
button to add the action
- Click on the
Conditions
tab
- Make sure that there are no conditions in place and all checkboxes are unchecked
- Click on the
Settings
tab
- Make sure that only the following checkboxes are checked:
Allow task to be run on demand
Run task as soon as possible after a scheduled start is missed
If the running task does not end when requested, force it to stop
- Make sure that the field
If the task is already running, then the following rule applies:
has the valueDo not start a new instance
in its dropbox- Make sure the rest of the checkboxes are unchecked
- Click on the
OK
button to create the task
- We are finished. You can close the Windows Task Scheduler
Sending an E-mail
On every run, OSA-Mailer is scanning its outbox
directory for new E-mail entries.
Each E-mail entry is represented as a JSON document file.
An E-mail entry can be though of as just a single "send E-mail" request that contains all details required to send it.
When attempting to send multiple E-mails to the same recipients, on the same subject, having a common denominator, they are all considered to be E-mail entries that compose the same, single E-mail ("Composed E-mail"), that represents the final product to be sent to your recipients.
You can have a relation of multiple E-mail entries per one composed E-mail or one E-mail entry per one composed E-mail. It depends on your personal configurations.
Once the E-mail entry is processed and sent successfully, it is deleted from the outbox
directory.
🚨 If the
.json
entry file is not deleted from theoutbox
directory, then an error might have occurred. You can check thelogs
directory to get more details about the errors.
Outbox Directory
In order to send an E-mail, we have to produce an E-mail entry which is a JSON document that contains all details required to send it, and place it in the outbox
directory.
Using the outbox
directory, enables us advanced features such as accumulating multiple E-mails into a single one that is containing accumulate context within its contents. This reduces spam in our recipients' inbox and provides them with more concise E-mails.
Other future features are in-bound such as delayed E-mails, etc. All of these features and more, are only possible to achieve when using an outbox
directory to accumulate E-mails.
Notice: In the future, we may use a database or provide an option for a database. For our MVP, we just put JSON files in the
outbox
directory
Example
📦osa_mailer
┣ 📂outbox 👈
┃ ┣ 🗎my_non_standard_email_entry.json
┃ ┣ 🗎a40a6508.3b0c7586049dd2.c8e7d381.3e5f6e98.json
┃ ┗ 🗎a40a6508.3b119a8fafdc3a.72e3d49e.fc982089.json
...
E-mail Entry Name Convention
The following describes the current, non-binding standard for E-mail entry file name convention:
{
E-mail ID
}.{Timestamp
}.{Entry ID
}.{Checksum
}.json
Field | Description |
---|---|
E-mail ID | A unique ID to identify the E-mail, produced by hashing the email part of the entry, encoded in hexadecimal |
Timestamp | Creation time in nanoseconds, encoded in hexadecimal |
Entry ID | A unique ID to identify the entry, extracted from the entry itself |
Checksum | A unique CRC32 checksum of the entire entry file, encoded in hexadecimal |
🚨 The file name convention isn't mandatory but it helps in debugging and avoiding coalitions when auto-generating E-mail entries. The standard is embedded in the
new_entry.py
script file which is located under themail_producer
directory
The following chapters will demonstrate how to compose an E-mail entry JSON document.
Common E-mail Entry
The following example represents an E-mail entry.
Currently, it is mandatory to be explicit about all possible fields. However it is not required to fill every possible field.
In the following examples, we will explain the roles of every key and JSON object.
Entry Object Structure
Here is the base structure of every E-mail entry:
Example
{
"id": "<ENTRY ID>",
"utc": "<SEND TIMESTAMP IN UTC ISO 8601 RFC3339 FORMAT>",
"notify_error": [ "<OPTIONAL E-MAIL ADDRESS FOR ERROR NOTIFICATIONS>" ],
"email": {
"<KEY-VALUE>": "<KEY-VALUE INPUTS, DESCRIBING HOW TO SEND THE E-MAIL>"
},
"context": {
"<KEY-VALUE>": "<KEY-VALUE INPUTS, DESCRIBING THE DATA FOR THE HTML TEMPLATE>"
}
}
The structure above is common among all E-mail entries. What varies are the assigned values.
Data Name | Data Type | Description |
---|---|---|
id | string | A unique ID provided by the entry generator. There is no mandatory standard. The only requirement is that each entry must have a unique value |
utc | string | A UTC timestamp value in the ISO 8601 RFC3339 standard |
notify_error | array of string s | A list of E-mail addresses to be notified about errors (not implemented yet) |
email | object | A dictionary or map of values that describes the E-mail to be sent. e.g. subject, recipients, attachments, HTML template, etc. |
context | object | Context variables for the HTML template |
E-mail Object Structure
The email
object within the entry object, is composed of the following structure:
Example
{
"email": {
"system": "My Automations System",
"subsystem": "[ID:12345] Trigger: Server Disk Out-of-Storage",
"from": "Ops Auto-Mailing System <tech-support@example.com>",
"reply_to": [
"System Admin <admin@example.com>",
"Project Lead <lead@example.com>"
],
"to": [ "Rick S. <rick_s@example.com>" ],
"cc": [],
"bcc": [],
"subject": "ATTENTION! Your server is out-of-storage",
"template": "ops_department",
"alternative_content": "Unable to render HTML. Please refer to the Ops department for details.",
"attachments": [],
"unique_by": ""
}
}
Data Name | Data Type | Description |
---|---|---|
system | string | The name of the external system that uses OSA-Mailer |
subsystem | string | The name of the subsystem that uses OSA-Mailer. e.g. Name of the trigger or rule that fired or activated OSA-Mailer, within the external system |
from | string | The E-mail address of the sender |
reply_to | array of string s | An optional array of E-mail addresses to re-direct replies to |
to | array of string s | An array of E-mail addresses representing the To: recipients |
cc | array of string s | An array of E-mail addresses representing the Cc: copy to recipients |
bcc | array of string s | An array of E-mail addresses representing the Bcc: hidden recipients |
subject | string | The E-mail subject |
template | string | The selected template for the message body, located under the templates directory |
alternative_content | string | The message to be displayed for clients that cannot render the HTML body of the message. Some E-mail clients use this value for message preview |
attachments | array of string s | An array of file paths to attach |
unique_by | string | An optional aid field to assist in generating a unique E-mail ID by providing custom values. This provides us the ability to affect how E-mails are accumulated |
The entire
Context Object Structure
The context
object within the entry object, can be freely composed of any JSON value. Every key within the context
object, is passed down to the selected template
Example
The following JSON context, can be accessed within its following HTML template example:
{
"context": {
"message": "Hello, world!",
"items": [ "apple", "orange", "watermelon" ]
}
}
HTML template using the handlebars
engine for rendering:
<!--TEMPLATE handlebars-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email Template</title>
</head>
<body>
<div>
<h1>{{ message }}</h1>
<p>Here's the list of items:</p>
<ul>
{{#each items}}
<li>{{ this }}</li>
{{/each}}
</ul>
</div>
</body>
</html>
There are 3 supported template engines at the moment:
Handlebars
,Liquid
andTera
. You can tell OSA-Mailer how to render the template with a special magic comment at the beginning of the HTML file<--TEMPLATE [ENGINE NAME]-->
(case insensitive)
🚨 At the moment, there are still standards to be formulated. It is within my hopes that once the project attracts attention, a community consensus will be established. So far, I try to avoid creating limits and only formulate what seems to me absolutely necessary. Striving for a standard is somewhat necessary so different clients and different potential backends, could still interface with each other with minimal to no modifications or adaptions
Basic E-mail
Here is a full example:
{
"id": "fed5cadb",
"utc": "2022-09-01T22:44:11.852662+00:00",
"notify_error": [
"Developers <dev-team@example.com>"
],
"email": {
"system": "My Automations System",
"subsystem": "[ID:12345] Trigger: Server Disk Out-of-Storage",
"from": "Ops Auto-Mailing System <tech-support@example.com>",
"reply_to": [
"System Admin <admin@example.com>",
"Project Lead <lead@example.com>"
],
"to": [ "Rick S. <rick_s@example.com>" ],
"cc": [],
"bcc": [],
"subject": "ATTENTION! Your server is out-of-storage",
"template": "ops_department",
"alternative_content": "Unable to render HTML. Please refer to the Ops department for details.",
"attachments": [],
"unique_by": ""
},
"context": {
"message": {
"heading": "Detected Problems in Your Server",
"body": "We have detected a disk capacity problem with one or more of your servers. Please refer to the instructions below"
}
}
}
Templates
The templates
directory is meant to contain all templates in separated directories, with their (optional) resources and assets included, where each directory name represents the template's name.
The template index file is called template.html
. In the example above, we use the ops_department
template.
Under the templates
directory, create a directory called ops_department
and then create a text file and name it template.html
Copy the following HTML content into template.html
and save the file.
Example
📦osa_mailer
┣ 📂templates
┃ ┗ 📂ops_department
┃ ┗ 🗎template.html 👈
...
<!--TEMPLATE handlebars-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email Template</title>
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#f4f4f4">
<tr>
<td align="center" valign="top">
<table width="600" border="0" cellspacing="0" cellpadding="20" bgcolor="#ffffff">
<tr>
<td align="center" valign="top">
<h1>{{message.heading}}</h1>
</td>
</tr>
<tr>
<td align="center" valign="top">
<p>{{message.body}}</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Open Source Community Vision
Some tools are developed in workplaces for niche use-cases that repeat between different companies, workplaces and clients, where skilled workers find themselves create, write and design the same tools over and over again, having no common standard.
My vision is to create some of these tools to be publicly available for free, encourage and build an open-source community around them in order to:
- Provide a common language and standard for common niche projects
- Provide quick-to-deploy, high-quality, capable and reliable solutions to impress our bosses or clients
- Gain common, shared, technical experience around them to configure and maintain them, providing better support
- Provide higher quality of manpower for companies by providing potential workers with relevant experience for common community tools with excellent resources
- Create job opportunities for the community as they easily solve their bosses or clients problems with easy to maintain, standard community solutions
— David Krasnitsky