Skip to Content
Technical Articles
Author's profile photo Joachim Van Praet

Send an email from a nodejs application

Hi All,

For a small business application we want to send e-mails from our nodejs application. In this blog post I will show you how you can use sap-cf-mailer based on nodemailer to send emails through an SMTP server defined in your destinations.

https://nodemailer.com

Test SMTP server

Instead of testing the code with your own email account and loading your mailbox full with test emails, you can use mailtrap as test SMTP server. It’s free for one inbox.

https://mailtrap.io/

Create an account on mailtrap and create a new inbox. Open the inbox and take a look at the settings. All mails send over this SMTP server will be delivered here without sending them to the real receiver.

 

MAIL destination

We need to create a mail destination that links to our SMTP server.

In this destination we configured following properties:

  • Name: a name for the destination
  • Type: MAIL
  • username and password from your mailtrap SMTP server
  • mail.smtp: smtp server address
  • mail.port: smtp server port
  • mail.from: if there is no mail from specified in the code, we will use this email address to send the mails.

NodeJS application

To send mails, we first have to read this destination properties and then send them to the nodemailer library. To make things a lot easier, I created a new library that will read the destination service and add it to the nodemailer for you.

Your application needs a reference to a destination service to be able to read the mailtrap-destination. this is how my mta.yaml file looks like

ID: sap-cf-mailer-example
_schema-version: "2.1"
description: Example sap cf mailer
version: 0.0.1
modules:
  - name: approuter
    type: approuter.nodejs
    path: approuter
    parameters:
      disk-quota: 256M
      memory: 256M
    requires:
      - name: uaa
      - name: destination_service
      - name: mail_api
        group: destinations
        properties:
          forwardAuthToken: true
          name: mail_api
          strictSSL: false
          url: '~{url}'
  - name: srv
    type: nodejs
    path: srv
    parameters:
      memory: 512M
      disk-quota: 256M
    provides:
      - name: mail_api
        properties:
          url: ${default-url}
    requires:
      - name: uaa
      - name: destination_service
resources:
  - name: destination_service
    type: org.cloudfoundry.existing-service
  - name: uaa
    type: org.cloudfoundry.existing-service

 

In the srv folder, just install the sap-cf-mailer library with:

$ npm install -s sap-cf-mailer

 

in your nodeJS application you can use it to send text or HTML emails.

const express = require('express');
const app = express();
const SapCfMailer = require('sap-cf-mailer').default;

const transporter = new SapCfMailer("MAILTRAP");

app.use(express.json());

app.get('/sendmail', async (req, res) => {
    // use sendmail as you should use it in nodemailer
    const result = await transporter.sendMail({
        to: 'someoneimportant@sap.com',
        subject: `This is the mail subject`,
        text: `body of the email`
    });

    res.send(result);
});

const port = process.env.PORT || 3000;;
app.listen(port, function () {
    console.log('myapp listening on port ' + port);
});

 

The result

After running the application you can check in the mailtrap inbox which email is sent to who!

 

So, now you can send emails in your nodejs cloud foundry application using the sap-cf-mailer module. For more advanced features like sending html emails and attachments your can consult the nodemailer documentation.

 

kr,

Joachim

