Only this pageAll pages
Powered by GitBook
1 of 21

cbMailServices

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Essentials

Loading...

Loading...

Loading...

Advanced

Loading...

Loading...

Loading...

Release History

In this section you will find the release notes for each version we release under this major version. If you are looking for the release notes of previous major versions use the version switcher at the top left of this documentation book. Here is a breakdown of our major version releases.

Version 2.0

Version is a major rewrite of this entire module to push it into modern land! It has been rewritten to allow for more fluent and modern syntax, more protocols, and asynchronous capabilities.

Version 1.0

Our first release as a module decoupled from the ColdBox 2 days!

What's New With 2.7.x

January 16, 2023

[v2.7.1] => 2023-FEB-14

Fixed

Fix usage of invalid named member function #33 (https://github.com/coldbox-modules/cbmailservices/pull/33)

[v2.7.0] => 2023-JAN-16

A big thanks to @richardherbert for all the updates in this release.

Fixed

  • FIXED var scoping of attachments variable

  • Updated to handle a response that is not JSON

  • 🐛 FIX: Update GHA to avoid deprecated syntax

Added

  • Added test for MAILGUN_BASEURL property

  • Updated to make MAILGUN_APIURL optional

  • Added support for Mailgun EU region by making MAILGUN_APIURL an optional property with https://api.mailgun.net/v3/ as the default.

Changed

  • Updated all GHA actions to the latest versions and moved to use temurin Java distributions due to deprecation of the service.

Introduction

cbMailServices is a module to send email in a fluent and abstracted approach.

Welcome to the ColdBox Mail Services

Sending emails doesn't have to be complicated or archaic. The ColdBox Mail Services (cbmailservices) module will allow you to send emails in a fluent and abstract way in multiple protocols for many environments in a single cohesive API. The supported protocols are:

  • CFMail - Traditional cfmail sending

  • File - Write emails to disk

  • InMemory - Store email mementos in an array. Perfect for testing.

  • Null - Ignores emails sent to it.

  • Postmark - Send via the PostMark API Service ()

  • Mailgun - Send via the MailGun API Service ()

It also sports tons of useful features for mail sending:

  • Async Mail

  • Mail Queues

  • Mail merging of variables

  • Mail attachments, headers, and parameters

System Requirements

  • Lucee 5+

  • Adobe ColdFusion 2018+

Versioning

cbMailServices is maintained under the guidelines as much as possible. Releases will be numbered in the following format:

And constructed with the following guidelines:

  • Breaking backward compatibility bumps the major (and resets the minor and patch)

  • New additions without breaking backward compatibility bumps the minor (and resets the patch)

  • Bug fixes and misc changes bumps the patch

License

Apache 2 License: ​

Important Links

  • Code: ​

  • Issues: ​

  • Community: ​

Professional Open Source

This module is professional open-source software backed by offering services like:

  • Custom Development

  • Professional Support & Mentoring

  • Training

  • Server Tuning

HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

"Therefore being justified by faith, we have peace with God through our Lord Jesus Christ: By whom also we have access by faith into this grace wherein we stand, and rejoice in hope of the glory of God." Romans 5:5

