As the name implies, the email notification plugin is a plugin that sends out emails when certain events occur. This document covers how to install, test, and use this plugin.

Prerequisites

Ensure that you have Kill Bill, Kaui, and the database set up as explained in the Getting Started Guide.

Overview

The email notification plugin is a notification plugin. It listens to events and sends emails accordingly.

Currently, the email notification plugin supports the following events:

Event TypeEmail Description

INVOICE_CREATION

The customer will receive an email informing them that a new invoice is available.

INVOICE_NOTIFICATION

The customer will receive an email about upcoming invoices (the time at which to send the email is configured through the Kill Bill system property org.killbill.invoice.dryRunNotificationSchedule).

INVOICE_PAYMENT_SUCCESS

The customer will receive an email after each successful payment or refund.

INVOICE_PAYMENT_FAILED

The customer will receive an email after each failed payment.

SUBSCRIPTION_CANCEL

The customer will receive an email at the time a subscription was requested to be canceled and/or at the effective date of the subscription cancellation.

In addition, it can be extended to to handle other types of events as well. This is explained in the [_configuring_the_plugin_for_additional_events] section below.

To send an email the following is required:

  • The tenant or account must be configured to permit such event(s). This is explained in the [_plugin_configuration] section below.

  • The account for which the emails need to be sent must have certain fields set. This is explained in the [_account_configuration] section below.

Plugin Installation

A plugin can be installed via the Kill Bill Package Manager (KPM). For this, please follow the steps given below:

  1. Ensure that you have kpm installed as explained here.

  2. Install the plugin using the following kpm command (Replace <path_to_install_plugin> with the path where you want to install the plugin. This path should match the path specified by the org.killbill.osgi.bundle.install.dir property in the Kill Bill configuration file):

    kpm install_java_plugin email-notifications --destination=<path_to_install_plugin>
  3. Verify that the plugin is installed properly. This can be done by ensuring that the plugin JAR is present at the path_to_install_plugin specified in the previous step. Alternatively, you can also open kpm in Kaui and verify that the email notification plugin is running as follows: kaui email notification plugin

  4. If you would like to make changes to the plugin, you can clone the plugin code, build and deploy it as explained here.

Database Configuration

The email-notification-plugin requires some additional database tables. To create these tables, please follow the steps given below:

  1. Connect to the Kill Bill database.

  2. Run the email-notification-plugin DDL.

Plugin Configuration

In order to use the email notification plugin, a tenant needs to be configured with the SMTP properties required for sending emails. Additionally, the tenant can also be configured with the events for which emails should be sent. In addition to the per-tenant configuration, the plugin also allows a more granular account-level configuration for the set of emails to be sent for the particular account. Thus, either the tenant or the account needs to be configured with the events for which the email needs to be sent.

