Skip to content
Wheels Email Generator logo

Wheels Email Generator

Generate email functionality including mailer controllers, email templates, and configuration. Use when sending emails, creating notifications, or implementing transactional emails. Ensures proper email structure, layouts, and testing.

mattnigh/skills_collection0installs24stars

SKILL.md

Full skill instructions

Wheels Email Generator

When to Use This Skill

Activate automatically when:

  • User wants to send emails
  • User mentions: email, mailer, sendMail, notification
  • User needs password reset emails
  • User wants welcome emails or transactional emails
  • User asks about email templates or configuration

Email Directory Structure

/​app/
├── controllers/
│   └── Mailer.cfc              # Email controller
├── views/
│   └── mailer/                 # Email templates
│       ├── layouts/
│       │   ├── email.cfm       # HTML layout
│       │   └── email.txt.cfm   # Plain text layout
│       ├── welcome.cfm         # HTML version
│       ├── welcome.txt.cfm     # Text version
│       ├── resetPassword.cfm
│       └── resetPassword.txt.cfm
└── /​config/
    └── settings.cfm            # Email configuration

Mailer Controller Template

component extends="Controller" {

    function config() {
        // Configure email defaults
        set(
            functionName = "sendEmail",
            from = "[email protected]",
            layout = "email",
            detectMultipart = true
        );
    }

    /​**
     * Send welcome email to new user
     */
    function welcome(required user) {
        sendEmail(
            to = arguments.user.email,
            subject = "Welcome to Our App!",
            template = "mailer/​welcome",
            user = arguments.user
        );
    }

    /​**
     * Send password reset email
     */
    function resetPassword(required user, required token) {
        local.resetUrl = URLFor(
            route = "passwordReset",
            token = arguments.token,
            onlyPath = false
        );

        sendEmail(
            to = arguments.user.email,
            subject = "Reset Your Password",
            template = "mailer/​resetPassword",
            user = arguments.user,
            resetUrl = local.resetUrl
        );
    }

    /​**
     * Send order confirmation email
     */
    function orderConfirmation(required order) {
        sendEmail(
            to = arguments.order.customerEmail,
            subject = "Order Confirmation - ##" & arguments.order.id,
            template = "mailer/​orderConfirmation",
            order = arguments.order
        );
    }

    /​**
     * Send notification to admin
     */
    function adminNotification(required subject, required message) {
        sendEmail(
            to = application.adminEmail,
            subject = arguments.subject,
            template = "mailer/​adminNotification",
            message = arguments.message
        );
    }

}

Email Layout (HTML) - views/​mailer/​layouts/​email.cfm

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            color: ##333;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }
        .header {
            background: ##007bff;
            color: white;
            padding: 20px;
            text-align: center;
        }
        .content {
            background: ##f9f9f9;
            padding: 30px;
            border: 1px solid ##ddd;
        }
        .button {
            display: inline-block;
            padding: 12px 24px;
            background: ##007bff;
            color: white;
            text-decoration: none;
            border-radius: 4px;
            margin: 20px 0;
        }
        .footer {
            text-align: center;
            padding: 20px;
            color: ##666;
            font-size: 12px;
        }
    </​style>
</​head>
<body>
    <div class="header">
        <h1>Your App Name</​h1>
    </​div>

    <div class="content">
        <cfoutput>##contentForLayout()##</​cfoutput>
    </​div>

    <div class="footer">
        <p>&copy; #Year(Now())# Your Company. All rights reserved.</​p>
        <p>
            <a href="##">Unsubscribe</​a> |
            <a href="##">Privacy Policy</​a> |
            <a href="##">Contact Us</​a>
        </​p>
    </​div>
</​body>
</​html>

Email Layout (Plain Text) - views/​mailer/​layouts/​email.txt.cfm

<cfoutput>
========================================
YOUR APP NAME
========================================

##contentForLayout()##

========================================
© #Year(Now())# Your Company
All rights reserved.

Unsubscribe: [URL]
Privacy: [URL]
========================================
</​cfoutput>

Email Template Examples

Welcome Email (HTML) - views/​mailer/​welcome.cfm

