SMTP Extension
CFSMTP opens up a whole new world of possibilities to the CFML developer. In much the same way OpenBD makes building rich web applications for web (HTTP) requests, this plugin opens up the world of email to the CFML community. Just as a page reacts to a request, the CFSMTP invokes a CFC for every email that comes into the server allowing to build rich email applications.
Once you register this listener, this plugin will listen for email delivery on the standard Port25. You have the opportunity to determine if you wish to accept email before the sender transmits the full email body, allowing you to quickly stop spam and unwanted emails. Once you've decided to accept the email, the plugin will ensure delivery and then call your CFC again detailing the email.
You can then process the email, looking at its headers, body, attachments and if you need to send out any email, then you use the standard CFML CFMAIL way of achieving that.
This extension is built-in to the core distribution of OpenBD, no extra download/installation required.
Overview of functions
CFSMTP is setup using a series of functions letting you startup, shutdown and query the status of your CFSMTP endpoint. You can run multiple servers, each on their different interface/port, referencing them using a symbolic name.
Function Name | Description |
---|---|
SmtpStart | Starts up a listening service for incoming emails, calling a CFC in response to all mails |
SmtpStatus | Returns back the stats for this SMTP end point; running, totalmails, totalconnections |
SmtpStop | Stops a running SMTP server. Returns true if it was stopped; false if it wasn't running |
MailRead | Used in conjunction with MailWrite(). This function reads the previously serialized email out to disk |
MailWrite | This function writes the email out to disk for later processing or archiving |
MailDeliver | This function takes the email object and sends it for delivery to a new server, giving you the opportunity to override from, to, cc, bcc and server |
The key to the success of the CFSMTP plugin is in the CFC that is used to process the incoming email. It is this CFC, with the pre-defined methods, that will be called for each stage of the email processing. Remember, these CFC's run as headless requests, which means they are outside of the normal scope of a web request. Therefore operations such as session management, cookie's and CGI scopes are not applicable.
However, the 'request' scope is available and is exclusive per each single transaction. This lets you, for example, put content into it when you are processing one of the onMailFrom() and pick it up again on the onAcceptMail()
Accepting Email
Email delivery is done in 3 stages. First the sender sends who the email is from, then it sends who the email is for, and finally it delivers the email body. Here is a full example using the same CFC for both the cfcmail and cfcfilter options.
<cfcomponent> <cffunction name="onmailfrom" access="public" returntype="boolean"> <cfargument name="email" required="yes"> <cfargument name="ip" required="yes"> <cfreturn true> </cffunction> <cffunction name="onmailto" access="public" returntype="boolean"> <cfargument name="email" required="yes"> <cfargument name="ip" required="yes"> <cfreturn true> </cffunction> <cffunction name="onMailAccept" access="public" returntype="any" output="no"> <cfargument name="mail" required="yes"> </cffunction> </cfcomponent>
onmailfrom / onmailto
If you specify this CFC cfcfilter option then you are given the opportunity to hook into the very start of the email exchange with the remote server. This gives you an opportunity to deny any further exchange with the remote server by returning false. This is a huge benefit when reducing spam and unwanted emails.
onMailAccept
This is the main processing for emails that come in to the server. From here you can work with all aspects of the incoming email, including processing the body and downloading any attachments.
The mail object that is passed in has the following functions to process the mail.
Function Name | Description |
---|---|
getAllBodyParts() | returns Array of ALL Parts including the inner ones |
getBodyParts() | returns Array of Parts; as per email |
getCcList() | returns Array of Structs (name/email) of all the people addressed in the Cc field |
getFromList() | returns Array of Structs (name/email) of all the people addressed in the From field |
getHeaders() | returns Array of all the email headers |
getHeader( string ) | returns the value of the given header |
getIP() | returns the IP address of the delivery agent |
getMessageId() | returns the email message id |
getMailFrom() | returns email address that was in the MAIL FROM |
getReplyToList() | returns Array of Structs (name/email) of all the people addressed in the Reply-To field |
getSentDate() | returns the date the message was sent |
getReceivedDate() | returns the date the message was received |
getRecipients() | returns Array of email addresses; these are the emails to which the email was delivered to via RCPT TO |
getSubject() | returns the email subject |
getSize() | returns the size of the email |
getToList() | returns Array of Structs (name/email) of all the people addressed in the To field |
spoolMailToDir(dir) | saves the mail to disk and returns the full path of the saved file |
Here is an example of extracting out only the plain text part of the email. This method works over MIME type emails as well as plain ones
<cfcomponent> <cfscript> function onMailAccept( mail ){ var body = getBodyFromParts( arguments.mail.getBodyParts(), "text/plain" ); } function getBodyFromParts( parts, mimetype ){ var x=true; var part=true; for ( x=1; x<=ArrayLen( arguments.parts ); x=x+1){ part = arguments.parts[x]; if ( part.isMultiPart() ){ return getBodyFromParts( part.getBodyParts(), arguments.mimetype ); } else if ( part.getContentType().indexOf(arguments.mimetype) != -1 ){ return part.getContent().trim(); } } //No body was found return ""; } </cfscript> </cfcomponent>