The tenant/account configuration can be done by executing the required API endpoints via cURL as explained below:

  1. Configure the tenant using the following cURL command (Replace <events> with a comma-separated list of the events for which the emails need to be sent. For example, to configure the tenant to send emails for INVOICE_CREATION and INVOICE_PAYMENT_SUCCESS, specify org.killbill.billing.plugin.email-notifications.defaultEvents=INVOICE_CREATION,INVOICE_PAYMENT_SUCCESS):

    curl -v \
         -X POST \
         -u admin:password \
         -H 'X-Killbill-ApiKey: bob' \
         -H 'X-Killbill-ApiSecret: lazar' \
         -H 'X-Killbill-CreatedBy: admin' \
         -H 'Content-Type: text/plain' \
         -d 'org.killbill.billing.plugin.email-notifications.defaultEvents=<events>
    org.killbill.billing.plugin.email-notifications.smtp.host=127.0.0.1
    org.killbill.billing.plugin.email-notifications.smtp.port=25
    org.killbill.billing.plugin.email-notifications.smtp.useAuthentication=true
    org.killbill.billing.plugin.email-notifications.smtp.userName=uuuuuu
    org.killbill.billing.plugin.email-notifications.smtp.password=zzzzzz
    org.killbill.billing.plugin.email-notifications.smtp.useSSL=false
    org.killbill.billing.plugin.email-notifications.smtp.sendHTMLEmail=true
    org.kil[email protected]yyy.com' \
    http://127.0.0.1:8080/1.0/kb/tenants/uploadPluginConfig/killbill-email-notifications
  2. If you are on Windows, we recommend that you use Git Bash to run the above command. Since the above is a multiline cURL command, it may not run properly in the standard windows command prompt. Alternatively, you may also use Postman to execute the tenant configuration endpoint as explained here.

  3. Configure the account using the following cURL command (Replace {accountId} with the id of the account for which emails need to be sent and <events> with a comma-separated list of the events for which the emails need to be sent. For example, to configure the account to send emails for INVOICE_CREATION and INVOICE_PAYMENT_SUCCESS, specify "INVOICE_CREATION", "INVOICE_PAYMENT_SUCCESS"):

    curl -v \
         -X POST \
         -u admin:password \
         -H 'X-Killbill-ApiKey: bob' \
         -H 'X-Killbill-ApiSecret: lazar' \
         -H 'X-Killbill-CreatedBy: admin' \
         -H 'Content-Type: application/json' \
         -d '[<events>]' \
        http://127.0.0.1:8080/plugins/killbill-email-notifications/v1/accounts/{accountId}
  4. Note that either the tenant or the account should be configured with the events for which emails need to be sent, otherwise, emails will not be sent. Some scenarios for this:

    1. If a tenant is configured with some events, but the account is not configured, then emails will be sent based on what is configured at the tenant level.

    2. If a tenant is not configured with any events but the account is configured with events, then emails will be sent based on what is configured at the account level.

    3. If both tenant and account are configured with separate events, emails will be sent based on the events configured for both.

Account Configuration

The account for which emails need to be sent, needs to have the email and locale fields set. In addition, the [email-templates] used by the notification plugin also require the company, address1, city, state, postalCode, country fields also set on the Account.

Thus, ensure that the account is created using the following cURL command (Replace <email_id> with the email id where you would like to receive the email and change values for the other fields as required):

curl -v \
    -X POST \
    -u admin:password \
    -H "X-Killbill-ApiKey: bob" \
    -H "X-Killbill-ApiSecret: lazar" \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -H "X-Killbill-CreatedBy: demo" \
    -H "X-Killbill-Reason: demo" \
    -H "X-Killbill-Comment: demo" \
    -d '{ "name": "John Doe", "email": "<email_id>", "currency": "USD", "company": "Acme Corporation", "locale":"en_US", "address1": "57 Academy Drive","city": "Oak Creek","state": "WI","postalCode": "53154", "country": "US"}' \
"http://127.0.0.1:8080/1.0/kb/accounts"

SMTP Server Notes

In order to be able to use the email notification plugin to send emails, a local SMTP server is required.

We typically use the namshi/smtp docker image as follows to start a local SMTP server on port 25:

docker run -tid --name smtp_server -p 25:25  -e DISABLE_IPV6=true namshi/smtp

Alternatively, if you would like to use a non-docker based SMTP server, you can use MailSlurper. MailSlurper is a small handy SMTP server that can be useful for development and testing. It can be downloaded and configured as explained here.

Testing the plugin

