cfmail is ColdFusion's core mechanism for sending email, it behaves similarly to cfoutput, except the generated text becomes an SMTP mail message instead of page output. Before getting into cfmail's full attribute set in the next lesson, this one covers how a message actually gets from your code to an inbox.
Learning Objectives
After completing this lesson, you'll be able to:
- Send a basic email with cfmail.
- Configure an SMTP server in the Administrator, or override it inline.
- Explain ColdFusion's spooled delivery architecture, and where a failed delivery ends up.
How a Message Actually Gets Delivered
cfmail Builds the Message
Spooled to Disk
Processed in the Background
Delivered via SMTP
cfmail doesn't send synchronously by default, the message is spooled to disk first so the request doesn't wait on the SMTP round-trip.
A Basic Email
<cfmail to="recipient@example.com" from="sender@example.com" subject="Welcome!">
Thanks for signing up.
</cfmail>cfmail(to = "recipient@example.com", from = "sender@example.com", subject = "Welcome!") {
writeOutput("Thanks for signing up.");
}SMTP Configuration: Administrator vs Inline
ColdFusion Administrator: Server Settings > Mail
cfmail Uses It by Default
Or Override Per-Tag with server/port/username/password
Configuring the SMTP server once in the Administrator keeps individual cfmail calls free of credentials. A cfmail tag's own server attribute overrides that Administrator setting for just that message.
A Real Example: Overriding the SMTP Server Inline
<cfmail
to="recipient@example.com"
from="sender@example.com"
subject="Password Reset"
server="smtp.sendgrid.net"
port="587"
username="apikey"
password="#smtpApiKey#"
useTLS="yes">
Click the link below to reset your password.
</cfmail>When a Delivery Fails
| Detail | Where |
|---|---|
| SMTP errors | Logged to mail.log in the ColdFusion log directory, with timestamps and diagnostic detail |
| The undelivered message itself | Written to \_CFusion_\Mail\Undelivr (Windows) or /opt/_coldfusion_/mail/undelivr (UNIX) |
| Retrying a failed delivery | Move the file from the Undelivr directory back into the Spool directory |
The mail.log entry for a failure includes the filename of the undelivered message, useful for tracing which specific message actually failed.
Common Beginner Mistakes
Assuming cfmail sends synchronously by default
Messages are spooled to disk and processed in the background, exactly to avoid making the request wait on the SMTP round-trip. A busy queue can delay delivery.
Hardcoding SMTP credentials in every cfmail call
Configuring the server once in the Administrator keeps individual calls free of credentials, only override inline when a specific message genuinely needs a different server.
Not knowing where a failed message actually goes
It lands in the Undelivr directory, with the reason logged in mail.log. Moving the file back into the Spool directory retries it.
Best Practices
- Configure SMTP settings once in the Administrator, and reserve inline server/username/password for genuine per-message exceptions.
- Check mail.log first when a message doesn't arrive, it names the specific undelivered file.
- Don't assume a message was actually delivered just because cfmail didn't throw, spooled delivery happens in the background.
Interview Questions
Why doesn't cfmail block the request while the email actually sends?
Messages are spooled to disk and delivered in the background by a separate process, so the request doesn't wait on the SMTP round-trip.
Where does a failed email delivery end up, and how would you retry it?
The message file lands in the Undelivr directory (with the failure logged in mail.log). Moving it back into the Spool directory retries delivery.
How would you send one specific email through a different SMTP server than the one configured in the Administrator?
Set cfmail's own server attribute (along with port/username/password as needed) on that tag, it overrides the Administrator's configuration for just that message.
Summary
In this lesson, you sent a basic email with cfmail, configured SMTP through the Administrator versus overriding it inline, and covered the spooled delivery architecture, where a failed message ends up, and how to retry it.
What's Next?
The next lesson covers cfmail itself in depth: its full attribute set, cfmailparam for attachments and custom headers, cfmailpart for multipart messages, and a real query-driven mail merge.