<cfparam name="user">
<cfoutput>

<h2>Welcome, ##user.firstName##!</​h2>

<p>Thank you for joining our community. We're excited to have you on board.</​p>

<p>Here's what you can do next:</​p>

<ul>
    <li>Complete your profile</​li>
    <li>Explore our features</​li>
    <li>Connect with other users</​li>
</​ul>

<p>
    <a href="##URLFor(route='dashboard', onlyPath=false)##" class="button">
        Get Started
    </​a>
</​p>

<p>If you have any questions, feel free to reply to this email.</​p>

<p>Best regards,<br>
The Team</​p>

</​cfoutput>

Welcome Email (Plain Text) - views/​mailer/​welcome.txt.cfm

<cfparam name="user">
<cfoutput>
Welcome, ##user.firstName##!

Thank you for joining our community. We're excited to have you on board.

Here's what you can do next:
- Complete your profile
- Explore our features
- Connect with other users

Get Started: ##URLFor(route='dashboard', onlyPath=false)##

If you have any questions, feel free to reply to this email.

Best regards,
The Team
</​cfoutput>

Password Reset Email - views/​mailer/​resetPassword.cfm

<cfparam name="user">
<cfparam name="resetUrl">
<cfoutput>

<h2>Reset Your Password</​h2>

<p>Hi ##user.firstName##,</​p>

<p>We received a request to reset your password. Click the button below to create a new password:</​p>

<p>
    <a href="##resetUrl##" class="button">Reset Password</​a>
</​p>

<p>Or copy and paste this link into your browser:</​p>
<p>##resetUrl##</​p>

<p><strong>This link will expire in 24 hours.</​strong></​p>

<p>If you didn't request a password reset, you can safely ignore this email.</​p>

<p>Thanks,<br>
The Security Team</​p>

</​cfoutput>

Email Configuration - config/​settings.cfm

<cfscript>
// Email Server Configuration
set(
    functionName = "sendEmail",
    server = "smtp.gmail.com",
    port = 587,
    username = "[email protected]",
    password = "your-app-password",
    useTLS = true,
    useSSL = false,
    from = "[email protected]",
    type = "html",
    charset = "utf-8"
);

// Environment-Specific Email Settings
if (application.wheels.environment == "development") {
    // Log emails instead of sending
    set(functionName = "sendEmail", debug = true, deliver = false);
}

if (application.wheels.environment == "testing") {
    // Send all emails to test account
    set(functionName = "sendEmail", to = "[email protected]");
}

if (application.wheels.environment == "production") {
    // Production settings
    set(
        functionName = "sendEmail",
        server = getEnv("SMTP_SERVER"),
        username = getEnv("SMTP_USERNAME"),
        password = getEnv("SMTP_PASSWORD"),
        deliver = true
    );
}
</​cfscript>

Using the Mailer

In Controllers

component extends="Controller" {

    function create() {
        user = model("User").new(params.user);

        if (user.save()) {
            // Send welcome email
            controller("Mailer").welcome(user);

            redirectTo(route="home", success="Account created! Check your email.");
        } else {
            renderView(action="new");
        }
    }

    function forgotPassword() {
        user = model("User").findOne(where="email='#params.email#'");

        if (isObject(user)) {
            // Generate reset token
            token = createUUID();
            user.update(resetToken=token, resetTokenExpiry=dateAdd("h", 24, now()));

            // Send reset email
            controller("Mailer").resetPassword(user=user, token=token);

            flashInsert(success="Password reset instructions sent to your email.");
        }

        redirectTo(action="login");
    }

}

Direct Usage

// Simple email
sendEmail(
    to = "[email protected]",
    from = "[email protected]",
    subject = "Test Email",
    body = "This is a test email."
);

// Email with template
sendEmail(
    to = "[email protected]",
    subject = "Custom Email",
    template = "mailer/​custom",
    customVariable = "value"
);

// Email with attachments
sendEmail(
    to = "[email protected]",
    subject = "Invoice",
    template = "mailer/​invoice",
    file = expandPath("./​uploads/​invoice.pdf"),
    fileName = "invoice-##123##.pdf"
);

