Hello SAP Community.
This blog post will provide a solution for many faced when developing their business application.
How to connect On-premise SAP BTP destination through a NodeJS application to send email using Cloud Application Programming CAP?
Solutions to these problem were successful for scenarios by Joachim Van Praet either creating our own destination in BTP using SMTP providers like Mailtrap, which was not suitable for our use case because it is not on-premise solution.
Other solution provided by Niklas Miroll is tackling the scenario through BTP Cloud Foundry using Java successfuly, but our tech stack was Javascript / NodeJS.
To find a solution, I have checked out the announcement from Marika Marszalkowski and this section of the post about newest updates fascinated me.
Sending Emails
We recently released experimental functionality to send e-mails against SAP BTP destinations of type “MAIL”.
In version 3 we will make it available for productive use.
You can find more details in the mail documentation.
After I read the documentation and understand it, I have created a new project to test this feature. And with a simple configuration, you can now connect your on premise mail servers successfully thanks to the wonderful developers of SAP Cloud SDK Team.
Let’s move step by step to show how to perform it in a simple CAP application from scratch.
1.Requirements – BTP Services Necessary In Setup Account
These are free services on BTP, so it means everyone can test what we perform with a Trial account:
- Authorization and Trust Management Service
- Destination Service
- Connectivity Service
IDE to make our app work is running in SAP Business Application Studio.
We also need to generate service instance keys for each of those services to test our application. Check image below how to create service instance key aft
I have generated those services and service keys with a naming convention as follows. First parameter is service instance name, second parameter is service instance key. I have created those in BTP as you can see Authorization and Trust Management service below, and complete the rest.
mail-xsuaa , mail-xsuaa-key
mail-destination , mail-destination-key
mail-connectivity, mail-connectivity-key
Destination configuration is very important to handle, in this example we are using SMTP server for Gmail and its configuration is as below in our BTP Destination.
With the ‘New Property’ Tab, you can add more properties or delete the extra ones that are not necessary for your configuration.The destination you are calling should be type ‘MAIL’ and must be configured correctly.
Here is an example for you:
Figure 2 : SMTP Destination Configuration in BTP Subaccount – Click to Enlarge
Additional properties we set up in the image that are not clearly visible is as below for this usecase is as below. Please note the configuration may change for different SMTP Server Providers:
mail.smtp.from=<enter e-mail address to send email from here>
mail.smtp.ssl.checkserveridentity=true
mail.smtp.starttls.enable=true
mail.smtp.starttls.required=true
mail.transport.protocol=smtp9
tokenServiceURLType=Dedicated (optional field)
2. Create a New Project
Open Business Application Studio. Click the top left pane red highlighted>File>New Project From Template.
Then choose CAP Project and click Start.
Set your project configuration as below image and click Finish.
3) Fill In Project With Packages and Add Custom Logic
package.json file
We have an empty project with a backbone configuration. An empty db folder, an empty srv folder, a package.json file and mta.yaml file which are important. We will fill those step by step.
- Go to package.json file. Open the terminal from Terminal > New Terminal and download dependencies generated by CAP Wizard with
npm install
- We have installed pregenerated packages, but we need to add 4 more packages to make our BTP services and mail service work. These packages can be installed consecutively through these commands
npm install @sap-cloud-sdk/mail-client
npm install @sap-cloud-sdk/connectivity
npm install @sap/xssec
npm install passport
Mail client package is the newest package from Sap Cloud SDK that provides necessary configuration for on-premise mail handling. Connectivity package is necessary to handle connectivity with on-premise destination. Xssec and passport are necessary to handle authentication.
- To call our destination, we need to add our destination details to the package.json file. This cds requires block should be added after rules block to the package.json, to the end of the package.json file. Here is the full package.json file also for convenience.
"cds": {
"requires": {
"[hybrid]": {
"auth": {
"kind": "xsuaa"
},
"mailService": {
"kind": "rest",
"credentials": {
"destination": "mail_destination",
"forwardAuthToken": true
}
}
}
}
}
{
"name": "mail-on-premise",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@sap-cloud-sdk/connectivity": "^2.14.0",
"@sap-cloud-sdk/mail-client": "^2.14.0",
"@sap/cds": "^6",
"@sap/xssec": "^3.2.17",
"express": "^4",
"passport": "^0.6.0"
},
"devDependencies": {
"sqlite3": "^5.0.4"
},
"scripts": {
"start": "cds run"
},
"engines": {
"node": "^16.15"
},
"eslintConfig": {
"extends": "eslint:recommended",
"env": {
"es2020": true,
"node": true,
"jest": true,
"mocha": true
},
"globals": {
"SELECT": true,
"INSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"DROP": true,
"CDL": true,
"CQL": true,
"CXL": true,
"cds": true
},
"rules": {
"no-console": "off",
"require-atomic-updates": "off"
}
},
"cds": {
"requires": {
"[hybrid]": {
"auth": {
"kind": "xsuaa"
},
"mailService": {
"kind": "rest",
"credentials": {
"destination": "mail_destination",
"forwardAuthToken": true
}
}
}
}
}
}
srv folder
- Create a mail.cds file inside srv folder. Call db file with this simple service
service MailService {
action sendmail();
}
- Create mail.js file inside srv folder. We are adding our custom logic here and mail client configuration.
const { sendMail } = require('@sap-cloud-sdk/mail-client');
module.exports = srv =>
srv.on("sendmail", async (req) => {
const mailConfig = {
to: 'ahmet.demirlicakmak@aarini.com',
subject: 'Test On Premise Destination',
text: 'If you receive this e-mail, you are successful.'
};
sendMail({ destinationName: 'mail_destination' }, [mailConfig]);
});
project root
- Create a test.http file in the project root and fill it as below.
### // Check mail
POST http://localhost:4004/mail/sendmail
Content-Type: application/json
{}
4) Connect to Your BTP Services in Hybrid Profile
- We will test sending e-mail in hybrid profile. Our reasoning is clearly defined in Capire documentation and the reasoning behind using it is as below:
- Saving time and effort: We can test new features locally
- Particularly selecting individual or combination of services: Although we may need to define many services in deployment, in hybrid approach we have flexibility to use only the ones we are interested.
To bind our service instances to our application, open the terminal and bind each of below service instancess step by step.
cds bind -2 mail-xsuaa:mail-xsuaa-key
cds bind -2 mail-destination:mail-destination-key
cds bind -2 mail-connectivity:mail-connectivity-key
5) Final Step – Test Your Application
Start your application with service instance bindings with command
cds watch --profile hybrid
Go to your test.http file and click Send Request shaded in gray.
Now check your e-mail. We want to receive e-mail with subject and text you have filled in mail.js file instantly.
6) Conclusion
If you have successfully followed up, you have received an e-mail from your SAP BTP On-Premise destination using SAP Cloud SDK and CAP.
To summarize, you have learned how to set up a simple CAP Project, consuming necessary BTP Services in hybrid mode, how SAP Cloud SDK is used with CAP and connecting on-premise mail servers.
Feel free to share and comment on this post for troubleshooting when necessary. Find the resources about SAP CAP and SAP Cloud SDK in below topics and make sure to follow to be notified with latest use cases: