Project Idea: XMPP Message Transfer Adapter

XMPP, the Extensible Messaging and Presence Protocol, should be preferred over any other centralized and/or proprietary messaging protocol. Unfortunately, sometimes it can be cumbersome to use XMPP, at least compared to other solutions.

One reason may be that certain port ranges are simply blocked by the network operator (restrictive firewalls). At work for example I can not connect to various XMPP ports through the internal network.

Another reason might be the integration overhead is too high, or the integration simply has not been done (yet). For example I’d like to get monitoring notifications (Icinga/Nagios) through XMPP, but I haven’t found an adequate plugin for this task. Even if I had, I’d still be faced with the previous problem.

Therefore I propose an XMPP Message Transfer Adapter (XMTA). It receives messages through HTTP (on a standard port range) and delivers them as XMPP messages to the server. I am aware of the existence of and XMPP over BOSH and Websockets, and while I’m very happy they exist, their usage is too complicated for a simple task like “send message X”.

In fact, this is the main focus of this tool: simplicity (for the client). The server has the credentials to the XMPP server, i.e. clients only need to know their token, much like Slack’s bot tokens or Telegram’s bot API. Clients are then able to send messages via a single curl command, maybe like so:

curl -X POST -F 'body=Hello, World!'
https://xmta.example.com/send/some-long-unique-hard-to-guess-token

Update: Though a friend of mine has pointed out that putting the token into the URL is actually not the best design choice (as per RFC 7235), I think there is a point to be made for the simplicity of this design decision. Also, in this case the token not only authenticates the client but also the XMPP account and possibly also the recipient.

Because here comes the ambiguous part: should the client be allowed to choose the message recipient? If so, he can simply add another field in the form-data field. If not, destinations must be predefined in the server configuration file. A possible configuration may look like this (YAML):

1
2
3
4
5
tokens:
- 'some-long-unique-hard-to-guess-token':
  user: 'bot@example.com`
  password: `123456`
  destination `notifications@example.com`

Maybe both cases can be allowed. If the destination has been specified in the configuration file, the client is allowed to omit the destination. If the client requests another destination than the one specified on the server he will get a 403 - Forbidden. Sounds like a good API to me.

Speaking about configuration files: should the server be configured through a single static configuration file or should it also have a web interface for creating, modifying and deleting tokens? The latter option would certainly make it more user friendly (i.e. SaaS-like). But then the server also needs a database (or at least some persistent file with write-access to store the configuration) and possibly needs to manage user accounts and authentication.

I think the application should stick to a static configuration file first, other applications may then be built around that.

If I get around to it, I will implement this in the future.