Once the plugin is installed and configured as explained above, it can be used for sending emails. You can verify that the plugin is working correctly by following the steps given below:

  1. Start a local SMTP server as explained in the [_smtp_server_notes] section above.

  2. Ensure that Kill Bill is running either in standalone mode or in Tomcat.

  3. Create a tenant as follows (specify the required apiKey and apiSecret):

    curl -v \
        -X POST \
        -u admin:password \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -H "X-Killbill-CreatedBy: demo" \
        -H "X-Killbill-Reason: demo" \
        -H "X-Killbill-Comment: demo" \
        -d '{ "apiKey": "bob", "apiSecret": "lazar"}' \
        "http://127.0.0.1:8080/1.0/kb/tenants"
  4. Configure the tenant as specified in the [tenant-config] section above with INVOICE_CREATION and INVOICE_PAYMENT_SUCCESS events.

  5. Create an account as follows (Replace <email_id> with the email id where you would like to receive the email and change values for the other fields as required):

    curl -v \
        -X POST \
        -u admin:password \
        -H "X-Killbill-ApiKey: bob" \
        -H "X-Killbill-ApiSecret: lazar" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -H "X-Killbill-CreatedBy: demo" \
        -H "X-Killbill-Reason: demo" \
        -H "X-Killbill-Comment: demo" \
        -d '{ "name": "John Doe", "email": "<email_id>", "currency": "USD", "company": "Acme Corporation", "locale":"en_US", "address1": "57 Academy Drive","city": "Oak Creek","state": "WI","postalCode": "53154", "country": "US"}' \
    "http://127.0.0.1:8080/1.0/kb/accounts"
  6. If successful, the command above returns a Location header like http://127.0.0.1:8080/1.0/kb/accounts/eda3e357-20a1-456d-a9b3-b39ca3db8020. Copy the account_id in the header (eda3e357-20a1-456d-a9b3-b39ca3db8020 in this case) and save it for future use.

  7. Add a payment method as follows (replace <account_id> with the account id obtained above):

    curl -v \
        -X POST \
        -u admin:password \
        -H "X-Killbill-ApiKey: bob" \
        -H "X-Killbill-ApiSecret: lazar" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -H "X-Killbill-CreatedBy: demo" \
        -H "X-Killbill-Reason: demo" \
        -H "X-Killbill-Comment: demo" \
        -d '{ "accountId": "<account_id>", "pluginName": "__EXTERNAL_PAYMENT__"}' \
        "http://127.0.0.1:8080/1.0/kb/accounts/<account_id>/paymentMethods"
  8. If successful, the command above returns a Location header like http://127.0.0.1:8080/1.0/kb/paymentMethods/c2ff0040-7c5b-48bf-9685-a4c57501535f. Copy the payment_method_id in the header (c2ff0040-7c5b-48bf-9685-a4c57501535f in this case) and save it for future use.

  9. Set the payment method as default as follows (replace <account_id> and <payment_method_id> with the values obtained above):

    curl -v \
        -X PUT \
        -u admin:password \
        -H "X-Killbill-ApiKey: bob" \
        -H "X-Killbill-ApiSecret: lazar" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -H "X-Killbill-CreatedBy: demo" \
        -H "X-Killbill-Reason: demo" \
        -H "X-Killbill-Comment: demo" \
        "http://127.0.0.1:8080/1.0/kb/accounts/<account_id>/paymentMethods/<payment_method_id>/setDefault"
  10. Create a external charge to trigger an invoice as follows(replace <account_id> with the account_id obtained above):

    curl -v \
        -X POST \
        -u admin:password \
        -H "X-Killbill-ApiKey: bob" \
        -H "X-Killbill-ApiSecret: lazar" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json" \
        -H "X-Killbill-CreatedBy: demo" \
        -H "X-Killbill-Reason: demo" \
        -H "X-Killbill-Comment: demo" \
        -d '[ { "accountId": "<account_id>", "description": "My charge", "amount": 50, "currency": "USD" }]'    \
        "http://127.0.0.1:8080/1.0/kb/invoices/charges/<account_id>?autoCommit=true"
  11. Confirm that an email is sent for the invoice and successful payment.

Note that you can also use Kaui for executing steps 2-9 above.

Template and resource configuration

The email notification plugin uses Mustache templates for generating emails. This section explains how custom email templates can be configured.

Templates Overview

An email template contains the body of an email. In addition to static text, it contains some variables which are replaced at runtime by the mustache engine.

The email notification plugin comes with some default templates. However, users can also upload their custom templates.