Assigned Tags

      10 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Egor Tokarev
      Egor Tokarev

      Hi Joachim, thanks a lot for your post! As I'm quite new to cloud foundry deployment it took me quite some time to understand mta.yml configuration magic (especially "resources") but after all I was able to repeat your steps and got email from nodejs. please keep on posting!

      Best regards,

      Egor

      Author's profile photo sara moreno da silva
      sara moreno da silva

      Hi Joachim Van Praet

      I'm trying to use nodemailer to send an email but it doesn't find the host. This host. The difference with your tutorial is that destination endpoint is SAP Cloud Connector and it's an on premiser server mail.

      I'm trying to send the email with these options but it seems it doesn't work:

              host: destination.destinationConfiguration["mail.smtp.host"],
              port: destination.destinationConfiguration["mail.smtp.port"],
              secure: false, // true for 465, false for other ports
              auth: {
                  user: destination.destinationConfiguration["mail.user"],
                  pass: destination.destinationConfiguration["mail.password"],
              },
              proxy: "http://" + connectivity.onpremise_proxy_host + ":" + connectivity.onpremise_proxy_http_port
      This is the error:
      code: 'EDNS'
      command: 'CONN'
      errno: 'ENOTFOUND'
      hostname: 'sendmail.henkelgroup.net'
      message: 'getaddrinfo ENOTFOUND sendmail.xxxxxxx.net'
      stack: 'Error: getaddrinfo ENOTFOUND sendmail.xxxxxxx.net\n at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:56:26)
      In this case shall wa use Java app? I'm afraid of it won't work too...
      Any suggestion will be appreciated 🙂 Thank you very much.
      Best regards,
      Author's profile photo Joachim Van Praet
      Joachim Van Praet
      Blog Post Author

      Hi sara moreno da silva ,

      Unfortunately the connection is not working for onpremise destinations yet.
      I will keep this in mind, when I have time I will add it.
      Feel free to add this feature yourself and send me a pull request.

      kr,

      Joachim

      Author's profile photo Janith Illangakoon
      Janith Illangakoon

      Hi Joachim Van Praet

      I'm trying to integrate the Gmail SMTP server instead of the Mailtrap.

      I've tried several destination parameter combinations but was unable to make it work. it says.

      Error: Unexpected socket close

       

      This is my destination configuration

       

      Author's profile photo Gregor Wolf
      Gregor Wolf

      Hi Joachim,

      thank you for this great description and the NPM Packages that make the consumption a breeze. I've added an example to my SAP Cloud Application Programming Model (CAP) demo application with this commit:

      https://github.com/gregorwolf/bookshop-demo/commit/adf6836ce91d327267538080e5c4d69738597af4

      The only pitfall that I run into was that the suggested properties in the MAIL destination doesn't fit to your names:

       

       

      Did SAP change something here and we need an update for your NPM package?

      Author's profile photo Joachim Van Praet
      Joachim Van Praet
      Blog Post Author

      Thanks Gregor,

      I think SAP changed this.
      I've adapted the properties in version 0.0.4.

      old property names still work.

      kr

      Joachim

       

      Author's profile photo Gregor Wolf
      Gregor Wolf

      Hi Joachim,

      thank you for the update. But it seems that your update isn't yet published to https://www.npmjs.com/package/sap-cf-mailer. I would suggest you add a GitHub Action to get it automatically published. Check out the example in: .github/workflows/npm-publish.yml.

      CU
      Gregor

      Author's profile photo RahulDeep Attri
      RahulDeep Attri

      Thanks a lot for your post!

      Author's profile photo Andreas Morf
      Andreas Morf
      Hi Joachim,
      thanks for the detailed blog. In our project, the email sending using SapCfMailer does not work yet using your explanations.
      We get back the following response from the console.log(transporter):
      SapCfMailer {
          destinationPromise: Promise { <pending> },
          transportConfig: undefined
      }
      const app = express();
      app.use(express.json());
      var transporter = new SapCfMailer("mailtrap");    
      console.log(transporter);
          
      app.get('/sendmail', async (req, res) => {
          // use sendmail as you should use it in nodemailer
          const result = await transporter.sendMail({
                  to: 'myEmailHere',
                  subject: `This is the mail subject`,
                  text: `Body of the email`
          });
          res.send(result);
      });

      We configured as well the mailtrap destination in our CF environment using the following parameters:

      Destination_Configuration

      If the picture is not readable, the params are like this:

      Name: mailtrap
      Type: MAIL
      Description: <does not matter>
      Proxy Type: Internet
      User: <as in the mailtrap login>
      Password: <as in the mailtrap login>
      Additional property - mail.smtp.from: <my email address>
      Additional property - mail.smtp.host: smtp.mailtrap.io
      Additional property - mail.smtp.port: 587

       

      Our sap/cds version and node.js version:
      | Node.js | v14.16.0 |
      | @sap/cds | 5.3.2 |
      | @sap/cds-compiler | 2.4.4 |
      | @sap/cds-dk | 4.1.5 |
      Using the destination curl in SAP Business Application Studio Terminal: "curl mailtrap.dest" we get the response "dial tcp: lookup mailtrap.dest on 100.64.0.10:53: no such host" which of course might or is the reason for the not working sending, however we cannot find any answer on the Web or SAP-internal to that.
      Can you help us one step further?
      Thank you. Cheers, Andreas

       

      Author's profile photo Tim Anlauf
      Tim Anlauf

      Joachim Van Praet is the package already able to connect to onPremise SMTP server ?

      If not, is there any other way to use our own SMTP server in cloud foundry environment?