A Loopback Microservice primarily used for in-mail implementation to compose and view in-mails for any client application.
npm i @sourceloop/in-mail-service
The project ships with generated migrations for PostgreSQL in the migrations folder. For generating migrations and implementing other data sources, please refer to refer to Database Migrations | LoopBack Documentation for more information.
Create a new Application using Loopback CLI and add the Component for InMailService
in application.ts
import {BootMixin} from '@loopback/boot';
import {ApplicationConfig} from '@loopback/core';
import {RepositoryMixin} from '@loopback/repository';
import {RestApplication} from '@loopback/rest';
import {
RestExplorerBindings,
RestExplorerComponent,
} from '@loopback/rest-explorer';
import {ServiceMixin} from '@loopback/service-proxy';
import { InMailServiceComponent } from '@sourceloop/in-mail-service';
import * as dotenv from 'dotenv';
import * as dotenvExt from 'dotenv-extended';
import path from 'path';
export {ApplicationConfig};
const port = 3000;
export class Client extends BootMixin(
ServiceMixin(RepositoryMixin(RestApplication)),
) {
constructor(options: ApplicationConfig = {}) {
dotenv.config();
dotenvExt.load({
schema: '.env.example',
errorOnMissing: true,
includeProcessEnv: true,
});
options.rest = options.rest || {};
options.rest.port = +(process.env.PORT || port);
options.rest.host = process.env.HOST;
super(options);
// Set up default home page
this.static('/', path.join(__dirname, '../public'));
// Customize @loopback/rest-explorer configuration here
this.configure(RestExplorerBindings.COMPONENT).to({
path: '/explorer',
});
this.component(RestExplorerComponent);
// add Component for InMailService
this.component(InMailServiceComponent);
this.projectRoot = __dirname;
// Customize @loopback/boot Booter Conventions here
this.bootOptions = {
controllers: {
// Customize ControllerBooter Conventions here
dirs: ['controllers'],
extensions: ['.controller.js'],
nested: true,
},
};
}
}
Do not forget to set Environment variables. The examples below show a common configuration for a PostgreSQL Database running locally.
NODE_ENV=dev
LOG_LEVEL=DEBUG
HOST=0.0.0.0
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_USER=pg_service_user
DB_PASSWORD=pg_service_user_password
DB_DATABASE=in_mail_db
DB_SCHEMA=public
JWT_SECRET=super_secret_string
JWT_ISSUER=https://authentication.service
Name | Required | Default Value | Description |
---|---|---|---|
NODE_ENV |
Y | Node environment value, i.e. dev , test , prod |
|
LOG_LEVEL |
Y | Log level value, i.e. error , warn , info , verbose , debug |
|
HOST |
Y | Host for the service to run under, i.e. 0.0.0.0 |
|
PORT |
Y | 3000 |
Port for the service to listen on. |
DB_HOST |
Y | Hostname for the database server. | |
DB_PORT |
Y | Port for the database server. | |
DB_USER |
Y | User for the database. | |
DB_PASSWORD |
Y | Password for the database user. | |
DB_DATABASE |
Y | Database to connect to on the database server. | |
DB_SCHEMA |
Y | public |
Database schema used for the data source. In PostgreSQL, this will be public unless a schema is made explicitly for the service. |
JWT_SECRET |
Y | Symmetric signing key of the JWT token. | |
JWT_ISSUER |
Y | Issuer of the JWT token. |
Here is a Sample Implementation DataSource
implementation using environment variables.
import {inject, lifeCycleObserver, LifeCycleObserver} from '@loopback/core';
import {juggler} from '@loopback/repository';
const config = {
name: 'inmailDb',
connector: 'postgresql',
url: '',
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
schema: process.env.DB_SCHEMA,
};
@lifeCycleObserver('datasource')
export class InMailDbDataSource extends juggler.DataSource
implements LifeCycleObserver {
static dataSourceName = 'inmail';
static readonly defaultConfig = config;
constructor(
// You need to set datasource configuration name as 'datasources.config.inmail' otherwise you might get Errors
@inject('datasources.config.inmail', {optional: true})
dsConfig: object = config,
) {
super(dsConfig);
}
}
Authorization: Bearer where is a JWT token signed using JWT issuer and secret.
Content-Type: application/json
in the response and in request if the API method is NOT GET
{version}: Defines the API Version
200: Successful Response. Response body varies w.r.t API
401: Unauthorized: The JWT token is missing or invalid
403: Forbidden : Not allowed to execute the concerned API
404: Entity Not Found
400: Bad Request (Error message varies w.r.t API)
201: No content: Empty Response
Description: Compose or draft a Mail to various Recipients
Request Body:
{
"threadId": "string", // Optional, add if you want the messages in a same thread
"groups": [ // You can define one or more receipients in a group array.
{
"party": "string", // email of the recipient
"type": "to", // type can be to | cc | bcc
}
],
"attachments": [ // Optional
{
"name": "string", // name of the attachment file
"path": "string", // It can be url like s3 url
"thumbnail": "string", // Smaller/Compressed version of attachment path. can be s3 url
"mime": "string", // Content Type of a file (example: image/jpg)
}
],
"meta": [ // Optional
{
"key": "string", // Key Name like Content-Type
"value": "string", // Value like application/json, text/html etc.
}
],
"body": "string", // The Message Body
"subject": "string", // The title of the Message
"status": "string", // Draft if you don't want to send message Now
"extId": "string", // External Id from the Client (Optional)
"extMetadata": {} // External Metadata from the Client (Optional)
}
Successful Response:
{
"id": "string", // id of the message
"version": "string" // API vewrsion
}
Description: Update Drafted Messages such as modifying attachment, receipients, message body, subject etc.
Request path Parameters:
{messageId}: Unique Id of the message which needs to be updated
Request Body:
{
"groups": [ // You can define one or more receipients in a group array.
{
"party": "string", // email of the recipient
"type": "to", // type can be to | cc | bcc
}
],
"attachments": [ // Optional
{
"name": "string", // name of the attachment file
"path": "string", // It can be url like s3 url
"thumbnail": "string", // Smaller/Compressed version of attachment path. can be s3 url
"mime": "string", // Content Type of a file (example: image/jpg)
}
],
"meta": [ // Optional
{
"key": "string", // Key Name like Content-Type
"value": "string", // Value like application/json, text/html etc.
}
],
"body": "string", // The Message Body (Optional)
"subject": "string", // The title of the Message (Optional)
"status": "string", // Draft if you don't want to send message Now, otherwise, send
"extId": "string", // External Id from the Client (Optional)
"extMetadata": "object" // External Metadata from the Client (Optional)
}
Success Response:
{
"id": "string", // id of the message
"version": "string" // API vewrsion
}
Description: add an attachment to an existing drafted mail
Request path Parameters:
{messageId}: The unique id of a mail
Request Body:
{
"attachments": [
{
"name": "string", // name of the attachment file
"path": "string", // It can be url like s3 url
"thumbnail": "string", // Smaller/Compressed version of attachment path. can be s3 url
"mime": "string" // Content Type of a file (example: image/jpg)
}
]
}
Successful Response:
{
"items": "array", // array containing attachments,
"version": "string", // an API version
}
Description: Move inbox/sent items to trash or delete the trashed item
Request path parameters:
{storage}: inbox/send/trash (to trash the inbox/sent message or to delete the trashed message)
{action}: trash/delete
Request body parameters
{
"messageIds": "Array<string>"
}
Successful Response:
{
"version" : "string", // the API version
"item": "Array<object>" // recipient/sender details which was marked for deletion/trash
}
Description: Restore the trashed Mail
Request body parameters
{
"messageIds": "Array<string>"
}
Successful Response:
{
"version": "string", // the API version
"items": "Array<object>" // receipient/sender details which was restored from trash
}
Description: Forward the mail to another receipient
Request path Parameter:
{messageId}: Unique message Id
Request Body:
{
"groups": [ // you can specify more recipients in groups array for forwarding the mail to multiple recipients
{
"party": "string", // email of the recipient
"type": "to" | "bcc" | "cc", // receipient type
}
]
}
Successful Response:
{
"version": "string", // the API version
"id": "string" // the message Id
}
Description: Send the drafted mail to the receipent
Request path Parameter:
{messageId}: Unique Message Id
Successful response
{
"id": "string",
"version": "string"
}
Description: mark the mails as read/unread/important/not-important
Request path Parameter:
{markType}: read/unread/important/not-important
Successful response
{
success : true,
}
Request path Parameters:
{threadId}: Unique id of thread
Request query Parameter(Optional):
filter: Object which contains attribute(s) key value pairs of thread model which is used to filter data.
Successful Response:
{
"version": "string", // the API version
"item": "object" // item containg the thread and the related message, attachment and/or meta-data details
}
Request query parameter(s):
groupFilter: Object which contains attribute(s) key value pairs of group model which is used to filter items. threadFilter: Object which contains attribute(s) key value pairs of thread model which is used to filter items.
Successful Response:
{
"version": "string", // the API version
"items": "array" // array containing thread details and the corresponding messages, attachments etc.
}
Request query parameter(s):
groupFilter: Object which contains attribute(s) key value pairs of group model which is used to filter items. threadFilter: Object which contains attribute(s) key value pairs of thread model which is used to filter items.