View and Layout+View rendering for mail

  • Mail Tracking

  • Multiple mailers

  • Success and Error callbacks

  • Mailable@cbmailservices delegate for adding mailing traits to objects.

  • So Much More!

  • Security Hardening

  • Code Reviews

  • Much More

  • https://postmarkapp.com/
    https://www.mailgun.com/
    Semantic Versioning
    http://www.apache.org/licenses/LICENSE-2.0
    https://github.com/coldbox-modules/cbmailservices
    https://ortussolutions.atlassian.net/browse/BOX
    https://community.ortussolutions.com/
    Ortus Solutions, Corp
    www.ortussolutions.com
    newMail( 
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html", // Can be plain, html, or text
    	bodyTokens : { 
    		user    : "Luis", 
    		product : "ColdBox", 
    		link    : event.buildLink( 'home' )
    	}
    )
    .setBody("
        <p>Dear @user@,</p>
        <p>Thank you for downloading @product@, have a great day!</p>
        <p><a href='@link@'>@link@</a></p> 
    ")
    .addAttachment( expandPath( "/tmp/reports/report.pdf" ) )
    .setReadReceipt( "[email protected]" )
    .send()
    .onSuccess( function( result, mail ){
    	// Process the success
    })
    .onError( function( result, mail ){
    	// Process the error
    });
    <major>.<minor>.<patch>

    What's New With 2.6

    November 15, 2022

    Added

    • New ColdBox 7 delegate Mailable@cbmailservices so you can easily add mailing capabilities to objects

    What's New With 2.1.0

    May 17, 2022

    Added

    • Ability for the preMailSend event to influence the mail record thanks to @gpickin

    • Getters only work if there is a variables.config key in existence. Add reasonable defaults for commonly accessed mail fields

    • New module setting: runQueueTask which is defaulted to true. If false it will not run the mail queue task in the background

    Installation

    Leverage to install into your ColdBox app:

    This will install the module in your application so you can it and . By default, it will register a mixin helper called newMail() and a WireBox ID: MailService@cbmailservices which you can inject into your models to send mail.

    It will register a default mailer that uses the cfmail protocol. You can find all of the API Docs here:

    What's New With 2.8.0

    September 13, 2023

    Added

    • Github Support Files

    • Github Action Updates

    ColdBox 7 Auto Testing

  • New start:fakemail command to start FakeSMTP for testing

  • Addded fake smtp server for testing on the harness

  • Skipping of parsing tokens if the mail type is template to avoid complex data in the send-grip protocol https://github.com/coldbox-modules/cbmailservices/pull/34

  • What's New With 2.4.0

    August 20, 2022

    Modified

    • Updated injections to generic box instead of coldbox.

    box install cbmailservices
    CommandBox
    configure
    use it

    What's New With 2.3.x

    August 04, 2022

    [v2.3.1] => 2022-AUG-04

    Fixed

    Fix github action


    [v2.3.0] => 2022-AUG-04

    Fixed

    • Fixed build process so it doesn't include box.bin in the final artifact.

    What's New With 2.5.x

    [v2.5.1] => 2022-NOV-1

    Fixed

    • Fixing asset version

    [v2.5.0] => 2022-OCT-19

    Modified

    • More updates of injections to generic box instead of coldbox

    Async Mail

    The module allows you to either send mail asynchronously or queue it in an in-memory queue so it can be delivered by the mail services scheduler. So let's explore the asynchronous nature of cbmailservices.

    Async Mail

    You can easily send mail asynchronously via the ColdBox Async Manager using the sendAsync() method. This will return to you a ColdBox Future object, which then you can use to setup an async pipeline to p

    newMail( 
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    	bodyTokens : { 
    		user    : "Luis", 
    		product : "ColdBox", 
    		link    : event.buildLink( 'home' )
    	}
    )
    .setBody("
        <p>Dear @user@,</p>
        <p>Thank you for downloading @product@, have a great day!</p>
        <p><a href='@link@'>@link@</a></p> 
    ")
    .sendAsync()
    .then( function( mail ){
    	// Async pipeline that can process the mail once it is sent.
    
    })

    Mail Queue

    You can also detach the mail and let the cbmailservices Mail Queue send it for you. The module's mail scheduler runs on a one-minute interval and will send any mail found in the processing queue. All you need to do is use the queue() method and be done!

    The queuemethod will return back a task ID guid, which you can use to track the task down in your logs or via the Mail Service.

    The mail scheduler is on by default for convenience but is only needed when using the asynchronous mail feature. It can be turned off, if desired, by these steps:

    1. Open config/coldbox.cfc

    2. In the modulesSettings section, add a key for cbmailServices with the property runQueueTask set to false. See the section for more details.

    Author

    Luis Fernando Majano Lainez

    Luis F. Majano

    Luis Majano is a Computer Engineer that has been developing and designing software systems since the year 2000. He was born in San Salvador, El Salvador in the late 70’s, during a period of economical instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelors of Science in Computer Engineering at Florida International University. Luis resides in Houston, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!

    He is the CEO of Ortus Solutions, a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything “BOX”, and contributes to many open source ColdFusion/Java projects. You can read his blog at

    Luis has a passion for Jesus, tennis, golf, volleyball and anything electronic. Random Author Facts:

    • He played volleyball in the Salvadorean National Team at the tender age of 17

    • The Lord of the Rings and The Hobbit is something he reads every 5 years. (Geek!)

    • His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)

    Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!

    “Trust in the LORD with all your heart, and do not lean on your own understanding.” Proverbs 3:5

    About This Book

    The source code for this book is hosted in GitHub:

    You can freely contribute to it and submit pull requests. The contents of this book are copyrighted by and cannot be altered or reproduced without the author's consent. All content is provided "As-Is" and can be freely distributed.

    • The majority of code examples in this book are done in cfscript.

    • The majority of code generation and running of examples are done via CommandBox: The ColdFusion (CFML) CLI, Package Manager, REPL -

    He has a geek love for circuits, microcontrollers and overall embedded systems.
  • He has of late (during old age) become a fan of organic gardening.

  • www.luismajano.com
    ​

    External Trademarks & Copyrights

    Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.

    Notice of Liability

    The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software, and resources described in it.

    Contributing

    We highly encourage contributions to this book and our open-source software. The source code for this book can be found in our GitHub repository where you can submit pull requests.

    Charitable Proceeds

    10% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - https://www.harvesting.org/. So please donate and purchase the printed version of this book, every book sold can help a child for almost 2 months.

    Shalom Children's Home

    Shalom Children’s Home is one of the ministries that are dear to our hearts located in El Salvador. During the 12-year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.

    Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education, and life skills training in a Christian environment. The home is supported by a child sponsorship program.

    We have personally supported Shalom for over 6 years now; it is a place of blessing for many children in El Salvador who either have no families or have been abandoned. This is a good earth to seed and plant.

    Ortus Solutions, Corp
    https://www.ortussolutions.com/products/commandbox
    var mailId = newMail( 
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    	bodyTokens : { 
    		user    : "Luis", 
    		product : "ColdBox", 
    		link    : event.buildLink( 'home' )
    	}
    )
    .setBody("
        <p>Dear @user@,</p>
        <p>Thank you for downloading @product@, have a great day!</p>
        <p><a href='@link@'>@link@</a></p> 
    ")
    .queue();
    Configuration

    Building Protocols

    If you want to build your own protocol you will have to do the following

    1. Create a CFC that inherits from cbmailservices.models.AbstractProtocol

    2. Create the init() and send() methods

    3. Give your protocol a name in the init() via the variables.name variable.

    4. Register it in the mailers section of the

    Here are the method signatures of the two methods to implement:

    That's it!

    What's New With 2.2.0

    June 15 2022

    New Features and Improvements

    Let’s investigate the new features and improvements.

    PreMailSend

    • Ability for the preMailSend event to influence the mail record thanks to @gpickin

    New Module Setting: runQueueTask

    • This setting is defaulted to true.

      • If false it will not run the mail queue task in the background

    Mailgun Mailer Protocol

    You can now register a MailGun protocols by using its alias:

    moduleSettings = {
    	cbmailServices : {
    		runQueueTask: false
    	}
    }
    /**
     * Constructor
     *
     * @properties The protocol properties to instantiate
     */
    function init( struct properties = {} ){
    	variables.properties = arguments.properties;
    	variables.name = "MyProtocol";
    	return this;
    }
    
    /**
     * Implemented by concrete protocols to send a message.
     *
     * The return is a struct with a minimum of the following two keys
     * - `error` - A boolean flag if the message was sent or not
     * - `messages` - An array of messages the protocol stored if any when sending the payload
     *
     * @payload The paylod object to send the message with
     * @payload.doc_generic cbmailservices.models.Mail
     *
     * @return struct of { "error" : boolean, "messages" : [] }
     */
    struct function send( required cbmailservices.models.Mail payload ){
    
    }
    configuration
    moduleSettings = {
    	cbMailservices : {
    		defaultProtocol : "default",
    		mailers : {
    			"default" : { class : "CFmail" },
    			"memory" : { class : "InMemory" },
    			"mailgun" = {
    				class = "Mailgun",
    				// Required properties
    				properties = {
    					ApiKey  = '123',
    					domain  = 'mg.somedomain.com'
    				}
    			}
    		}
    	}
    }

    Mail Events

    The module will register two interception points. PreMailSend and PostMailSend. These interception points are useful to alter the mail object before it gets sent out, and/or perform any functions after the mail gets sent out. An example interceptor would be:

    preMailSend

    Announced before the mail payload is sent to the chosen mailer protocol for sending. This is your last change to influence the payload.

    Data Passed

    Key
    Type
    Description

    postMailSend

    Announced after the mail payload has been sent via the mailer protocol of choice.

    Data Passed

    Key
    Type
    Description
    component extends="coldbox.system.Interceptor"{
    
        void function configure(){
        }
    
        function preMailSend( event, data, buffer, rc, prc ){
            var environment = getSetting('environment');
            var appName = getSetting('appName');
    
            if(environment eq 'development'){
                //change recipient if we are on development
                data.mail.setTo('[email protected]');  
                //prefix the subject if we are on development
                data.mail.setSubject('<DEV-#appName#> #data.mail.getSubject()#');
            }       
        }
    
        function postMailSend( event, data, buffer, rc, prc ){
            if( data.result.error ){
                //log mail failure here...
            }
        }
    
    }

    mail

    Mail

    The mail payload object

    mail

    Mail

    The mail payload object

    result

    struct

    The result structure from the mailer protocol. At most it will contain an error boolean key and a messages array.

    What's New With 2.0.0

    November 2021

    cbMailServices has been rewritten from the ground up for the 2.x release. It was about time to add some 💕 and modernize it. Please note that this is a major upgrade and it WILL require some changes on your configuration and usage. We have documented all the changes for you to provide for a smooth transition.

    Compatibility Changes

    The following are the changes you will need to do to upgrade to version 2.x.

    Adobe 2016 Support Dropped

    It’s too old and too cumbersome to support now. So upgrade to a supported engine.

    MailSettingsBean Dropped

    This CFC was unnecessary and dropped in favor of encapsulation in the MailService

    Configuration Changes

    You will have to place the configuration in the standard ColdBox approach now of moduleSettings.cbmailservices in the config/coldbox.cfc configuration file instead of the top level mailServices struct.

    No More Top Level Mail Settings

    In the previous version you would put any payload mail default settings as a top-level key under the mailServices struct. Now you will use the defaults struct instead.

    Default Protocol

    In 2.x you can define multiple mailers in an application. So the previous protocol struct is now removed. You will have to register the protocol by name in the mailers struct and add a defaultProtocol key which points to the one you define in the mailers.

    If no defaultProtocol is added and no mailers then the mail services module will register a cfmail protocol for you as the default mailer.

    Mail bean returned from send() method

    Previous a struct containing error and errorArray would be returned from the send() method. Now, the Mail bean is returned (whether using mail.send() or mailService.send( mail )). The previously available struct can be accessed using mail.getResults(). (Be sure to see the .)

    No More errorArray

    The return struct from the mail services has been modified. The errorArray has been renamed to messages. Which is still an array but can be used by any protocol to register an array of messages about the mailing for any status.

    Mail config() renamed to configure()

    The mail payload config() method was renamed to configure()

    Postmark message_id renamed to messageId

    The return message identifier from postmark has been renamed from message_id to messageID to be consistent with the postmark API results.


    New Features and Improvements

    Let’s investigate now the new features and improvements.

    newMail() Helper

    The module now registers several new mixin helpers. You can now use newMail() in any handler, and interceptor to start a fluent mailing.

    Mailer Aliases

    You can now register your mailer protocols by using their alias instead of the full CFC path:

    • CFMail

    • File

    • InMemory

    • Null

    Mailer WireBox ID

    You can now also register ANY WireBox ID or class path as the mailer as well. This will allow you to register mailers that come from your application or any other module.

    Protocol Names

    All protocols now have a name property that can be used to give a human readable name for all protocols.

    Fluent Mail

    The mail payload object has been completely rewritten to allow you to use it to not only construct a mail payload, but to do it in a fluent and more approachable manner. It also allows you to send the payload itself without using the mail service. It also sports a dynamic getter/setter approach for any property stored in the internal config structure. This structure is used to model all the mail settings and properties that will be used to send mail through any protocol.

    Success - Errors Callback

    The send() method will return itself so you can interact with the payload for either success or failures. You will do so using the following methods:

    • OnError( callback )

    • OnSuccess ( callback )

    Utility Methods

    The following utility methods can be used for inspecting results and errors.

    • getResults() : struct. Empty if no results

    • hasErrors() : boolean. False if no results

    • getResultMessages() : array. Empty if no results

    Multiple Transmission Mailer Protocols

    The configuration allows for a mailers structure where you can register extra named mailer protocols. You can then use them by name in your mail payloads and set the defaultProtocol as well by it's name.

    You can also seed the mailer name in the payload using the setMailer() method to register the name of the mailer to use for the payload or use the mailer configuration key.

    View Rendering

    Allow for the payload to render a view as the body for you instead of doing this manually using the setView() method.

    This will tell the mail payload to render the view with or without the layout, pass in the args into the view and layout as the body of the mailing. If you don't pass a layout by convention we will just render the view in isolation.

    Async Sending

    Thanks to ColdBox futures you can now send the mailing asynchronously via the sendAsync() method. The return is a ColdBox Future object.

    In Memory Mail Queue

    The mail services module will also register a mail scheduler that will iterate and send mail payload asynchronously. The scheduler runs every minute and iterates and sends all mail in the queue. This allows for your application to not wait and block until mail is sent.

    All you need to do is use the queue() method. That’s it. The mail services schedule will deliver the mail payload to the right mailer asynchronously and at least every minute schedule.

    Please note that we are in async land, so you won’t be able to process successes or failures. The scheduler will log all activity to the applications logging facilities for either a success or failed mailing. The return of the queue() method is a task ID guid which you can use to track in log statements.

    Postmark

    changes to the errorArray name below
    moduleSettings = {
    	cbMailservices : {
    
    	}
    };
    cbmailservices : { 
      tokenMarker : "@",
      defaults : {
        from : "[email protected]",
        cc : "[email protected]",
        server : "myserver"
      }
    }
    cbmailservices : {
      defaultProtocol : "cfmail",
      mailers : {
        "files" : { class : "File" },
        "cfmail" : { class : "CFMail" }
      }
    }
    mailService
    	.newMail()
    	.configure(
    		from    = "[email protected]",
    		to      = "[email protected]",
    		subject = "Mail With Params - Hello Luis"
    	)
    function save( event, rc, prc ){
    	...
    
    	newMail( to: "[email protected]", subject : "Hello" )
    		.setBody( "hello body" )
    		.send();
    }
    moduleSettings = {
    	cbMailservices : {
    		defaultProtocol : "default",
    		mailers : {
    			"default" : { class : "CFmail" },
    			"memory" : { class : "InMemory" }
    		}
    	}
    }
    moduleSettings = {
    	cbMailservices : {
    		defaultProtocol : "default",
    		mailers : {
    			"default" : { class : "CFmail" },
    			"amazon" : { class : "Mailer@amazonsns" }
    		}
    	}
    }
    /**
     * Initialize the InMemory protocol
     *
     * @properties A map of configuration properties for the protocol
     */
    InMemoryProtocol function init( struct properties = {} ){
    
    	variables.name = "InMemory";
    
    	super.init( argumentCollection = arguments );
    	variables.mail = [];
    	return this;
    }
    mailService
    	.newMail()
    	.configure(
    		from    = "[email protected]",
    		to      = "[email protected]",
    		subject = "Mail With Params - Hello Luis"
    	)
    	.setBody( "Hello This is my great unit test" )
    	.addMailParam(
    		name  = "Disposition-Notification-To",
    		value = "[email protected]"
    	)
    	.addMailParam( name = "Importance", value = "High" )
    	.send()
      .onSuccess ( () => {
    
      } )
      .onError( () => {
      } );
    newMail( to: "[email protected]" )
    .setSubject( "This is my email confirmation" )
    .setBody( "You got in buddy!" )
    .send()
      .onSuccess ( () => {
    
      } )
      .onError( () = > {
      } );
    cbMailservices : {
    	// Default Token marker
    	tokenMarker : "@",
    
    	// Default protocol
    	defaultProtocol : "file",
    
    	// Mailers
    	mailers : {
    		file : { class: "", properties : {} },
    		postmark : { class: "", properties : {} },
    		amazon : { class: "", properties : {} }
    	},
    
      ...
    
    }
    // Using constructor
    newMail( mailer : "amazon" )
    
    // Using setter
    newMail()
    	.setMailer( "amazon" )
    newMail()
    .setView(
    	view   : "View",
    	module : "view module",
    	layout : "layout",
    	layoutModule : "layout module",
    	args   : {}
    )
    future = newMail()
     .setView( "report" )
     .sendAsync()
    var taskId = newMail()
     ...
     .queue();

    Sending Mail

    Up up and away!

    You can initiate a mail payload via the mixin helper (newMail()) or via the injected mail service's newMail() method. The arguments you pass into this method will be used to seed the payload with all the arguments passed to the cfmail tag or the chosen protocol properties. You can also pass an optional mailer argument that will override the default protocol to one of your likings.

    Helper

    The newMail() helper is useful so you can send mail from your handlers and interceptors.

    Please note that the mixin helper can ONLY be used in handlers, interceptors, layouts and views. You will need to use the delegater if you want to send mail from your models.

    Delegate

    If you are using ColdBox 7 you can use the Mailable@cbMailservices delegate to add mailing capabilities to ANY model managed by WireBox. It will add the newMail() method to your objects:

    MailService

    Use the WireBox ID of MailService@cbmailservices to inject the service in any model object to send mail from your models.

    Mail Payload

    The return of the newMail() calls will be a Mail payload object of type cbmailservices.models.Mail. You can find all the full API Docs here:

    This object will be used to set properties that the mail protocols can use to send mail. We also have several utility methods that can be used to set mail headers, attachments, read receipts, send receipts and so much more. Let's start investigating the Mail Payload Object.

    Constructor

    The newMail() or configure() method is used to initiate and configure a mail payload. Any argument you pass into these methods will be used to seed the mail config property which is used by all protocols to send email out. Example, the cfmail protocol will read all those properties and pass them as an attribute collection to the cfmail tag.

    Send()

    You will leverage the send() method to initiate a call to the mail protocols to deliver your mail using your payload. You can then tap into the results of the mailing via the mail or the . Please also note that the sending operation points (preMailSend, postMailSend) that you can use to influence the mail payload or listen to mail results.

    Callbacks

    The mail payload allows you to register two callbacks to determine what happened to the mail payload when sending:

    • onSuccess( callback )

    • onError( callback )

    Each callback argument is a function/closure/lambda that receives two arguments:

    • result : The result structure with at least two keys: { error :boolean, messages: array }

    • mail : The mail payload itself.

    Changing Mailers

    You can easily change to use a specific mailer protocol by specifying the mailer argument to the newMail() calls or by calling the setMailer( mailer ) method.

    Body Tokens

    The mail service allows you to register a structure of tokens that can be replaced by key name on the body content for you. The tokens are demarcated by the tokenMarker setting which defaults to @. Here is the token pattern:

    Before sending the mail, the service will replace all the tokens with the specific key names in your content and then send the mail. You can use the bodyTokens argument to the newMail() or configure() methods, or you can use the setBodyTokens() method.

    Rendering Views

    You can also set the body of the email to be a view or a layout+view combination using the setView() method. Here is the method signature:

    Please note that you can bind your views and layotus with the args structure as well. You can also use the bodyTokens in your views. Then you can use it in your mail sending goodness:

    Mail Attachments

    You can easily add mail attachments using mail params (next section) directly or our fancy helper method called addAttachments().

    Signature

    Here is our method signature:

    The files argument can be a list of file locations or an array of file locations to send.

    Example

    Mail Params

    You can easily add mail parameters (cfmailparam) to a payload so you can attach headers or files to the message by using the addMailParam() method. Please see the https://cfdocs.org/cfmailparam cfmail param docs for more information.

    Signature

    Example

    Mail Parts

    You can also add mail parts via the cfmailpart feature of cfmail (https://cfdocs.org/cfmailpart). This allows you to build multi-parted emails.

    Signature

    Example

    Mail Helper Methods

    We have also registered several methods to help you when sending mail:

    • setReadReceipt( email ) - Set the read receipt email

    • setSendReceipt( email ) - Set the send receipt email

    • setHtml( body ) - Set a multi-part body for html

    Mail Additional Info

    The Mail object has some additional methods to allow you to pass additional information so protocols can leverage them:

    setText( body ) - Set a multi-part body for text

  • addAttachments( files, remove=false) - Easily add attachments

  • getMemento() - Get the entire mail settings for the payload

  • hasErrors():boolean - Verifies if there are any errors in the mailing

  • getResultMessages():array - Get's the array of messages of the sending of the mail

  • getResults():struct - Get the structure of the results of sending the mail

  • callbacks
    mail helper methods
    announces two interceptions
    // Mixin Helper Approach
    newMail(
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html", // Can be plain, html, or text
    	bodyTokens : {
    		user    : "Luis",
    		product : "ColdBox",
    		link    : event.buildLink( 'home' )
    	}
    )
    .setBody("
        <p>Dear @user@,</p>
        <p>Thank you for downloading @product@, have a great day!</p>
        <p><a href='@link@'>@link@</a></p>
    ")
    .send()
    .onSuccess( function( result, mail ){
    	// Process the success
    })
    .onError( function( result, mail ){
    	// Process the error
    });
    component name="UserService" delegates="Mailable@cbMailservices"{
    
      ...
        newMail()
          .send();
    
    }
    component{
    
    	property name="mailService" inject="MailService@cbmailservices";
    
    	...
    
    	function submitOrder( required order ){
    
    		...
    
    		variables.mailService
    		.newMail(
    			to         : "[email protected]",
    			from       : "[email protected]",
    			subject    : "Mail Services Rock",
    			type       : "html",
    			bodyTokens : {
    				user    : "Luis",
    				product : "ColdBox",
    				link    : event.buildLink( 'home' )
    			}
    		)
    		.setBody("
    			<p>Dear @user@,</p>
    			<p>Thank you for downloading @product@, have a great day!</p>
    			<p><a href='@link@'>@link@</a></p>
    		")
    		.send()
    		.onSuccess( function( result, mail ){
    			// Process the success
    		})
    		.onError( function( result, mail ){
    			// Process the error
    		});
    
    	}
    
    }
    variables.mailService
    .newMail(
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    	bodyTokens : {
    		user    : "Luis",
    		product : "ColdBox",
    		link    : event.buildLink( 'home' )
    	}
    )
    
    newMail()
    .configure(
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    	bodyTokens : {
    		user    : "Luis",
    		product : "ColdBox",
    		link    : event.buildLink( 'home' )
    	}
    )
    .send()
    	.onSuccess( function( result, mail ){
    		// Process the success
    	})
    	.onError( function( result, mail ){
    		// Process the error
    	});
    newMail( mailer : "files" ),,,
    
    
    newMail()
    	.setMailer( "files" )
    @tokenName@
    // Via constructor
    newMail(
    	to         : "[email protected]",
    	from       : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    	bodyTokens : {
    		user    : "Luis",
    		product : "ColdBox",
    		link    : event.buildLink( 'home' )
    	}
    )
    .setBody("
    	<p>Dear @user@,</p>
    	<p>Thank you for downloading @product@, have a great day!</p>
    	<p><a href='@link@'>@link@</a></p>
    ")
    .send()
    
    // Body Tokens Method
    newMail(
    	to         : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    )
    .setBodyTokens( {
    	user    : "Luis",
    	product : "ColdBox",
    	link    : event.buildLink( 'home' )
    })
    .setBody("
    	<p>Dear @user@,</p>
    	<p>Thank you for downloading @product@, have a great day!</p>
    	<p><a href='@link@'>@link@</a></p>
    ")
    .send()
    /**
     * Render or a view layout combination as the body for this email.  If you use this, the `type`
     * of the email will be set to `html` as well.  You can also bind the view/layout with
     * the args struct and use them accordingly.  You can also use body tokens that the service will
     * replace for you at runtime.
     *
     * @view The view to render as the body
     * @args The structure of arguments to bind the view/layout with
     * @module Optional, the module the view is located in
     * @layout Optional, If passed, we will render the view in this layout
     * @layoutModule Optional, If passed, the module the layout is in
     */
    Mail function setView(
    	required view,
    	struct args = {},
    	module      = "",
    	layout,
    	layoutModule = ""
    )
    newMail(
    	to         : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    )
    .setBodyTokens( {
    	user    : "Luis",
    	product : "ColdBox",
    	link    : event.buildLink( 'home' )
    })
    .setView( view : "emails/newUser" )
    .send()
    
    newMail(
    	to         : "[email protected]",
    	subject    : "Mail Services Rock",
    	type       : "html",
    )
    .setView( view : "emails/newUser", layout : "emails" )
    .send()
    /**
     * Add attachment(s) to this payload using a list or array of file locations
     *
     * @files A list or array of files to attach to this payload
     * @remove If true, ColdFusion removes attachment files (if any) after the mail is successfully delivered.
     */
    Mail function addAttachments( required files, boolean remove = false )
    newMail(
    	subject = "Hello",
    	from    = "[email protected]",
    	to      = "[email protected]",
    	body    = "Here are your docs"
    )
    .addAttachments( "c:\temp\reports\report.pdf", true )
    .addAttachments( expandpath( "/reports/anotherReport.pdf" ), true )
    .addAttachments( [
    	expandPath( "/logs/maillog.txt" )
    	expandPath( "/logs/maillog2.txt" )
    ], true )
    .send();
    /**
     * Attach a file or adss a header to the email payload
     *
     * @contentID The Identifier for the attached file.
     * @disposition How the attached file is to be handled: attachment, inline
     * @file Attaches file to a message. Mutually exclusive with name argument.
     * @type The MIME media type for the attachment.
     * @name The name of the email header to attach. See https://cfdocs.org/cfmailparam. Mututally exclusive with file
     * @value The value of the header
     * @remove Tells ColdFusion to remove any attachments after sucdcesful mail delivery
     * @content Lets you send the contents of a ColdFusion variable as an attachment
     */
    Mail function addMailParam(
    	contentID,
    	disposition,
    	file,
    	type,
    	name,
    	value,
    	boolean remove,
    	content
    )
    newMail()
    	.configure(
    		from    = "[email protected]",
    		to      = "[email protected]",
    		subject = "Mail With Params - Hello Luis"
    	)
    	.setBody( "Hello This is my great unit test" )
    	.addMailParam(
    		name  = "Disposition-Notification-To",
    		value = "[email protected]"
    	)
    	.addMailParam( name = "Importance", value = "High" )
    	.send();
    /**
     * Add a new mail part to this mail payload
     *
     * @charset The charset of the part, defaults to utf-8
     * @type The valid mime type: text/plain or text/html
     * @wraptext Specifies the maximum line length, in characters of the mail text.
     * @type The MIME media type for the attachment.
     * @body The body of the email according to the type.
     */
    Mail function addMailPart(
    	charset = "utf-8",
    	type,
    	numeric wraptext,
    	body
    ){
    newMail(
    	from    = "[email protected]",
    	to      = "[email protected]",
    	subject = "Mail MultiPart No Params - Hello Luis"
    )
    .addMailPart(
    	type = "text",
    	body = "You are reading this message as plain text, because your mail reader does not handle it."
    )
    .addMailPart( type = "html", body = "<h1>This is the body of the message.</h1>" )
    .send()
    mail.setAdditionalInfo( struct );
    mail.getAdditionalInfo();
    
    mail.setAdditionalInfoItem( key, value );
    mail.getAdditionalInfoItem( key );
    Generated Documentation (cbmailservices v2.8.0)s3.amazonaws.com
    Async Programming | ColdBox HMVC Documentationcoldbox.ortusbooks.com
    Harvesting in Spanish - Evangelism With A Heartharvesting.org
    www.harvesting.org
    Logo
    Mails3.amazonaws.com
    cbmailservices.models.Mail
    Not found
    Logo

    Configuration

    Let's get up and running!

    Application Configuration

    You can configure the module by creating a cbmailservices key under the moduleSettings structure in the config/Coldbox.cfc file or the new ColdBox 7 approach of creating a config/modules/cbmailservices.cfc

    Here, you will configure all the different mailers, default protocol, default sending settings, and more.

    By default, the mail services are configured to send mail via the cfmail tag using a mailer called default.

    TokenMarker

    The tokenMarker is used when doing mail merges with variables. The service will look in the body of the email and do replacements according to the following pattern:

    DefaultProtocol

    The name of the mailer key will be used by default to send mail. The default is called default.

    Mailers

    A structure of mailer protocol registrations by key name. Each mailer is registered with the following pattern:

    Defaults

    A structure of default variables will be seeded into the Mail payload. The protocols then use these as defaults. For example, the CFMail protocol will use all these as defaults to the cfmail tag.

    RunQueueTask

    By default, a task runs every minute to facilitate sending emails asynchronously (non-blocking). Setting runQueueTask to false will override the default, and the task will not run.

    Mail Protocols

    The mail services can send mail via different protocols. The available protocol aliases you can register are:

    • CFMail

    • Null

    • InMemory

    Please note that some of the protocols have property requirements.

    Mailer WireBox ID

    You can also register ANY WireBox ID or classpath as the mailer. This will allow you to register mailers from your application or any other module.

    File
  • Mailgun

  • Postmark

  • moduleSettings = {
        cbmailServices = {
            // The default token Marker Symbol
            tokenMarker     : "@",
            // Default protocol to use, it must be defined in the mailers configuration
            defaultProtocol : "default",
            // Here you can register one or many mailers by name
            mailers         : {
                "default" : { class : "CFMail" },
                "files" : { class:"File", properties : { filePath : "/logs" } },
                "postmark" : { class:"PostMark", properties : { apiKey : "234" } },
                "mailgun" : { class:"Mailgun", properties : {
    				apiKey : "234",
    				domain: 'mailgun.example.com'
    			} }
            },
            // The defaults for all mail config payloads and protocols
            defaults        : {
                from : "[email protected]",
                cc : "[email protected]"
            },
    	//Whether the scheduled task is running or not
    	runQueueTask	: true
        }
    }
    @{key}@
    mailerKey : {
        class : "Alias|wireBoxID|CFCPath",
        properties : {}
    }
    defaultProtocol : "default",
    mailers : {
    	// Default CFMail
    	"default" : {
    		class : "CFMail"
    	},
    
    	// FileProtocol
    	"files" = {
    		class = "File",
    		// Required Properties
    		properties = {
    			filePath = "logs",
    			autoExpand = true
    		}
    	},
    
    	// NullProtocol
    	"null" = {
    		class = "Null",
    		properties = {}
    	},
    
    	// InMemoryProtocol
    	"memory" = {
    		class = "InMemory",
    		properties = {}
    	},
    
    	// PostMark
    	"postmark" = {
    		class = "Postmark",
    		// Required properties
    		properties = {
    			apiKey = "123"
    		}
    	},
    
    	// MailGun
    	"mailgun" = {
    		class = "Mailgun",
    		// Required properties
    		properties = {
    			apiKey  = "123",
    			domain  = "mailgun.example.com",
    			// Optional property, defaults to https://api.mailgun.net/v3/
    			// https://documentation.mailgun.com/en/latest/api-intro.html#base-url-1
    			// https://documentation.mailgun.com/en/latest/api-intro.html#mailgun-regions-1
    			baseURL = "https://api.eu.mailgun.net/v3/" // for the EU region
    		}
    	};
    }
    moduleSettings = {
    	cbMailservices : {
    		defaultProtocol : "default",
    		mailers : {
    			"default" : { class : "CFmail" },
    			// Custom amazon mailer from the amazonsns module
    			"amazon" : { class : "Mailer@amazonsns" }
    		}
    	}
    }