Email with File Attachments

function sendInvoice(required order) {
    local.pdfPath = expandPath("./​temp/​invoice-##arguments.order.id##.pdf");

    // Generate PDF invoice
    generateInvoicePDF(arguments.order, local.pdfPath);

    // Send email with attachment
    sendEmail(
        to = arguments.order.customerEmail,
        subject = "Your Invoice - Order ##arguments.order.id##",
        template = "mailer/​invoice",
        order = arguments.order,
        file = local.pdfPath,
        fileName = "invoice-##arguments.order.id##.pdf"
    );

    // Clean up temp file
    fileDelete(local.pdfPath);
}

Email with Multiple Recipients

function sendNewsletter(required subject, required template) {
    // Get all subscribed users
    subscribers = model("User").findAll(where="subscribed=1");

    // Send to each subscriber
    for (local.subscriber in subscribers) {
        sendEmail(
            to = local.subscriber.email,
            subject = arguments.subject,
            template = arguments.template,
            user = local.subscriber
        );
    }
}

Testing Emails

Email Test

component extends="wheels.Test" {

    function testWelcomeEmailSent() {
        // Create test user
        user = model("User").create(
            email = "[email protected]",
            firstName = "Test"
        );

        // Call mailer
        controller("Mailer").welcome(user);

        // Verify email was queued
        assert("application.wheels.emailQueue.len() > 0");
    }

    function testPasswordResetEmail() {
        user = model("User").findByKey(1);
        token = createUUID();

        controller("Mailer").resetPassword(user=user, token=token);

        // Check email contains reset link
        lastEmail = application.wheels.emailQueue[1];
        assert("findNoCase('reset', lastEmail.body) > 0");
        assert("findNoCase(token, lastEmail.body) > 0");
    }

}

Manual Testing

// Test in browser - add route
.get(name="testEmail", pattern="/​test/​email", to="tests##testEmail")

// Test controller
function testEmail() {
    user = model("User").findByKey(1);
    controller("Mailer").welcome(user);
    renderText("Email sent! Check server logs.");
}

Email Best Practices

✅ DO:

  • Always provide both HTML and plain text versions
  • Use responsive email layouts (max-width: 600px)
  • Include unsubscribe links
  • Test emails across different clients
  • Use descriptive subject lines
  • Handle email failures gracefully
  • Queue emails for bulk sending
  • Use environment-specific settings

❌ DON'T:

  • Send emails synchronously in production
  • Hardcode email addresses
  • Use complex CSS (limited support)
  • Forget error handling
  • Send without user consent
  • Include sensitive data in emails
  • Use JavaScript in emails

Common Email Patterns

1. Transactional Emails

// Order confirmation, password resets, account verification
- Time-sensitive
- User-triggered
- High priority

2. Notification Emails

// Activity updates, mentions, reminders
- Event-driven
- May be batched
- User preferences apply

3. Marketing Emails

// Newsletters, promotions
- Bulk sending
- Unsubscribe required
- Scheduled

Email Queue Pattern

// Queue email for background processing
function queueEmail(required struct emailData) {
    model("EmailQueue").create(
        recipient = arguments.emailData.to,
        subject = arguments.emailData.subject,
        template = arguments.emailData.template,
        data = serializeJSON(arguments.emailData),
        status = "pending"
    );
}

// Process queue (run via scheduled task)
function processEmailQueue() {
    pending = model("EmailQueue").findAll(
        where = "status='pending'",
        order = "createdAt",
        maxRows = 50
    );

    for (local.email in pending) {
        try {
            local.data = deserializeJSON(local.email.data);
            sendEmail(argumentCollection=local.data);
            local.email.update(status="sent", sentAt=now());
        } catch (any e) {
            local.email.update(
                status = "failed",
                errorMessage = e.message
            );
        }
    }
}

SMTP Providers

Gmail

server = "smtp.gmail.com"
port = 587
useTLS = true
// Note: Use app password, not account password

SendGrid

server = "smtp.sendgrid.net"
port = 587
username = "apikey"
password = "YOUR_API_KEY"
useTLS = true

