In a simplistic explanation, letterbot is a system which is able to interpret special commands embedded in a common email message. It was not developed to solve a single problem, but to be used as a platform for the development of services on top of it.

Why email?

Using email instead of a more elaborated protocol has a number of uses in many different environments.

Here are a few advantages of that interface:

Well Known
Works on top of well known and widely available standards.
Knowledge Reuse
Benefits from the already acquired knowledge for special setups.
Connection Less
The system can be offline or disabled when a request is sent.
Load Control
Choose the best time to answer a request.
Human Friendly
Contact the system from anywhere, without special tools.
Firewall Friendly
It goes as far as an email can get.
Human Interference
Review requests before dispatching them to the system.
Strong Authentication
Can use public key based protection, if necessary.


Here are some of the letterbot highlights:


No software description is complete without a screenshot. As this is a remote mail administration system, here is a mail sample of how a request would be made:

From: My Name <me@example.com>
To: LetterBot <letterbot@example.com>
Subject: Hello 

hello world!

My Name

Indeed, nothing special.

And here is how letterbot would react to it:

From: LetterBot <letterbot@example.com>
To: My Name <me@example.com>
Subject: Re: Hello  [B0FE55F20]

> hello world! 

Unknown command. Use "help" for more information.


So far, there's no "hello" command available, but we'll create one below. Notice that letterbot already attached the session key in the subject. This way, it's possible to have a single procedure taking several iteration steps with no efforts.

We'll implement the "hello" command below.

Standard modules

Here is the help message sent for the letterbot "help" command, when all the current standard modules are installed.

> help 

Here is a full description of all available commands:


The "chalcalc" command sends you the chalcalc python program, useful
for calculating challenge answers trough its graphic and command line
interfaces. For more information, check the "challenge" command.


The challenge command is an alternative authentication scheme. When
you send the "challenge" command without parameters, you receive
a challenge string. To authenticate, you must concatenate that string
to the end of your password and send the md5 of the resulting string
back as the first parameter to the next challenge command. You may
use standard unix tools to calculate. For example:

    echo -n "<passwd><challenge>" | md5sum

You may also use the chalcalc python program, which provide graphic
and command line interfaces. To obtain this program, just use the
"chalcalc" command, and it will be attached in a mail to you.

Note that a challenge is useful just once. Every time you authenticate,
being successful or not, you'll receive a new challenge.


This command allows you to execute arbitrary commands in the
machine. For example:

    exec <filename>

        Execute attached file with given name.
    exec - <<END
    <shell commands>

        Execute inline script.


This command allows you to send and retrieve files of predefined
directories. The command provides the following subcommands:

    file get <path>

        Retrieve the given file.

    file put <path>

        Put in the given path the attached file. The filename of the
        attached file will be extracted from path itself.


The "gpg" command allows you to access the gpg functionality in
letterbot. The following subcommands are available:

    gpg setkey <filename>

        The "setkey" subcommand allows you to register a gpg public
        key. Any signed messages you send will then be considered as
        strongly authenticated. The filename parameter is the name of
        an attached file containing a gpg public key.

    gpg getkey

        Retrieve the public key of letterbot, if available.

    gpg encrypt

        Ask letterbot to encrypt the returning message with the
        provided key.


You may ask for help on a specific command using "help <command>". Using
just "help" will give you a full description of every available command.


You may authenticate yourself using the command "password <passwd>".
Please, avoid using this command to authenticate yourself, since it
requires you to publish your password. Instead, use the challenge
scheme trough the "challenge" command, or register a gpg key with the
"gpg setkey" command, and sign your messages.


To register yourself as a user, use the command "register <password>". If
possible, encrypt your message when registering.




Here is a sample configuration file, showing how easy it is to personalize letterbot for your needs. In this sample you can also see how the permission system works.

; When debugging is enabled, letterbot will show the responses to stdout
; instead of mailing them back.
debug = yes

; The remote option allows letterbot to check in a central place for
; permissions and user information. Local user information will also
; be considered, even when this option is turned on. This is useful
; to maintain a central repository of information in a farm with many
; machines. Notice that permissions are appended to the end of the
; permission set in this file, and local user data may be overriden
; by remote settings.
;remote = xmlrpc:http://localhost:6757

; This is the email that will receive debugging information when
; letterbot finds some internal error.
admin = me@example.com

; How letterbot will identify itself. Notice that unless the
; email_from_target is enabled, letterbot will only recognize messages
; aimed to his email.
name = LetterBot
email = letterbot@example.com
signature = --

; When email_from_target is on, all messages will be interpreted, and
; letterbot will identify itself to the sender using the "To:" information
; of the processed message. Notice that even when this is turned on,
; you should include valid information in "email" and "name" options,
; since sometimes letterbot must send "new" messages (e.g. an internal
; error occurred).
email_from_target = no

; How letterbot will deliver messages.
smtp_server = localhost

