Cfmail options for multiple servers

While testing a new setup including mail server details in application.cfc, I ran into this bug [LDEV-3088] - Lucee which basically means any mail server setup in the lucee server overrides the web instance.

So having read through the docs I thought a way around this would be to simply specify the server (smtp host) inside the cfmail tag, as is possible in coldfusion. But apparently that doesn’t work, as lucee works slightly different and won’t match that host with any that are setup: https://lucee.daemonite.io/t/defining-and-using-multiple-smtp-servers/1584/2

Is there any other way to specify which mail server lucee should use, without having to include username/password in each cfmail tag? Seeing as you can setup multiple mail servers also inside a web admin, how do you then use this functionality if it’s not by host?

Is my only other option (till bug mentioned at top gets fixed) to delete the mail server in the lucee server instance, essentially removing a ‘backup’ mail server for all web instances? It would be super useful to specify a different mail server for transactional emails vs marketing emails fex.

I’m on 5.3.7.48.

Not sure what your Mailserver setup is, but you could just define your Lucee server, or servers (cluster) as relay hosts and then have your MTA do the work of sending the email on behalf of the domain without providing a username / password.

The other option would be in perl and use cfexecute or cron (Taskschedule job if Windows)

There is a perl module called Postfix postdrop
You could install that then do something like this

<cfset myMessage ='Something something something darkside'>
<cfset myMsg = 'use Mail::PostFix::Postdrop 'inject';   inject #myMessage# Sender     => '#qryMsgSender#', Recipients => [ qw(#qryMsgRecipient#) ]; '>


<cffile action = "write" 
file = "/var/path/to/postfix/maildrop/#loopmessage#.msg" 
output ="#myMsg#"
>

I did suggest that email servers be setup like datasources about 10 years ago… #sigh… aka mailsources…

i setup my mailsources in my app settings and just then pass in a source="myserver’ and my email component then looks up username/password if required (as it also allows api driven email)

2 Likes

So you basically hit up a standard email component and include a server variable when calling that, which then inserts user/pw (if SMTP) directly in the cfmail tag inside that component? That seems like a good and simple fallback.

From what I gather they are roughly supposed to work like datasources, but there’s bugs stopping it. It would be awesome if one could specify a “application.mailServer1” though or some such.

@dawesi example as a component is the best solution. But you can do it the very classic way also (did that also over 10years ago :slight_smile: ), something like so:

<!--- set global mailservers struct with all variables you need for the cfmail tag 
(over 10 years ago I defined that struct with bracket notation :D) --->
<cfset application.myMailservers={
    "SmtpName1": { "hostAddress": "127.0.0.1", "username": "myUsername1", "password": "mySecret"},
    "SmtpName2": { "hostAddress": "127.0.0.2", "username": "myUsername2", "password": "mySecret"},
    "SmtpName4": { "hostAddress": "127.0.0.3", "username": "myUsername3", "password": "mySecret"},
    "SmtpName5": { "hostAddress": "127.0.0.4", "username": "myUsername4", "password": "mySecret"}
}>

<!--- define mailservername as you may need somewhere --->
<cfset useMailServer="SmtpName4">


<!--- the  cfmail call is always made dynamically, so that the variable names keep the same for all cfmail tags --->
<cfmail to="recipient@example.com" from="sender@example.com" subject="Example email" 
        port="25"
        server="#application.myMailservers[ useMailServer ].hostAddress#"
        username="#application.myMailservers[ useMailServer ].username#" 
        password="#application.myMailservers[ useMailServer ].password#">
    Your Email Message!!
</cfmail> 

Ok - either way it seems I need to insert user details in the cfmail to get this to work :frowning:
It’s a shame it doesn’t mirror acf here where just the server is enough. And there is obviously already a realization based on that bug that current behaviour isn’t right. I’m a bit loath to delete the mail details in the server which seems to be a decent fallback solution, but I guess as long as all web instances are set up correctly it would be ok. Thanks for the insight everyone.

You could try setting the default username and password attributes for the cfmail tag in your Application.cfc like so:

this.tag.mail = { username: "user", password: "password" };

EDIT: Although, maybe I’m misunderstanding… you want to be able to switch servers, so perhaps that won’t work.

I have set up the web mail instance using “<cfset this.mailservers = xxxxx” and that works, but only if the server mail instance is deleted. Basically there is a bug that the server one ALWAYS takes precedence over the web one (when set up via application.cfc). I can use the web administrator to set it up (though more a pain to maintain in the long run vs application.cfc), which at least still gives me the server backup, but even then to toggle between two different ones that are setup I need to include user/pw details for it to work. Anyway, I can work around it, was just hoping something else that was cleaner worked till the server bug thing is fixed.