Mailgun

server = "smtp.mailgun.org"
port = 587
username = "[email protected]"
password = "YOUR_PASSWORD"
useTLS = true

AWS SES

server = "email-smtp.us-east-1.amazonaws.com"
port = 587
username = "YOUR_SMTP_USERNAME"
password = "YOUR_SMTP_PASSWORD"
useTLS = true

Related Skills

  • wheels-controller-generator: Create mailer controllers
  • wheels-view-generator: Create email templates
  • wheels-auth-generator: Password reset emails
  • wheels-test-generator: Test email functionality

Generated by: Wheels Email Generator Skill v1.0

More skills from mattnigh

spring-framework-patterns logo
mattnigh/skills_collection

spring-framework-patterns

Comprehensive Spring Framework and Spring Boot best practices including dependency injection patterns, bean lifecycle and scopes, REST API development, Spring Data JPA, service layer design, Spring Security, testing strategies, caching, AOP, async processing, error handling, and common anti-patte...

24 0
View

TypeScript厳格モードによる型安全性設計を専門とするスキル。 📖 参照書籍: - 『Effective TypeScript』(Dan Vanderkam): 型設計 📚 リソース参照: - `resources/Level1_basics.md`: レベル1の基礎ガイド - `resources/Level2_intermediate.md`: レベル2の実務ガイド - `resources/Level3_advanced.md`: レベル3の応用ガイド - `resources/Level4_expert.md`: レベル4の専門ガイド - `resources/di...

24 0
View
deploying-cloud-k8s logo
mattnigh/skills_collection

deploying-cloud-k8s

Deploys applications to cloud Kubernetes (AKS/GKE/DOKS) with CI/CD pipelines. Use when deploying to production, setting up GitHub Actions, troubleshooting deployments. Covers build-time vs runtime vars, architecture matching, and battle-tested debugging.

24 0
View
moai-alfred-agent-guide logo
mattnigh/skills_collection

moai-alfred-agent-guide

19-agent team structure, decision trees for agent selection, Haiku vs Sonnet model selection, and agent collaboration principles. Use when deciding which sub-agent to invoke, understanding team responsibilities, or learning multi-agent orchestration.

24 0
View
mermaid-diagram-generator logo
mattnigh/skills_collection

mermaid-diagram-generator

Converts architecture descriptions, module specs, or workflow docs into Mermaid diagrams. Use when visualizing brick module relationships, workflows (DDD, investigation), or system architecture. Supports: flowcharts, sequence diagrams, class diagrams, state machines, entity relationship diagrams,...

24 0
View
pre-flight-check logo
mattnigh/skills_collection

pre-flight-check

INVOKE FIRST before any code work. Validates git workflow (branch, issue, worklog) and checks approach. Use at START of every task and END before completing. Prevents skipped steps.

24 0
View
browser-dev-tools logo
mattnigh/skills_collection

browser-dev-tools

This skill should be used when working with browser-rendered artifacts (i.e. Bun, React/React Native) to proactively validate that development work on localhost is being built appropriately and to support debugging browser-rendered content. Use this skill after making frontend changes to verify t...

24 0
View
lead-dev logo
mattnigh/skills_collection

lead-dev

Lead Développeur - Coordination technique opérationnelle, code review, mentoring et livraison. Pair de web-dev-process au niveau OPÉRATIONS.

24 0
View
worker-monitor logo
mattnigh/skills_collection

worker-monitor

Monitor Docker workers, RQ queue health, and auto-scale workers (max 4). Use when: checking job progress, monitoring queue depth, scaling workers up/down, diagnosing slow processing, or waiting for jobs to complete. Referenced by data-quality skill during reprocessing.

24 0
View
quality-advisor logo
mattnigh/skills_collection

quality-advisor

Proactive quality guidance system that monitors artifact creation and provides real-time feedback on documentation quality

24 0
View
bump-version logo
mattnigh/skills_collection

bump-version

This skill should be used when the user wants to bump the version number in the workspace. It updates versions across all pyproject.toml files (root, tde, and tda packages) and the CHANGELOG.md to keep them synchronized.

24 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View