Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
September 13, 2023
cbMailServices is a module to send email in a fluent and abstracted approach.
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:
Fix usage of invalid named member function #33 (https://github.com/coldbox-modules/cbmailservices/pull/33)
A big thanks to @richardherbert for all the updates in this release.
FIXED var scoping of attachments variable
Updated to handle a response that is not JSON
🐛 FIX: Update GHA to avoid deprecated syntax
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.
Updated all GHA actions to the latest versions and moved to use temurin Java distributions due to deprecation of the service.
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 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.
Our first release as a module decoupled from the ColdBox 2 days!
cfmail sendingFile - 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 (https://postmarkapp.com/)
Mailgun - Send via the MailGun API Service (https://www.mailgun.com/)
It also sports tons of useful features for mail sending:
Async Mail
Mail Queues
Mail merging of variables
Mail attachments, headers, and parameters
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!
Lucee 5+
Adobe ColdFusion 2018+
cbMailServices is maintained under the Semantic Versioning 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
Apache 2 License: http://www.apache.org/licenses/LICENSE-2.0
Community: https://community.ortussolutions.com/
This module is professional open-source software backed by Ortus Solutions, Corp offering services like:
Custom Development
Professional Support & Mentoring
Training
Server Tuning
Security Hardening
Code Reviews
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
June 15 2022
Let’s investigate the new features and improvements.
Ability for the preMailSend event to influence the mail record thanks to @gpickin
runQueueTask This setting is defaulted to true.
If false it will not run the mail queue task in the background
You can now register a MailGun protocols by using its alias:
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>moduleSettings = {
cbMailservices : {
defaultProtocol : "default",
mailers : {
"default" : { class : "CFmail" },
"memory" : { class : "InMemory" },
"mailgun" = {
class = "Mailgun",
// Required properties
properties = {
ApiKey = '123',
domain = 'mg.somedomain.com'
}
}
}
}
}May 17, 2022
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
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 -
Fix github action
Fixed build process so it doesn't include box.bin in the final artifact.
Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.
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.
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.
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 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.
Luis Majano is a Computer Engineer that has been developing and designing software systems since the year 2000. He was born in 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 . Luis resides in Houston, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!
He is the CEO of , 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!)
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.
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

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.
The following are the changes you will need to do to upgrade to version 2.x.
It’s too old and too cumbersome to support now. So upgrade to a supported engine.
This CFC was unnecessary and dropped in favor of encapsulation in the MailService
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.
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.
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.
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 .)
errorArrayThe 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.
The mail payload config() method was renamed to configure()
message_id renamed to messageIdThe return message identifier from postmark has been renamed from message_id to messageID to be consistent with the postmark API results.
Let’s investigate now the new features and improvements.
The module now registers several new mixin helpers. You can now use newMail() in any handler, and interceptor to start a fluent mailing.
You can now register your mailer protocols by using their alias instead of the full CFC path:
CFMail
File
InMemory
Null
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.
All protocols now have a name property that can be used to give a human readable name for all protocols.
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.
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 )
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
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.
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.
Thanks to ColdBox futures you can now send the mailing asynchronously via the sendAsync() method. The return is a ColdBox Future object.
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
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();