We saw in Lesson 13 that a Spiderwiz-based application can be configured to automatically send notifications, alerts and exception reports by email. Currently Spiderwiz supports only SMTP mail, but other messaging systems can be added by writing a custom Mail plugin. We will see an example here.
We are going to write a WhatsApp messaging plugin. Actually it will be a dual system plugin. If the address to send to is of the form “whatsapp:<phone number>” then a WhatsApp message is sent, otherwise SMTP mail is used to send an email.
Mail plugins need to implement the ZMail interface. However since we want to revert
to the standard SMTP mail when the addressee is not a WhatsApp account we will
extend ZSMTPMail that is by itself an implementation of ZMail
.
Our implementation uses the Twilio SDK. To use it, we need to include the following dependency:
<dependency> <groupId>com.twilio.sdk</groupId> <artifactId>twilio</artifactId> <version>7.54.2</version> <classifier>jar-with-dependencies</classifier> </dependency>
With this in place, let’s see WhatsAppMail
:
package org.spiderwiz.tutorial.lesson16; import com.twilio.Twilio; import com.twilio.rest.api.v2010.account.Message; import com.twilio.type.PhoneNumber; import java.io.UnsupportedEncodingException; import java.util.Map; import javax.mail.MessagingException; import org.spiderwiz.zutils.ZHtml; import org.spiderwiz.zutils.ZSMTPMail; /** * A class that extends ZSMTPMail to implement a dual mail system. If the addressee is a WhatsApp phone number then the message is * sent via WhatsApp, otherwise the 'super' methods are called to process SMTP mail. * otherwise */ public class WhatsAppMail extends ZSMTPMail { private final static String WHATSAPP_PREFIX = "whatsapp:"; private String sid; private String auth; private String fromNumber; /** * Configure WhatsApp with a Twilio Account SID, Auth Token and the sender phone number, * then call the super method to configure SMTP mail. * @param configParams the configuration map. */ @Override public synchronized void configure(Map<String, String> configParams) { sid = configParams.get("sid"); auth = configParams.get("auth"); fromNumber = configParams.get("from"); if (fromNumber != null) fromNumber = WHATSAPP_PREFIX + fromNumber; super.configure(configParams); } @Override public void send(String from, String to, String cc, String subject, String body, boolean html, boolean highPriority) throws MessagingException, UnsupportedEncodingException { // Try first WhatsApp boolean toWhatsApp; boolean ccWhatsApp; if ((toWhatsApp = to != null && to.toLowerCase().startsWith(WHATSAPP_PREFIX)) | (ccWhatsApp = cc != null && cc.toLowerCase().startsWith(WHATSAPP_PREFIX)) ) { Twilio.init(sid, auth); String text = "*" + subject + "*" + (html ? ZHtml.toPlainText(body) : "n" + body); if (toWhatsApp) { Message.creator(new PhoneNumber(to), new PhoneNumber(fromNumber), text).create(); to = null; } if (ccWhatsApp) { Message.creator(new PhoneNumber(cc), new PhoneNumber(fromNumber), text).create(); cc = null; } } // Call super for SMTP mail super.send(from, to, cc, subject, body, html, highPriority); } }
There are just two methods that we need to implement, or
override in our case. The first is configure() (line 29). The method receives a
parameter map that maps keys to values, which is parsed from the mail system
property of the application’s configuration file. To send a
WhatsApp message we need three parameters:
sid
Twilio Account SIDauth
Auth Tokenfrom
The WhatsApp sender’s phone number
We save the parameters for later use and call super.configure()
to let the base class
extract SMTP parameters.
The other method that we override is send() (line 40). This is also simple. We check
if either to
or cc
are WhatsApp addresses and if so we send a WhatsApp message to
any or both of them using the appropriate Twilio methods. Since the mail
message might be formatted as HTML code that is not supported by WhatsApp, we
convert it first to plain text using the static ZHtml.toPlainText() method that is part of the
Spiderwiz framework. The converted text is preceded by a line that consists of
the subject
text enclosed by
asterisks (*) to make it look bold
on WhatsApp. When this is done we call super.send()
to send the message to email addresses via SMTP.
To test the plugin with a chat application, rebuild it with the plugin in the CLASSPATH and configure it to something like this:
[application name]Chat 1 [log folder]/tests/Chat1/Logs [backup folder]/tests/Chat1/Backup [history file]/tests/Chat1/history.dat [producer-1]websocket=localhost:90/MyHub [mail system]class=org.spiderwiz.tutorial.lesson16.WhatsAppMail;sid=ACXXXXXXXXXXXX;auth=your_auth_token;from=+19177568000;server=smtp.gov;user=donaldt@whitehouse.gov;pwd=dumptrump;port=465;ssl=true [from address]Alerts<alert@whitehouse.gov> [to email]Administrator<hell@whitehouse.gov> [to exception email]Bug Reports<bugs@whitehouse.gov> [cc exception email]whatsapp:+12024561111
The configuration of the mail
system property includes the class
parameter that refers to the fully qualified class name of the plugin. Other
parameters define both WhatsApp and SMTP attributes as explained above.
Run the chat application, log in and then type something that should cause an exception, for instance:
!history 1od
A message with the description of the exception will be sent
to the email address configured by to
exception email and a (plain text) copy will be sent to the WhatsApp
account configured by cc exception email
.
The next lesson is the last in the “how to extend Spiderwiz” trilogy. We will talk about writing an Import Handler plugin.