The email notification plugin uses one template per locale and per type (as opposed to one template per type with an additional set of translation string bundles for each locale). So, for example, the INVOICE_CREATION event can have templates like INVOICE_CREATION_en_US, INVOICE_CREATION_fr_FR, and so on. When an INVOICE CREATION email needs to be sent for a user, the user’s locale is checked and the corresponding template is used. The default templates are available only for the en_US locale, however, users can upload templates for other locales if required.

Resources overview

In addition to templates, the email notification plugin requires a resource file. This resource file contains key-value pairs which can be used to replace variables in a template. The email notification plugin comes with a default resource file that contains key-value pairs for the variables in the default templates.

Unlike email templates, all the events have a single resource file. However, different locales can have different resource files. This allows having string translations in different languages, (like different translations for the catalog product names). So for example, you can have different resource files like Translation_en_US.properties, Translation_fr_FR.properties, and so on. When an email needs to be sent for a user, the user’s locale is checked and the corresponding resource file is used to replace the variables in the template.

The default resource file is available only for the en_US locale. Users can add additional key-value pairs to this resource file as well as add new resource files for different locales.

Template/Translation Resource Keys

Each email template and the translation resource is assigned a key. To upload a custom email template/translation resource, its key needs to be specified.

The following table provides details about the template/translation resource keys (assuming that the locale is en_US):

Template TypeTemplate KeyTemplate DescriptionDefault Template

Invoice creation

killbill-email-notifications:INVOICE_CREATION_en_US

Template for the email that will be sent when an invoice is created

InvoiceCreation.mustache

Upcoming invoices

killbill-email-notifications:UPCOMING_INVOICE_en_US

Template for the email that will be sent when an invoice is due

UpcomingInvoice.mustache

Successful payments

killbill-email-notifications:SUCCESSFUL_PAYMENT_en_US

Template for the email that will be sent when a payment is successful

SuccessfulPayment.mustache

Failed payments

killbill-email-notifications:FAILED_PAYMENT_en_US

Template for the email that will be sent when a payment fails

FailedPayment.mustache

Subscription cancellation (requested date)

killbill-email-notifications:SUBSCRIPTION_CANCELLATION_REQUESTED_en_US

Template for the email that will be sent when a user requests to cancel a subscription

SubscriptionCancellationRequested.mustache

Subscription cancellation (effective date)

killbill-email-notifications:SUBSCRIPTION_CANCELLATION_EFFECTIVE_en_US

Template for the email that will be sent when a subscription is actually cancelled

SubscriptionCancellationEffective.mustache

Payment refunds

killbill-email-notifications:PAYMENT_REFUND_en_US

Template for the email that will be sent when a payment is refunded

PaymentRefund.mustache

Translation strings

killbill-email-notifications:TEMPLATE_TRANSLATION_en_US

Includes all the text values referenced in the templates. Also includes the email subjects using the following keys: upcomingInvoiceSubject successfulPaymentSubject failedPaymentSubject paymentRefundSubject subscriptionCancellationRequestedSubject subscriptionCancellationEffectiveSubject invoiceCreationSubject

Translation_en_US.properties

Uploading a custom template

