The Lua interpreter in Rumble comes with the standard libraries as well as the extensions listed below.
To add a Lua script to the mail server, simply create a Lua file and add the following command to rumble.conf:
LoadScript /path/to/your/scriptFor an example of how to use the Lua API, check out RumbleLua, which ships with the Rumble packages, or check out these simple example modules.
string.SHA256(s)
Returns the SHA-256 message digest of the string s.
This is primarilly used for creating passwords for saving new accounts or updating old ones.
string.decode64(s) / string.encode64(s)
Decodes or encodes a string using the base-64 algorithm.
file.stat(f):
Returns a table containing information about the file f, similar to fstat().
file.exists(f):
Returns true if the file exists, otherwise false.
network.getHostByName(host):
Resolves the host name host into its IP address.
network.getMX(domain):
Looks up the MX records of domain and returns a list of entries found.
Mailman.accountExists(domain, user):
Returns true if an account exists with the literal domain and username.
Unlike Mailman.addressExists, this function will only return true if an account with the exact credentials exists.
Mailman.addressExists(domain, user):
Returns true if the address user@domain is either an existing email account on the server, or if any wildcard or GLOB'ed alias will pick up mail sent for it. For example, Mailman.addressExists("domain.tld", "somename") will return true if you have created the account *@domain.tld, whereas Mailman.accountExists would return false:
if ( Mailman.accountExists("mydomain.tld", "someuser") ) then
print ("someuser@mydomain.tld is a real account!");
else
print ("someuser@mydomain.tld is not a valid account!");
if ( Mailman.addressExists("mydomain.tld", "someuser") ) then
print ("...but it is a valid address!");
end
end
Mailman.createDomain(domain):
Adds domain as a new domain in the mail service if it doesn't already exist.
Mailman.deleteAccount([uid], domain, user):
If no UID is provided, deletes the account user@domain from the database, otherwise deletes the account with the specified UID.
Mailman.deleteDomain(domain):
Deletes domain from the database if it exists.
Mailman.listDomains():
Returns a table containing all the domains in the mail server database:
Mailman.listAccounts(domain):
Returns a table containing all the accounts associated with domain:
Mailman.listHeaders(uid[, folder]):
Retrieves the headers of all messages belonging to the specified user id or, optionally, the messages in the folder specified by folder:
Mailman.readAccount([uid,] domain, user):
If the account, specified either by the UID or by domain and user, exists, returns a table containing the infomation about the account, otherwise returns false:
Mailman.readMail(uid, lid):
Reads the message with id lid. The account uid is required to prevent exploitation.
If found, the entire message is read and parsed into both headers, message body and
individual message parts in case of multipart messages (text/html versions, attached files
and so on). The returned message structure can be quite complex, and as such, the example
below only shows a fragment of it. For an in-depth example, please see the webmail module
included in the mail server package.
Mailman.saveAccount(account):
If account, specified as a table containing the same information as given by Mailman.readAccount, exists, saves and updates the information stored, otherwise creates a new account with the specified credentials.
Note: If you are saving or updating passwords, remember to first run them through the string.SHA256().
Mailman.sendMail(from, to, message)
Creates and sends an email using the specified parameters.
The message should be properly formatted with headers and a body.
Note: This API call is considered an internal mechanism and will still work even if the
BlockOutgoingMail directive is enabled in rumble.conf.
Rumble.createService(luaFunction, port, [threadCount]):
Creates a TCP service on port, hooking into the function luaFunction. The optional argument
threadCount specifies the number of threads to create (default is 10). Returns true if the service
was created, otherwise returns false. If another thread has already created this service,
createService returns nil.
Rumble.listModules():
Returns a list of the C/C++ modules enabled on the server:
Rumble.readConfig(key)
Returns the value of key in the configuration file:
Rumble.resumeService(svcName)
If suspended, resumes the service called svcName:
Rumble.serviceInfo(svc):
If the service specified in name by svc exists, returns a table containing information about the
service, otherwise returns nil:
Rumble.serverInfo():
Returns a table containing information about the server:
Rumble.getLog():
Returns a table containing the last 200 logged messages from the server:
Rumble.setHook(luaFunction(session, cmd), svcName, when [, cmd])
Adds a Lua hook to the service defined as svcName, hooking the function luaFunction to the
moment in a session specified by when:
- accept: Executes the Lua function whenever a new connection is made to the service
- close: Executes the Lua function when a connection is being closed.
- command: if cmd is specified, executes the Lua function whenever that specific command
is issued by the client.Hooks can issue a return value to control the sessions. A return value of false or "failure" will terminate a connection.
Rumble.startService(svcName)
If stopped (disabled), tries to start up the service called svcName:
Rumble.stopService(svcName)
If running or suspended, stops (kills) the service called svcName:
Rumble.suspendService(svcName)
If running, suspends the service called svcName gracefully. Unlike stopService(), it will only stop active server sessions once they have finished:
Session handles returned by hooking via Rumble.setHook or Rumble.createService have the following set of functions to communicate with the client:
session:send(msg):
Sends the message msg to the client:
session:receive():
Returns one line of data received by the client.
session:receivebytes(numBytes):
Reads numBytes of data from the client and returns the data received and the actual number of
bytes, or an empty string and a length of -1 if the operation failed:
session:lock() and session:unlock():
Locks or unlocks the core mutex of the entire service. This method can be used for performing
operations that would otherwise be unsafe in a threaded environment.
Rumble will automatically unlock the service once your script exits, but nonetheless, it's
important to remember to unlock it after you're done...just in case.