June 10, 2021 By Henrik Loeser 4 min read

Easily send emails using SendGrid, MailJet or your own SMTP server.

You have created your app on IBM Cloud. Now, you want to extend its functionality to send out emails. You could integrate all the email functionality into your app or just call out to another microservice. I opted for the latter for my apps. 

I created a small, reusable, serverless action using IBM Cloud Functions. That action takes care of interacting with the email server. All my app needs to do is invoke the action with the email payload. I tested it with my custom domain and my own SMTP server as well as with email delivery services like SendGrid and MailJet.

The serverless action and instructions are available in the IBM-Cloud/cloudmailer GitHub repository. In the following, I discuss how it works, how to configure it and what you need to know to have your app send an email like the one below:

Sample email with HTML content, including link.

Serverless action to send emails

In the introduction, I mentioned that I created a small, reusable, serverless action to send out emails: sendEmail. Serverless computing provisions compute resources on demand. You only pay for the consumed resources when your code is active. Thus, it is ideal for a microservice to send emails. IBM Cloud offers both IBM Cloud Code Engine and IBM Cloud Functions for serverless computing. For this microservice, I opted for a Cloud Functions action because of the small project size and the Nodemailer module already included in the standard Node.js runtime.

With a module to handle the SMTP-related functionality conveniently available, all the action has to perform is to retrieve the configuration and email properties from the available parameters, establish a connection to the SMTP server and pass on the email object. Let’s take a look into what data is needed:

Code section from sendEmail action.

Configure the email delivery service

The properties to establish a connection to an SMTP server are the same, regardless of whether you are using an email delivery service like SendGrid, MailJet, etc. or interacting with your email provider/your own email server. It is the host and the port along with a username/password combination, all packed into a JSON object “server”:

    "server": {
        "host": "smtp.example.com",
        "port" : 465,
        "id": "security@example.com",
        "password": "strong-password"

Because of SPAM and other abuse, often the typical SMTP port 25 is either not available or blocked by the compute environment. Thus, expect to find port numbers like 465 or 587. Instead of the username and password, an API key could be used. In the case of SendGrid and some others, then the username would be “apikey” and the password value the actual API key. Other vendors use an API key as username and a special secret key as password.

With that server configuration available, I first deploy the sendEmail action and then bind the SMTP configuration as default parameters to the action. There are different ways to accomplish this and the GitHub repository includes steps for the IBM Cloud command line interface (CLI). But, you could also just copy and paste the source code for the action and use the IBM Cloud Functions web UI.

Provide the email as payload

Once you deploy the action and have the SMTP server configuration ready, it’s time to send an email. The “email” is another JSON object with a structure like this:

            "sender": "Henrik Loeser <henrik@example.com>",
            "receiver": "data-henrik@example.com",
            "subject": "Sample email for blog post",
            "text": "see the HTML text",
            "html": "<html><h1>Hello world!</h1>Check out the <a href=\"https://github.com/IBM-Cloud/cloudmailer\">code on GitHub</a>.<h3>Let's talk emails</h3>To receive emails, someone has to send them.</html>"

The shown values result in an email like the one shown in the first screenshot above. It consists of the sender, receiver, the email subject and one of (or both) the text or HTML version of the email body. Note that for some email services, you can only use verified email addresses as sender. The value for receiver can be a comma-separated list of email addresses. As you can see, the value  for “html” can include formatting, hyperlinks and more.

The email object needs to be passed into the action when invoking it (i.e., when calling this email microservice).

Ready, set, send email

To send emails, you have to invoke the Cloud Functions actions. There are multiple ways of how to do this and I describe them in README in the GitHub repository. The easiest way for testing probably is to use the CLI or Cloud Functions web UI. If you configured the SMTP server as default parameters, the following command would send out an email with its properties read from the file email.json:

ibmcloud fn action invoke cloudmailer/sendEmail -r  -P email.json 

To utilize the action from your app as microservice, you can either invoke the action via the Cloud Functions REST API or turn it into a web action. For the latter, you would need to set an additional flag and decide how to secure it.


In this blog post, I have shown that it is simple to set up a microservice to send out emails via SMTP. I have implemented it as serverless action with IBM Cloud Functions and in Node.js. The service can be used on its own or utilized by apps to send out status emails or alerts. In the blog post “How to Get IBM Cloud Security Advisor Alerts via Slack or Email” from last year, I discussed how to set up email alerts for security issues. A recent follow-up post shows how to use SMTP servers similar to what I discussed today.

Note that the Nodemailer module offers more message options, including attachments to send images or PDF documents and, of course, setting email addresses on CC and BCC. This could be added to the code. Open a GitHub issue if you need help. If you have other feedback, suggestions, or questions about this post, please reach out to me on Twitter (@data_henrik) or LinkedIn

Was this article helpful?

More from Cloud

Enhance your data security posture with a no-code approach to application-level encryption

4 min read - Data is the lifeblood of every organization. As your organization’s data footprint expands across the clouds and between your own business lines to drive value, it is essential to secure data at all stages of the cloud adoption and throughout the data lifecycle. While there are different mechanisms available to encrypt data throughout its lifecycle (in transit, at rest and in use), application-level encryption (ALE) provides an additional layer of protection by encrypting data at its source. ALE can enhance…

Attention new clients: exciting financial incentives for VMware Cloud Foundation on IBM Cloud

4 min read - New client specials: Get up to 50% off when you commit to a 1- or 3-year term contract on new VCF-as-a-Service offerings, plus an additional value of up to USD 200K in credits through 30 June 2025 when you migrate your VMware workloads to IBM Cloud®.1 Low starting prices: On-demand VCF-as-a-Service deployments begin under USD 200 per month.2 The IBM Cloud benefit: See the potential for a 201%3 return on investment (ROI) over 3 years with reduced downtime, cost and…

The history of the central processing unit (CPU)

10 min read - The central processing unit (CPU) is the computer’s brain. It handles the assignment and processing of tasks, in addition to functions that make a computer run. There’s no way to overstate the importance of the CPU to computing. Virtually all computer systems contain, at the least, some type of basic CPU. Regardless of whether they’re used in personal computers (PCs), laptops, tablets, smartphones or even in supercomputers whose output is so strong it must be measured in floating-point operations per…

IBM Newsletters

Get our newsletters and topic updates that deliver the latest thought leadership and insights on emerging trends.
Subscribe now More newsletters