As explained earlier, you can upload per-tenant email templates for various events. Let’s look at an example to upload a template for the next upcoming invoice for a locale en_US:

  1. Create the template /tmp/UpcomingInvoice.mustache:

    *** You Have a New Invoice ***
    
    You have a new invoice from {{text.merchantName}}, due on {{invoice.targetDate}}.
    
    {{#invoice.invoiceItems}}
    {{startDate}} {{planName}} : {{invoice.formattedAmount}}
    {{/invoice.invoiceItems}}
    
    {{text.invoiceAmountTotal}}: {{invoice.formattedBalance}}
    
    {{text.billedTo}}:
    {{account.companyName}}
    {{account.name}}
    {{account.address1}}
    {{account.city}}, {{account.stateOrProvince}} {{account.postalCode}}
    {{account.country}}
    
    If you have any questions about your account, please reply to this email or contact {{text.merchantName}} Support at: {{text.merchantContactPhone}}
  2. Upload the template for your tenant:

    curl -v \
    -u admin:password \
    -H "X-Killbill-ApiKey: bob" \
    -H "X-Killbill-ApiSecret: lazar" \
    -H 'X-Killbill-CreatedBy: admin' \
    -H "Content-Type: text/plain" \
    -X POST \
    --data-binary @/tmp/UpcomingInvoice.mustache \
    http://127.0.0.1:8080/1.0/kb/tenants/userKeyValue/killbill-email-notifications:UPCOMING_INVOICE_en_US
  3. If your template uses some additional keys than what are specified in the default translation file, these need to be added to the translation file as explained in the next section.

Uploading Resource files

As explained earlier, you can upload additional resource files for different locales or additional keys in existing resource files. In order to do this, please follow the steps given below:

  1. Check if a resource file already exists for your locale. If so, download the file and if not, create a new file. You can use the default translation template as a reference to create a new file.

  2. Add the required properties (key-value pairs) to your file.

  3. Upload the new resource file using the following cURL command (Replace <template-name> with the name of the file created in the previous step and <translation_key> with the translation key. For example the translation key for a resource file for the en_US locale will be TEMPLATE_TRANSLATION_en_US):

    curl -v \
    -u admin:password \
    -H "X-Killbill-ApiKey: bob" \
    -H "X-Killbill-ApiSecret: lazar" \
    -H 'X-Killbill-CreatedBy: admin' \
    -H "Content-Type: text/plain" \
    -X POST \
    --data-binary @/<template-name>.properties \
    http://127.0.0.1:8080/1.0/kb/tenants/userKeyValue/killbill-email-notifications:<translation_key>

Configuring the plugin for additional events

As explained earlier, the email notification plugin is a notification plugin. In addition to the events handled by it by default, it can be configured to listen to other events and send emails accordingly.

In order to configure the plugin to send emails for other events, you will need to modify the plugin code as follows:

  1. Ensure that the event for which you would like to send an email is defined in the ExtBusEventType.java.

  2. Modify the EmailNotificationListener class as follows:

    1. Modify the EmailNotificationListener#handleKillbillEvent method to add case statements corresponding to the events that need to be handled.

    2. Add a method corresponding to the email that you would like to send similar to the EmailNotificationListener#sendEmailForUpComingInvoice method.

  3. Upload email templates and translation resource file corresponding to the email that you would like to send as explained in the [_template_and_resource_configuration] section.

Customizing the invoice sent in an email

Sometimes, you may need to customize the invoice sent in an email with additional fields. For this, you will need to create a custom plugin. The detailed instructions for this are mentioned in our Custom Email Invoice Formatter document.

Troubleshooting

This section covers some common issues and their solutions.

Emails not sent

Sometimes, even after configuring the plugin as mentioned above, you may find that emails are not sent. There are several reasons for this:

Missing information on Account

In order to send an email, the Account record needs to have the locale and email fields set. In addition, if you are using the default templates provided by the plugin, the company, address1, city, state, postalCode, country fields also need to be set on the Account. If any of these fields are missing, emails will not be sent and you will see the following exception in the Kill Bill logs:

com.samskivert.mustache.MustacheException: No key, method or field with name 'account.companyName'

Ensure that the account for which the emails are to be sent is configured with all the required fields as explained in the [_account_configuration] section above.

Missing information in template

Sometimes, you may upload a custom template. However, you may forget to upload the translation keys for it in the resource file. In such a case, the email will not be sent and you will see the following exception in the Kill Bill logs:

com.samskivert.mustache.MustacheException: No key, method or field with name 'text.merchantName'

Ensure that you also update the translation properties as specified in the [_uploading_resource_files] section above.

Enabling SSL in emails

In order to enable SSL while sending emails, you need to configure the tenant with the org.killbill.mail.useSSL=true as specified in the [tenant-config] section above.