FileMaker 18: Sending FileMaker HTML Email with SMTP and cURL
A major new feature in FileMaker 18 that has flown somewhat under the radar is the expanded capability of the Insert from URL script step. Insert from URL now supports the smtp and smtps URL protocols, as well as a few related cURL options. This means that sending email is now possible using Insert from URL, including the ability to send HTML email!
Sending HTML email has been a long-requested feature for the FileMaker platform and was previously only available through plug-ins or, more recently, external API calls. Using cURL to send emails with attachments provides additional capabilities that makes FileMaker HTML emails more robust.
In this article we’ll review how sending mail using SMTP and cURL in FileMaker 18 works and go through several examples. We’ve also built a robust demo file you can download for free and use to dig into this functionality in more detail, and we’ll discuss some of its capabilities here. Finally, we’ll look at how this new feature compares to some alternatives for sending mail from your FileMaker app.
Note that sending email with SMTP and cURL works across the entire FileMaker 18 platform, including FileMaker Pro Advanced, FileMaker Go, WebDirect, and server-side scripts.
How it Works
To send mail using the Insert from URL script step, there are three major components you need to assemble: the URL, the cURL options string, and the message content in raw MIME format. There are a few additional options in the Insert from URL script step which we’ll also review.
URL
The URL is the SMTP server address, preceded with the “smtps” or “smtp” URL protocol, and followed by the port number. For Gmail, this is smtps://smtp.gmail.com:465
. Your email provider will likely have its SMTP server and port information documented online.
If the port is 465, use the “smtps” URL protocol; if it’s 587 or another port, use “smtp”. Generally speaking, the protocol and port define the type of security initiated (implicit TLS vs. explicit STARTTLS; details on this are beyond the scope of this article).
cURL: Send Email with Attachment
There are four required cURL options to send mail with SMTP. The full cURL options string for these would look something like:
"--mail-from sender@example.com
--mail-rcpt recipient@example.com
--upload-file $mail_file
--user account:password"
Notes:
- The sender and recipient addresses are not enclosed in quotes.
- For multiple recipients, repeat the
--mail-rcpt
option for each individual recipient. This includes To, Cc, and Bcc recipients. - The
--upload-file
option specifies a variable which has been set to a container data object containing the message in raw MIME format. This is explained in more detail below, but note that only the variable name is indicated in the cURL options string, not the variable content itself. In other words, the cURL option should be written as"--upload-file $mail_file"
and not"--upload-file " & $mail_file
. - The account and password are not enclosed in quotes.
There are a few additional options which are not strictly required but are recommended:
"--ssl-reqd
--show-error
--dump-headers $headers"
Notes:
--ssl-reqd
tells the URL request to require an SSL/TLS (encrypted) connection with the SMTP server; if this is not available, the connection is terminated. An alternative cURL option is-ssl
which means that SSL/TLS is attempted, but if it’s not available, the request reverts to a non-secure connection. Obviously, it’s best to use-ssl-reqd
.- Include the
--show-error
option to be able to see specific errors returned by the cURL library. If the request fails, use theGet(LastExternalErrorDetail)
function to get the cURL response code. - The
--dump-headers
option returns the full cURL response headers to the variable name specified. This can be helpful for debugging purposes. Be sure to specify the variable name the same way as handled with the--upload-file
option.
MIME Message
MIME, or Multipurpose Internet Mail Extensions, is a standard for formatting email messages to support text, attachments, and messages with multiple parts. MIME is a pretty deep topic that could fill an article all on its own. But let’s start with a very basic structure of a MIME formatted message:
From: Sender Name <sender@example.com>
To: Recipient Name <recipient@example.com>
Subject: Subject line
Content-Type: text/plain; charset="utf8"
Hello World!
The From
and To
lines contain the sender and recipient(s), formatted as Sender Name <sender@example.com>
(to include the sender’s display name) or just sender@example.com
(no display name). Separate multiple recipients with a comma and space. For Cc recipients, just add a new line starting with CC:
(all caps). Do not include Bcc recipients in the MIME message, since the actual message content is visible to all recipients. To specify a “reply to” address different than the “from” address, add a new line starting with Reply-To:
.
The Content-Type
line is a MIME header that indicates what type of content the message contains. In this example, the message body contains plain text. There are many different content types, and it’s common for a message to include multiple content types; more on that later.
In your FileMaker app, you’ll need to use a calculation field or script to assemble all of the components of the message into MIME-formatted text. You then use the TextEncode function to convert this text into container data. For example, say you have a script that assembles the MIME-formatted text and sets it to a variable called $mail_content
. You would then add the following step:
Set Variable ( $mail_file ; TextEncode ( $mail_content ; "utf-8" ; 3 ) )
The $mail_file
variable is now properly set for use in the --upload-file
cURL option mentioned above.
Other Insert from URL Options in FileMaker
There are a couple other settings to note in the Insert from URL script step.
Target: Set this to a variable named $result
. This should be blank when a message is sent successfully, but will contain useful debugging information when it’s not.
Verify SSL Certificates: In general, this option should be checked, as it provides additional security by validating the SSL certificate of the SMTP server. However, in our testing with Gmail, we found that FileMaker is unable to verify Gmail’s SSL certificate. It’s unclear why this is, but for now, if you want to send mail through Gmail’s SMTP server, you’ll need to leave this box unchecked.
Handling Errors
Now that we have everything we need to execute the Insert from URL script step, we need to do some error checking in case things don’t work. Immediately following Insert from URL, you’ll want to capture Get(LastError)
and Get(LastExternalErrorDetail)
. Since the Set Variable step generates its own LastError, you’ll need to do this in a single step using the Let
function so that all errors captured are from the Insert from URL step:
Set Variable ( $parse_errors ;
Let ( [
$error = Get ( LastError ) ;
$external_error = Get ( LastExternalErrorDetail )
] ;
True
)
)
Your script should then inform the user or take other appropriate action if errors are encountered. Be sure to inspect the $result
variable in your error handling as well.
There’s a MIME and a Place for Everything
In our basic example above, we generated a plain text message, as indicated by the Content-Type
header in the MIME message. But MIME can handle lots of different content types, as well as multiple content types.
HTML
To compose an HTML message, just set the Content-Type
to text/html
instead of text/plain
. The message body can then contain HTML content which will be rendered as HTML by the recipient’s email client. Simple!
Multipart Messages
Email messages often contain multiple content types. A simple example is an email with both message text and an attachment. MIME handles this using the multipart
content type, with a specified boundary name. The boundary is then referred to in the message content to indicate where a part starts (--BoundaryName
) and where the last part with that content type ends (--BoundaryName--
). The following example message includes both HTML and plain text content, for proper handling by email clients that aren’t able to render HTML messages:
From: Sender Name <sender@example.com>
To: Recipient Name <recipient@example.com>
Subject: Subject line
Content-Type: multipart/alternative; boundary=AlternativeBoundary
--AlternativeBoundary
Content-Type: text/plain; charset="utf-8"
Hello World!
--AlternativeBoundary
Content-Type: text/html; charset="utf-8"
<html>
<body>
Hello World!
</body>
</html>
--AlternativeBoundary--
The “Alternative” multipart subtype indicates that each part is an alternative version of the same content. Here, each part is the message text, and the last part that the user’s email client is able to render is the one that is displayed (this is why we’ve ordered the HTML part last here).
There are several different multipart subtypes. “Mixed” indicates that the message contains different types of content, such as text and attachments. “Related” indicates that each part is a component of a larger whole, such as when an inline image attachment appears within an HTML text message. (There are many others as well, beyond the scope of this post.)
Email Attachments in MIME
The handling of attachments in MIME can get pretty involved. An attachment requires several MIME headers, and the attachment file itself must be converted into Base64-encoded text. An attachment for a text file named “HelloWorld.txt” would be represented as follows:
Content-Type: text/plain; name="HelloWorld.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="HelloWorld.txt"
[base64-encoded text]
Notes:
- The particular MIME content type depends on the type of file attached. A good list of MIME types based on filename extension can be found here.
- In FileMaker you can convert a file stored as container data into Base64-encoded text using the Base64Encode function.
To further complicate things, if the message contains text as well as the attachment, the entire message should be formatted as multipart/mixed
:
From: Sender Name <sender@example.com>
To: Recipient Name <recipient@example.com>
Subject: Subject line
Content-Type: multipart/mixed; boundary=MixedBoundary
--MixedBoundary
Content-Type: text/html; charset="utf-8"
<html>
<body>
Hello World!
</body>
</html>
--MixedBoundary
Content-Type: image/jpeg
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="MyImage.jpeg"
[base64-encoded text]
--MixedBoundary--
Universal MIME Structure
A robust email implementation needs to be able to handle different combinations of content types and numbers of parts. For example, you might need to be able to send HTML text, plain text, one or more regular attachments, and one or more inline image attachments. This begs the question: Is there a singular way to code to handle all these combinations? As you might have guessed, the answer is Yes! Thanks to some smart folks on the Internet, we’ve found that the following structure for a MIME-formatted message consistently works, even if some parts are not present.
- Mixed
- Alternative
- Plain Text
- Related
- HTML Text
- Inline image 1
- Inline image 2
- (Repeat for additional inline images)
- Attachment 1
- Attachment 2
- (Repeat for additional attachments)
- Alternative
To illustrate, the following example represents an email with both a plain text and HTML body, an inline image attachment (MyImage.jpeg) and a regular attachment (HelloWorld.txt):
From: Sender Name <sender@example.com>
To: Recipient Name <recipient@example.com>
Subject: Subject line
Content-Type: multipart/mixed; boundary="MixedBoundary"
--MixedBoundary
Content-Type: multipart/alternative; boundary="AlternativeBoundary"
--AlternativeBoundary
Content-Type: text/plain; charset="utf-8"
Hello World!
--AlternativeBoundary
Content-Type: multipart/related; boundary="RelatedBoundary"
--RelatedBoundary
Content-Type: text/html; charset="utf-8"
<html>
<body>
Hello World!<br>
Here is an inline image:<br>
<img src="cid:MyImage.jpeg"/>
</body>
</html>
--RelatedBoundary
Content-Type: image/jpeg; name="MyImage.jpeg"
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="MyImage.jpeg"
Content-ID: <MyImage.jpeg>
[base64-encoded text]
--RelatedBoundary--
--AlternativeBoundary--
--MixedBoundary
Content-Type: text/plain; name="HelloWorld.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="HelloWorld.txt"
[base64-encoded text]
--MixedBoundary--
The above example contains at least one of each of the parts we’ve discussed (plain text, HTML, inline image, regular attachment). But what if you want to send an email with no attachments, no inline images, or no alternative plain text message? You can still keep the same basic structure in place; just don’t include any part or its starting boundary that’s not present. For example, here’s an email containing just HTML text and a regular attachment:
From: Sender Name <sender@example.com>
To: Recipient Name <recipient@example.com>
Subject: Subject line
Content-Type: multipart/mixed; boundary="MixedBoundary"
--MixedBoundary
Content-Type: multipart/related; boundary="AlternativeBoundary"
--AlternativeBoundary
Content-Type: multipart/related; boundary="RelatedBoundary"
--RelatedBoundary
Content-Type: text/html; charset="utf-8"
<html>
<body>
Hello World!
</body>
</html>
--RelatedBoundary--
--AlternativeBoundary--
--MixedBoundary
Content-Type: text/plain; name="HelloWorld.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="HelloWorld.txt"
[base64-encoded text]
--MixedBoundary--
The flexibility of this structure makes it relatively straightforward to code for the various possible combinations of email content. And speaking of code…
Demo File HTML FileMaker Email
To gain a better understanding of using SMTP and cURL to send emails with attachments, we built a demo file to test this feature and come up with a robust framework to handle various scenarios. We wanted to be able to easily test the following:
- Define and test multiple SMTP configurations
- Define and test multiple messages with different recipients and content
- Multiple recipients
- Plain text, HTML, and HTML with CSS content
- One or more regular attachments
- One or more inline image attachments
The demo provides several examples of how to use this feature and suggests ways you could use it to build or extend your own custom app.
You can download the demo file for free here. It requires that you have FileMaker Pro 18 Advanced installed. Free trial software is available.
We hope our demo file helps in your exploration!
When Should I Use FileMaker to Send HTML Emails?
As we’ve shown here, there is a lot of work involved in configuring FileMaker 18 to send mail using cURL and SMTP. While we’ve done a lot of the heavy lifting for you already in our demo file showing cURL to send emails with attachments, there are still a lot of considerations and customization required to incorporate this into any production app. Before moving forward with any serious email implementation in FileMaker, it’s a good idea to review the various options available and make sure you choose the right one for your business case. Here is a quick overview of some options and their benefits and drawbacks.
Native FileMaker 18 (SMTP and cURL)
Pros:
- Native FileMaker; no external tools or services necessary, beyond access to an SMTP server
- Especially well-suited for simple HTML email and attachments
- Full control over your own code
Cons:
- A bit of code to write and maintain; development cost
- Requires savvy users or developers who are comfortable writing HTML content
- Daily or monthly message limits (as governed by SMTP server)
Plug-In
There are several FileMaker email plug-ins on the market. This has historically been the main way to send HTML email and, prior to FileMaker 17, email with multiple attachments.
Pros:
- Less development required; most of the code is managed for you within the plug-in
- Especially well-suited for simple HTML email and attachments
- Some plug-ins are free
Cons:
- Have to manage plug-in distribution to users
- Most plug-ins are not free
- Requires savvy users or developers who are comfortable writing HTML content
- Daily or monthly message limits (as governed by SMTP server)
API
In recent years, more and more email services are providing API’s so that you can connect your custom apps directly to them. This includes full email campaign services like MailChimp and Constant Contact, as well as more bare-bones endpoint services like Amazon SES and SendGrid.
Pros:
- Development required, but in some cases can be simpler than the above options
- Some providers offer free tiers of service
- Access to HTML email templates with email campaign providers like MailChimp, so users don’t need to know as much HTML
- Higher message limits (with paid plans)
- Many services offer additional benefits such as email campaign analytics and tools to minimize email getting blocked or flagged as spam
Cons:
- Requires maintaining an account with an additional service provider
- Integration with API’s requires a bit of code to write and maintain; development cost
- For access to higher message limits or additional benefits you’ll likely need a paid plan
Stu Dietz is a FileMaker 17 Certified Developer at Skeleton Key in St. Louis, MO.
About Skeleton Key’s FileMaker Solutions
Skeleton Key develops apps on the FileMaker platform making them easy-to-integrate, easy-to-use, and quick to build and deploy. Our team of experts takes a comprehensive consulting approach to focus on learning how your organization operates. With deeper insights into the way your team works, we’re able to create an ideal solution built around your operations while forming a partnership founded on trust and transparency. We hope you found this content useful and we would love to hear from you if we can be of any further assistance.