; Where letterbot will store peristent information. You may consider
; this as the letterbot "memory".
options_file = ./options

; GPG keys for letterbot. These keys will be used to decrypt received
; messages, and for signing sent messages. *DO NOT* use the test keys!
gpg_public_key = ./tests/public-key.gpg
gpg_secret_key = ./tests/secret-key.gpg

; LetterBot offers a very flexible permission system. It maps emails
; (with or without wildcards) to permissions. Each permission may
; have additional parameters. Here is an example:
; * = perm1(auth) perm2(sauth) perm3
; *@example.com = perm4(opt1,opt2) perm5(opt2)
; badguy@example.com = -perm2 perm4(opt1)
; goodguy@example.com = perm6(sauth)
; Notice in the example above that ordering matters.
; Existent permissions:
; help      - Allow users to ask for help
; register  - Allow users to register themselves
; gpg       - Allow users to work with gpg encryption and signatures
; file_*    - Allow users to retrieve and/or store files in paths
;             configured in the "files" section. Each path has its
;             own permissions. For example, file_cnc_wb refers to the
;             /cnc/wb path (which might not be the real /cnc/wb in
;             the local filesystem).
; The following options are accepted by all permissions:
; reg       - User must be registered to use this permission.
; auth      - User must be authenticated to use this permission.
; cauth     - User must be authenticated at least with the challenge
;             system use this permission.
; sauth     - User must be authenticated with a strong system (gpg
;             signature) to use this permission.
; crypt     - Message must be encrypted to use this permission.
; The following options are accepted by the "file" permission.
; wo        - User can only write in that directory.
; ro        - User can only read from that directory.

* = help register gpg
*example.com{,.br} = file_wb(wo)
me@example.com = exec

; The paths directive sets which paths are accessible by remote users,
; and under what virtual paths. Notice that besides including the
; path here, you'll have to add permissions for them as well.
;paths = /public:/home/myself/public /wb:/cnc/wb


The system works as a mail "filter", receiving mails in its standard input, usually delivered by some MDA. This makes it possible to have letterbot working in several different schemes. Here are presented a few setup options.

{i} Make sure you have letterbot.conf correctly configured, as described above.


If you're running some standard SMTP server in the machine you want to run letterbot on, perhaps the simplest way to install it in the system is to include a new user with a .forward file in its home directory, such as:



If you're running fetchmail to retrieve your mails, or is running an SMTP server, but want more flexibility when deciding what to process with letterbot, the best option is to use the well known procmail software. Here is a sample configuration file, which would process only messages for the letterbot address. Additionally, it will also check if the messages don't exceed 100kb, and store these messages in a special letterbot mailbox for further consulting:

* ^TO_letterbot@example.com
        :0 c
        * < 100000
        | /usr/bin/letterbot


Notice that this setup allows letterbot to be installed even in your personal email, using the subject to filter out messages to be processed by letterbot, for example.

Multiple Machines

The software offers basic functionality for working on a machine farm. In this case, the problem to be addressed is how to maintain a single base of information for authentication and permissions. The functionality offered allows you to install a central letterbot which will publish user information as read-only. Then, it's possible to setup every other client to check the central information when a request is received. For now, it's only possible to authenticate using a public key scheme when talking to the clients.

Standalone server

When running the lbserver program directly, it will bind itself in the port 6757 and listen for XML-RPC connections. Just point the remote config option to this server in all clients, like this:

remote = xmlrpc:http://localhost:6757

CGI server

If the lbserver program is installed somewhere under an existent HTTP server, it will work as a CGI XML-RPC server. Just point the remote config option in all clients to this server, like this:

remote = xmlrpc:http://example.com/cgi-bin/lbserver


The software was developed with extensibility in mind. If you're wondering how hard it would be to add that specific feature to the system, it's probably just a few lines away.

Hello world

Here is a small module to give you an idea about how to extend letterbot with new functionality:

from letterbot import *

HELP = """\
This is a sample command.

class Hello:
    def __init__(self):
        hooks.register("Command", self.command)
        mm.register_help(0, "hello", HELP)
    def unload(self):
        hooks.unregister_help("Command", self.command)
        mm.unregister_help(0, "hello")

    def command(self, cmd, ans):
        if cmd.get_name() == "hello":
            ans.add_line("Hi master!")
            return 0

def __loadmodule__():
    global mod
    mod = Hello()

def __unloadmodule__():
    global mod
    del mod

Now, if we try again the request shown in the screenshot section, here is what we get:

From: LetterBot <letterbot@example.com>
To: My Name <me@example.com>
Subject: Re: Hello  [B0FE55F20]

> hello world! 

Hi master!


{i} Please, let me know if you develop some interesting new module for letterbot.


Not available. May be eventually published.


GustavoNiemeyer <gustavo@niemeyer.net>


letterbot (last edited 2008-03-03 03:04:54 by GustavoNiemeyer)