Skip to main content

Send mail via an API

At the end of this tutorial, you will have built an Express App, that exposes an API you can use to send messages with Mailchain. Your app will use the Mailchain SDK that handles signatures, encryption, and sending the message. In most cases, you would add a route to an existing Express App, but for this tutorial, you'll create a new app.

You can find the final code and working example in mailchain/examples-js on GitHub.

Prerequisites

To complete this tutorial, you need to first:

  1. Download and install NodeJS.
  2. Install npx by running npm install -g npx.
  3. Create new Mailchain account for development and testing purposes.

Step 1 - New API server

You'll create a new Express app that exposes an API, the simplest way to do that is with a generator that creates an Express App structure. There are various express generators, for this tutorial you'll use typescript-express-starter.

To begin, open a terminal window on your computer and run:

npx [email protected] mailchain-send-api
note

typescript-express-starter does change from time to time, so using [email protected] guarantees this tutorial completes successfully.

If you get a message similar to below, likely it because it's the first time using npx to run express generator, or this specific version. Press y to continue, you'll only need to do this once.

Need to install the following packages:
[email protected]
Ok to proceed? (y)

typescript-express-starter will ask you for some details:

  1. Accept the default template, by pressing enter.
  2. Press n when asked to update to the latest packages, this guarantees this tutorial completes successfully.
  3. Press y when asked to removed duplicate packages at npm.

typescript-express-starter can take a while to create a new project as it's installing npm packages. Once completed typescript-express-starter will confirm it's status:

? Please select the template you want default
? Do you want to update all packages in the node_modules directory and dependency ? No
? Do you want to Used to removed duplicate packages at npm ? Yes
[ 1 / 3 ] 🔍 copying project...
[ 2 / 3 ] 🚚 fetching node_modules...
[ 3 / 3 ] 🔗 linking node_modules...
─────────────────────────────────────────
✔ Complete setup project

Your Express App is now created. Open mailchain-send-api in your favorite code editor. You'll see it contains example services, controllers, routes, etc. Later you'll extend this functionality.

Check you can start your mailchain-send-api app in development mode by running:

cd mailchain-send-api && npm run dev

The output should look like:

