Email Outbound Hardening
SMTP configuration and email delivery best practices
Configure ColdFusion mail services with proper authentication, encryption, rate limiting, and error handling to ensure reliable and secure email delivery.
Mail Server Configuration
You should configure mail servers in the ColdFusion Administrator following these security best practices:
- Use a dedicated SMTP relay service instead of attempting direct delivery to recipient mail servers
- Enable STARTTLS or SSL/TLS encryption to protect email content in transit
- Require SMTP authentication to prevent unauthorized use of your mail server
- Store SMTP credentials in an external secrets manager rather than in the Administrator
- Set an appropriate connection timeout between 30-60 seconds to handle network issues gracefully
Example Configuration
// In ColdFusion Administrator > Mail
Mail Server: smtp.sendgrid.net
Port: 587 (STARTTLS) or 465 (SSL)
Username: apikey
Password: <from secrets manager>
Use TLS: Yes
Verify Connection: Yes
Timeout: 60 secondsSecure Email Sending
<cfmail
to="#recipientEmail#"
from="noreply@example.com"
subject="Secure Test Message"
type="html"
usetls="true">
<p>This email was sent securely over TLS</p>
</cfmail>cfmail(
to = recipientEmail,
from = "noreply@example.com",
subject = "Secure Test Message",
type = "html",
useTLS = true
) {
writeOutput("<p>This email was sent securely over TLS</p>");
}Rate Limiting
You must implement rate limiting to avoid overwhelming your SMTP provider and triggering abuse protection:
- Configure mail spooling to queue outbound messages and send them at a controlled rate
- Set spool interval between 15-60 seconds depending on your provider's limits
- Track send success/failure rates and alert on anomalies
- Implement exponential backoff for failed deliveries
Mail Spooling
Spooling separates mail generation from delivery:
- Enable spooling in ColdFusion Administrator under Mail settings
- Configure spool interval appropriately for your volume
- Monitor undelivered mail directory for disk space usage
- Implement a process to handle failed deliveries after retry attempts
<cfmail
to="#recipientEmail#"
from="noreply@example.com"
subject="Spooled Message"
type="html"
spoolEnable="true">
<p>This email will be queued and sent via the spool</p>
</cfmail>cfmail(
to = recipientEmail,
from = "noreply@example.com",
subject = "Spooled Message",
type = "html",
spoolEnable = true
) {
writeOutput("<p>This email will be queued and sent via the spool</p>");
}Error Handling
Proper error handling prevents silent failures:
<cftry>
<cfmail
to="#recipientEmail#"
from="noreply@example.com"
subject="Important Message"
type="html"
usetls="true">
<p>Message content</p>
</cfmail>
<cfcatch type="any">
<cflog
file="email_errors"
type="error"
text="Failed to send email to #recipientEmail#: #cfcatch.message#">
<!--- Implement retry logic or notification --->
</cfcatch>
</cftry>try {
cfmail(
to = recipientEmail,
from = "noreply@example.com",
subject = "Important Message",
type = "html",
useTLS = true
) {
writeOutput("<p>Message content</p>");
}
} catch (any e) {
writeLog(
file = "email_errors",
type = "error",
text = "Failed to send email to #recipientEmail#: #e.message#"
);
// Implement retry logic or notification
}Input Validation
Always validate and sanitize email inputs to prevent header injection attacks:
<cffunction name="validateEmail" returnType="boolean">
<cfargument name="email" type="string" required="true">
<!--- Basic email format validation --->
<cfif NOT isValid("email", arguments.email)>
<cfreturn false>
</cfif>
<!--- Check for header injection attempts --->
<cfif findNoCase(chr(10), arguments.email) OR findNoCase(chr(13), arguments.email)>
<cfreturn false>
</cfif>
<cfreturn true>
</cffunction>
<cfif validateEmail(form.email)>
<cfmail to="#form.email#" from="noreply@example.com" subject="Welcome">
Thank you for signing up!
</cfmail>
<cfelse>
<!--- Log attempt and reject --->
<cflog file="security" type="warning" text="Invalid email attempt: #form.email#">
</cfif>function validateEmail(required string email) {
// Basic email format validation
if (!isValid("email", email)) {
return false;
}
// Check for header injection attempts
if (findNoCase(chr(10), email) || findNoCase(chr(13), email)) {
return false;
}
return true;
}
if (validateEmail(form.email)) {
cfmail(
to = form.email,
from = "noreply@example.com",
subject = "Welcome"
) {
writeOutput("Thank you for signing up!");
}
} else {
// Log attempt and reject
writeLog(
file = "security",
type = "warning",
text = "Invalid email attempt: #form.email#"
);
}DNS Authentication Records
Configure SPF, DKIM, and DMARC records to improve deliverability:
- SPF (Sender Policy Framework): Identifies authorized mail servers for your domain
- DKIM (DomainKeys Identified Mail): Cryptographically signs outbound email
- DMARC (Domain-based Message Authentication): Specifies policy for handling failed authentication
Work with your DNS provider and SMTP relay service to configure these records properly.
Email Security Checklist
- SMTP authentication enabled
- STARTTLS or SSL/TLS encryption configured
- Credentials stored in secrets manager
- Rate limiting implemented
- Mail spooling enabled with retry logic
- Email addresses validated before sending
- SPF, DKIM, DMARC records configured
- Undelivered mail monitored
- Send success/failure rates tracked
Gotchas
- Port 25 blocked: Port 25 often blocked by cloud providers - use 587 or 465
- DNS authentication: Missing SPF/DKIM records causes delivery to spam folders
- Rate limits: Bulk sends without throttling trigger provider rate limits
- Disk space: Unmonitored undelivered mail directory fills disk
- Credential storage: Hard-coded SMTP credentials in code create security vulnerabilities
- Header injection: Header injection in custom headers allows email spoofing
Related Resources
Need Help?
Convective can help configure secure, reliable email delivery for ColdFusion applications.
Find out more