These examples show how to use the SMTP send email function socket.mail(). Although the examples are designed to run "as is" using the Mako Server, they can also be used by other Barracuda App Server products such as Xedge.
Note that Xedge has built-in email configuration via the IDE, as explained in the tutorial How to Send Emails with Xedge IDE.
Before running the examples using the Mako Server, edit mako.conf and configure log.smtp with valid SMTP settings.
The text, html, and eml examples all use the Mako Server's log settings in mako.conf as their SMTP configuration. In each .preload script, the code loads require"loadconf", clones conf.log.smtp into a local smtpCfg table, and then translates consec = "starttls" or consec = "tls" into the settings expected by socket.mail(). This means the same from, to, server, port, user, password, and transport security settings used for emailed logs are also used when these examples send email directly.
Run the email examples in this order:
mako -l::textmako -l::htmlmako -l::eml
All examples except log exit the Mako Server after the email is sent.
This example shows the smallest complete socket.mail() usage pattern: create an SMTP client from mako.conf, send a plain text body, print the result, and exit.
The .preload script performs the following steps:
- Loads and clones the SMTP settings from
mako.conf. - Converts
log.smtp.consecinto the transport settings used bysocket.mail(). - Verifies that
socket.mailwas loaded bymako.zip. - Creates a plain text message body.
- Creates an SMTP client with
socket.mail(smtpCfg). - Sends the message with
smtp:send{...}. - Calls
mako.exit()after the send attempt completes.
The message body is the Robert Frost Poem used by the SharkSSL SMTP C example, but the send operation itself is pure Lua:
local smtp=socket.mail(smtpCfg)
local ok,err=smtp:send{
from=smtpCfg.from,
to=smtpCfg.to,
subject="Text email sent by BAS",
txtbody=message
}Use this example first when validating your SMTP settings because it removes HTML, inline images, and template parsing from the test.
This example sends an HTML email with an inline image by using htmlbody, a plain text fallback, and htmlimg.
Like the text example, .preload clones conf.log.smtp from mako.conf, normalizes the consec setting, creates an SMTP client, sends one message, and exits with mako.exit().
The main difference is the message table passed to smtp:send(...):
local ok,err=smtp:send{
from=smtpCfg.from,
to=smtpCfg.to,
subject="HTML email sent by BAS",
txtbody="The email can only be viewed by an HTML enabled client",
htmlbody=message,
htmlimg={
id="the-unique-id",
name="logo.png",
source=ba.openio"home":open"data/BAS-Logo.png"
}
}The HTML body references the image with src="cid:the-unique-id", and htmlimg attaches data/BAS-Logo.png as the corresponding inline MIME part.
This example is useful after the plain text example succeeds because it confirms that your SMTP configuration also works for multipart HTML messages with embedded content.
This example indirectly sends email by using mako.log() instead of calling socket.mail() directly.
The .preload script defines a small helper that enables timestamps and then writes two log messages:
- The first call queues a log entry without flushing.
- A
ba.timer(...)callback runs two seconds later. - The second call uses
{flush=true}so the buffered log data is flushed immediately. - If logging is not enabled, the helper reports that by calling
trace.
This example uses the same email-related configuration in mako.conf, but through Mako's logging system instead of through socket.mail(). The log.smtp table defines where log emails are sent, log.signature adds the message footer, and log.logerr = true enables emailed Lua exception reports.
The crash-report part of the example is triggered by index.lsp (http://localhost). When that page is requested while the server is running in the background, the page intentionally raises an error if mako.daemon is true. With log.logerr = true, that exception is turned into a log email containing the stack trace.
Background mode means:
- On Windows, the server must be installed as a service.
- On Linux, you can run
mako -s -l::log, which keeps the server attached to the console while still running in background mode.
Unlike the text, html, and eml examples, the log example does not call mako.exit() because it is meant to demonstrate ongoing logging and request-triggered error reporting.
This example shows how to parse an .eml file, modify the parsed message, and send it with socket.mail().
The eml module is useful when you want to design and store an email as a single file and then reuse it as a runtime template. A typical workflow is:
- Create the email in a regular mail client or HTML email editor.
- Save the message as an
.emlfile. - Parse the file at runtime.
- Replace dynamic tags in the parsed body.
- Set sender, recipient, and subject.
- Send the message with
socket.mail().
This approach is practical for HTML emails because the original formatting, inline images, and MIME structure can stay in one consistent source file.
The eml module is part of this example. It is not included with the Barracuda App Server as a built-in module.
The example provides the parser in .lua/eml, and .preload sets up module loading with mako.createloader(io) so it can be imported with:
local eml = require'eml/EmailMessage'If you want to reuse the parser in another BAS application, copy the eml module files into that application's Lua module path and set up loading in the same way.
An EML file is a raw email message stored as text. It normally contains:
- Message headers such as
From,To,Subject,Content-Type, andContent-Transfer-Encoding - One body or multiple MIME parts
- Optional plain text and HTML alternatives
- Optional inline images or attachments
An EML file is effectively the serialized form of one email message. Because it preserves the MIME structure, it is a good format for storing a finished email template that can later be customized before sending.
For example, an HTML body could contain placeholders such as:
<p>Hello {{NAME}},</p>
<p>Your order {{ORDER_ID}} is ready.</p>After parsing the EML file, your Lua code can replace these tags before calling smtp:send(...).
The .preload script performs the following steps:
- Loads and clones the SMTP settings from
mako.conf. - Calls
mako.createloader(io)so Lua can load modules fromeml/.lua. - Loads the parser with
require "eml/EmailMessage". - Opens
data/BAS-Info.eml. - Parses the EML file into a Lua table.
- Verifies that an HTML body and inline-image table were extracted.
- Adds fields required for sending.
- Creates an SMTP client with
socket.mail(smtpCfg). - Sends the parsed and modified message with
smtp:send(m).
The core flow in .preload is:
mako.createloader(io)
local eml = require'eml/EmailMessage'
local emlFile=require"rwfile".file(ba.openio"home","data/BAS-Info.eml")
local m,err = eml(emlFile) -- Parse
m.txtbody="The email can only be viewed by an HTML enabled client"
m.from=smtpCfg.from
m.to=smtpCfg.to
m.subject="EML (HTML) email sent by BAS"
local smtp=socket.mail(smtpCfg)
local ok,err=smtp:send(m)require "eml/EmailMessage" returns a function that parses the raw EML text:
local eml = require'eml/EmailMessage'
local m, err = eml(rawEmlText)On success, the returned table may include:
m.htmlbodyThe decoded HTML body, if present.m.txtbodyThe decoded plain text body, if present.m.htmlimgA table with inline image data extracted from MIME parts withContent-ID.m.charsetThe detected charset from the MIME headers or HTML meta tag.
This return value is shaped so it can be extended and then sent through socket.mail().
After parsing, the example adds the fields typically required by the SMTP client:
m.fromm.tom.subjectm.txtbodyif a plain text fallback should be included
The parsed m.htmlbody and m.htmlimg values are preserved and passed directly to smtp:send(m).
This means the EML file can hold the HTML design and any inline images, while the runtime code supplies delivery-specific values such as recipient and subject.
One of the main advantages of storing an email as EML is that you can keep one approved template and update only the dynamic values before sending.
This is the simplest option and works well when the template only needs a few values replaced.
local m, err = eml(emlFile)
assert(m, err)
m.htmlbody = m.htmlbody
:gsub("{{NAME}}", customerName)
:gsub("{{ORDER_ID}}", orderId)
m.txtbody = (m.txtbody or "Hello {{NAME}}")
:gsub("{{NAME}}", customerName)
:gsub("{{ORDER_ID}}", orderId)
m.from = smtpCfg.from
m.to = customerEmail
m.subject = "Order " .. orderId
assert(socket.mail(smtpCfg):send(m))This pattern is ideal when:
- the email layout should be maintained outside the Lua code
- designers or non-programmers produce the original email
- the same email structure is reused many times
- only a small number of fields need to change at runtime
For more advanced systems, especially embedded systems, the email can still be stored as one stable EML template while selected sections are generated dynamically by Lua.
This is useful when the email includes generated data such as:
- logs
- alarms
- measurement tables
- runtime status summaries
- device-specific diagnostics
The BAS function ba.parselsp() parses Lua Server Page content and returns Lua source code that can be compiled with load(). Note that ba.parselsp()can be used with any text format, including HTML. The parser simply converts text into Lua code and preserves the embedded Lua code within and tags.
- The parser normalizes message structure internally and decodes quoted-printable and base64 body content.
- Inline MIME parts with
Content-IDare collected inm.htmlimg. - The .preload example assumes the EML file contains an HTML body.
- If the EML file does not provide all fields required for sending, add them in Lua before calling
smtp:send(...).