[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/* .env
[nodemon] watching extensions: js,ts,json
[nodemon] starting `ts-node -r tsconfig-paths/register --transpile-only src/server.ts`
info: =================================
info: ======= ENV: development =======
info: 🚀 App listening on the port 3000
info: =================================

This confirms that the app started correctly and can be accessed via http://localhost:3000.

Press ctrl + c together, this will stop the Express App.


Step 2 - Mailchain SDK

Mailchain SDK is the easiest way to use Mailchain, it deals with all of the encryption, signatures, and hashing for you.

Install

To install the Mailchain SDK you need to run an npm command in the base directory of your project mailchain-send-api. If you are following Step 1, you should already be in this folder. Otherwise, open up a terminal window and navigate to your mailchain-send-api folder.

Install Mailchain SDK using npm:

npm install --save @mailchain/sdk
note

npm installed Mailchain SDK and added it as dependency to your project. You can see this change by opening package.json, you'll find an entry for @mailchain/sdk. This tells package the package manager that @mailchain/sdk is a dependency and should be installed with other dependencies.

package.json
// ...
"dependencies": {
"@mailchain/sdk": "^0.9.3",
"bcrypt": "^5.0.1",
"class-transformer": "^0.5.1",
// ...

You have now installed the Mailchain SDK and are ready to configure it.

Secret Recovery Phrase

A Mailchain account is web3 identity, this means that the account is created via a private key that the user owns and controls. In Mailchain's case, the Secret Recovery Phrase creates the private key.

danger

Whoever has the Secret Recovery Phrase controls the account. You should treat Secret Recovery Phrases as if they are private keys. They MUST be kept safely and only saved in a trusted store.

We suggest for development and testing that you use a Secret Recovery Phrase from a test account. Go ahead and create a new account if you don't already have one. Your Secret Recovery Phrase is available to view or download when you register your account. To get your Secret Recovery Phrase afterward go to the settings page and look for the Secret Recovery Phrase section.

Configure

The Mailchain SDK needs to be authenticated with your Secret Recovery Phrase to send messages. We are assuming you are developing on a local machine and it is secure.

Environment variables let you set values that are passed to your server-side code. Your code sets environment variables using env files. The environment files are in the root directory of your app and are named according to the environment, e.g. .env.development.local.

danger

Care must be taken to avoid storing environment variables in source control. For this tutorial, there is a .gitignore file. This tells git to ignore each of the existing environment files. This prevents changes to the existing environment files from being stored in git. Make sure you add new environments to .gitignore.

Use your test development account's Secret Recovery Phrase that you retrieved from the previous step. Open .env.development.local in your editor, and add a new line to the bottom SECRET_RECOVERY_PHRASE=enter your secret phrase here.

Replace enter your secret phrase here with your Secret Recovery Phrase and save the file.

After your .env.development.local should look similar to this:

# PORT
PORT = 3000

SECRET_RECOVERY_PHRASE=enter your secret phrase here

In your terminal window run, npm run dev from the root directory of your mailchain-send-api app. You should get a response similar to below:

info: =================================
info: ======= ENV: development =======
info: 🚀 App listening on the port 3000
info: =================================

This means is successfully started and listening on port 3000.

note

nodemon automatically restarts your API when file changes are detected. However, it doesn't pick up changes to .env.development.local so you need to restart the server manually by pressing ctrl + c and running npm run dev. You'll only need to restart the app when changing the SECRET_RECOVERY_PHRASE setting.


Step 3 - Create a service for sending mail

Express uses services to perform tasks, in this case sending mail using the Mailchain SDK. The service will send messages using the account based on the SECRET_RECOVERY_PHRASE environment variable.

MailService will perform the following actions:

  1. Authenticate the Mailchain SDK using the SECRET_RECOVERY_PHRASE.
  2. Set the from address to the currently authenticated user if it's not supplied.
  3. Send mail using the Mailchain SDK.

Inside src/services/ create mail.service.ts and copy the code below into it.

src/services/mail.service.ts
import { Mailchain, SendMailParams } from '@mailchain/sdk';

class MailService {
async send(params: SendMailParams) {
const secretRecoveryPhrase = process.env.SECRET_RECOVERY_PHRASE;

if (secretRecoveryPhrase == null) {
throw new Error('You must provide a secret recovery phrase');
}
const mailchain = Mailchain.fromSecretRecoveryPhrase(secretRecoveryPhrase);

if (!params.from || params.from === '') {
// set the from address to current user if not provided
const currentUser = await mailchain.user();
params.from = currentUser.address;
}

const { data, error } = await mailchain.sendMail(params);
if (error) {
throw new Error('Mailchain error: ' + error.message);
}

return data;
}
}

export default MailService;

Remember to save mail.service.ts after pasting the code.


Step 4 - Create mail controller

Controllers manage the incoming HTTP requests and send the necessary data to the correct service.

MailController will perform the following actions:

  1. Pass the HTTP request body to the send service.
  2. Set the HTTP response status field using the SDK response.

In your editor create mail.controller.ts in the src/controllers/ folder. Copy and paste the code below into it.

src/controllers/mail.controller.ts
import { NextFunction, Request, Response } from 'express';
import mailService from '@services/mail.service';

class MailController {
public mailService = new mailService();

public postMail = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
try {
const sendResult = await this.mailService.send(req.body);

res.status(200).json({ status: sendResult.status });
} catch (error) {
next(error);
}
};
}

export default MailController;

Remember to save mail.controller.ts after pasting the code.

Step 5 - Wire up API

RESTful API's are designed around paths and methods, in Express these are created in the src/routes folder.

Add mail route

The API is called by clients using HTTP. The HTTP interface is modeled as a RESTful API making it familiar for developers and easy to discover. You'll create an additional route that accepts mail parameters. The route will use the sendMail function you created in Step 3 above.

MailRoute performs the following actions:

  1. Adds the send path.
  2. Listens for a POST.
  3. Route request to the mail controller.

In your editor create mail.route.ts in the src/routes/ folder. Copy and paste the code below into it.

src/routes/mail.route.ts
import { Router } from 'express';
import { Routes } from '@interfaces/routes.interface';
import MailController from '@/controllers/mail.controller';

class MailRoute implements Routes {
public router = Router();
private readonly _mailController: MailController;

constructor() {
this._mailController = new MailController();
this.initializeRoutes();
}

private initializeRoutes() {
this.router.post('/send', this._mailController.postMail);
}
}

export default MailRoute;

Remember to save mail.route.ts after pasting the code.

Add to server

Now MailRoute has been created, the final code change is to add MailRoute to the server.

The server code:

  1. Adds routes.
  2. Listens to incoming requests.

In your editor open the existing server.ts file in the src/ folder. Replace the existing contents by copying and pasting the code below into it.

src/server.ts
import App from '@/app';
import IndexRoute from '@routes/index.route';
import MailRoute from './routes/mail.route';

const app = new App([new IndexRoute(), new MailRoute()]);

app.listen();

Remember to save server.ts after pasting the code.

Now your app is ready to start accepting HTTP requests.


Test your API using CURL

Now you have API that can send messages. You can test this by sending a sample request via HTTP.

note

Your Express App needs to be running to accept requests. If your Express App is not already running, open your terminal and navigate to the base directory of your project e.g. mailchain-send-api then run npm run dev to start your Express app.

You can now test your API by sending a message. Open a new terminal window, and paste the following curl command into a terminal window.

curl http://localhost:3000/send -i -X POST \
--header 'Content-Type: application/json' \
-d '{"to": ["0xbb56FbD7A2caC3e4C17936027102344127b7a112@ethereum.mailchain.com"], "subject": "Sent via curl", "content": {"text": "Hello Mailchain 👋", "html": "<p>Hello Mailchain 👋</p>"}}'

After a few seconds, you should get a response that looks a bit like this:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
...

{"status": "success"}

200 OK means that it worked. 200 is the HTTP response code for success. You can check the message has been sent by looking in the sent folder in the Mailchain web app. Awesome you have sent a Mailchain message via your API.

Want to try more? Edit the curl command above and try to:

  • Send a message to your Mailchain account. Change the to address "<username>@mailchain.com". Check your inbox and you'll see your message. ✅
  • Do you want to send mail to an Ethereum address? Register your Ethereum address in the Mailchain application. Then send a message to <ethereum-address>@ethereum.mailchain.com. ✅
note

I get status 200 OK but I can't see the message in the sent folder. 200 means the API responded correctly, the message should have been sent. Make sure you are logged in with your development/testing account and try refreshing the sent folder.

Conclusion

Congratulations 🎉 you've built an App that exposes an API. You can use this API to send messages from other services and apps, for example notifying your product's users.

What's next?

Authenticate requests before sending. Extend this code by following the authenticated webhook guide