0
votes

I am writing a custom tag for CFMAIL. I need to handle certain emails differently then the standard CFMAIL. I am using the following post as a staring point - http://www.cfhero.com/2011/11/creating-environment-safe-wrapper-for.html

Before

<cfmail to="[email protected]" from="[email protected]" subject="This is only a test">
<cfmailparam name="Importance" value="high">
hello world</cfmail>

After Custom Tags

<cf_email to="[email protected]" from="[email protected]" subject="This is only a test">
<cf_emailparam name="Importance" value="high">
hello world</cf_email>

Everything working correctly for the custom CFMAIL and CFMAILPARAM but my question is how to handle "CFMAILPART". When using the existing CFMAILPART within the new tags, CF throws an error.

<cf_email to="[email protected]" from="[email protected]" subject="This is only a test">
<cf_emailparam name="Importance" value="high">
    <cfmailpart type="text">Text</cfmailpart>
    <cfmailpart type="html">HTML</cfmailpart></cf_email>

Detail: The tag must be nested inside a cfmail tag.

Message: Context validation error for tag cfmailpart.

I am striking out with my ideas and I am failing finding any help docs. Any help or starting points would most appreciated.

Thanks in advance.

2
What version of ColdFusion are you on? I am seeing that the code is from 2011. This person might have been doing this on CF 9 - James A Mohler
What is the use case for writing a custom tag for cfmail? It doesn't seem like you are really doing anything different. - Scott Stroz
Just say no to custom tags. - Adrian J. Moreno
I am using a custom tag point some CFMAIL to a 3rd party to handle click rates, drops and such. We have have dozens + of instances of CFMAIL, The plan is to move a few to the 3rd party now, then eventually move some more. Not all CFMAIL will be pointed at the 3rd party, that is why I want to use CFMAIL and a CF_EMAIL. - nope_four

2 Answers

4
votes

Does it have to be a custom tag? Seems to me this would be simpler wrapped up in a CFC. Something like:

<cfcomponent output="false">

    <cffunction name="init" access="public" returntype="any" output="false">
        <cfreturn this>
    </cfunction>

    <cffunction name="sendEmail" access="public" returntype="void" output="false">
        <cfargument name="to" required="true">
        <cfargument name="from" required="true">
        <cfargument name="subject" required="true">
        <cfargument name="importance" required="true">
        <cfargument name="htmlContent" required="true">
        <cfargument name="textContent" required="true">

        <!--- do a check here to see if in production something like--->
        <cfif ListFirst(CGI.SERVER_NAME, ".") neq "www">
            <!--- override the to email address or whatever here --->
            <cfset to = "[email protected]">
        </cfif>

        <cfmail to="#to#" from="#from#" subject="#subject#">
            <cfmailparam name="Importance" value="#importance#">
            <cfmailpart type="text/plain">#textContent#</cfmailpart>
            <cfmailpart type="text/html">#htmlContent#</cfmailpart>
        </cfmail>
    </cffunction>

</cfcomponent>

Then you can call it via:

<cfset Mailer = new Path.To.Component()>
<cfset Mailer.sendEmail(
    to="[email protected]",
    from="[email protected]",,
    subject="An Email",
    importance="high",
    htmlContent="<p>Hello!</p>,
    textContent="Hello!"
)>

The Mailer instance can be a singleton (you only need one instance per application) and then you can do things like injecting a config setting into it if you want to instead of having the environment detection in the actual CFC.

2
votes

EDIT: While this will get it to work using custom tags, John Whish's solution using a cfc is more flexible.

You'll probably need to create a cf_emailpart custom tag for the same reason you created a cf_emailparam tag. cfemailparam must be contained in a cfmail tag

<cf_email to="[email protected]" from="[email protected]" subject="This is only a test">
    <cf_emailparam name="Importance" value="high">
    <cf_emailpart type="text">Text</cf_emailpart>
    <cf_emailpart type="html">HTML</cf_emailpart>
</cf_email>

cf_emailpart

Almost the Same as cf_emailparam. The last part of this associates the tag with cf_email

<cfif CompareNoCase(thisTag.hasEndtag,"YES") EQ 0 AND CompareNoCase(thisTag.executionMode,"END") EQ 0 >
    <cfexit method="exittag" />
</cfif>

<cfassociate basetag="cf_email" datacollection="emailPart">

Then you'll need to add this inside your cf_email custom tag file, after the section where you output the cfmailparam tags, and inside the cfmail tag.

<cfif isDefined("thisTag.emailPart")>
    <cfloop array="#thisTag.emailPart#" index="attrCol">
        <cfmailpart attributecollection="#attrCol#" >
    </cfloop> 
 </cfif>

I haven't tested this code, but I think this is the direction you'll have to go.