For all of you who have Smartermail as their mailserver software, I just made your life a bit easier!
You probably already know that it is not possible inside of smartermail, to change user settings for all existing customers in one time? You can change the Defaults for new users, but existing, nehh.
Since I needed to do some global changes for a few hundred accounts, I decided to check out the Smartermail API. And what began as a simple task, turned into my newest opensource Coldfusion project: the Smartermail API wrapper for coldfusion, complete with a UI for everyone!
The main file that cfml developers will use is smartermail.cfc , which does the actuall call to the webservice.
All other people (also non-coldfusion-people) can use the API wrapper UI which I also built.
Versions
17 june 2011: Version 1.3.1
Fixes a bug which made some API calls fail: all arguments were xmlFormatted, while some of these arguments needed to actually be shown as xml (i.e. <string>email@domain.com</string>).
26 february 2011: Version 1.3.0
Added extra no-compression
headers to the http api call, to fix an Adobe CF bug. Updated the UI to
allow domain admins to login and use the functionality.
01 december 2010: Version 1.2
Added debugging options in the Smartermail.cfc file; added optional extra debugging in the UI files; enhanced the UI a bit.
28 march 2010: Version 1.1
Changes in the smartermail API wrapper code, to make it CF7/8 compatible. (it used to be Railo + CF9 only)
9 may 2010: Version 1.1.1
The api wrapper now uses the xmlFormat() function for all values in the soap call. The smartermail api wrapper UI now shows a textarea when the field for an api function has 'description' in it's name. Also, all form values are now escaped with htmleditformat() when the form is shown again after submit. Also, some minor text/layout change.
Download the code
- You can download the whole package here (.zip, 456KB)
- View the source of smartermail.cfc or all other files
WSDL? No, just cfhttp ;-)
One of the biggest irritations with webservices is the wsdl itself, and the flunky way some versions of coldfusion handle it. For me, the simpler you can do it, the better. Web services are just a way of communication: I send an xml package with a question inside, and I get an xml package returned with the answer. That's it.
So, I decided to not use <cfinvoke>, but just <cfhttp>:
<cfhttp method="post" url="#this.serverURL#/Services/#arguments.page#.asmx" throwonerror="yes" result="cfhttpReturn_struct">
<cfhttpparam type="header" name="Content-Type" value="application/soap+xml" />
<cfhttpparam type="body" value="#soapBody#" />
</cfhttp>
The UI
As you can see in the example pages, all the methods are there, complete with the documentation and an example of the soap xml which is used. If you just want to use the UI, then just don't care about the xml; it's all done for you. Just fill in the displayed form, and you're fine!
For starters, you have to login with your server credentials. After that, a check is done to see if the credentials are correct.
Then, you are ready to go!
All of the options can also be done in your smartermail administrator, but I've made a few extras...
You can manage the settings for multiple email addresses in one time, and even for multiple domains in one time. If, for example, you want to change the mailbox size of 200 users, you only have to do one call! (hmm, wasn't that the thing I originally just needed to do?)
How to use the API wrapper yourself.
First, create the smartermail-object with the admin details:
<cfset variables.smartermail_obj = createObject("component", "Smartermail").init(serverURL="http://webmail.yourserver.com", wsUsername="your admin username", wsPassword="your admin password") />
Then, you can call any function you like, like this:
<cfset return_xml = variables.smartermail_obj.callWs(page='svcDomainAdmin', method='GetAllDomains') />
In case you need to give extra arguments to the page you are calling, you supply the extra argument 'args', like this:
<cfset extraArguments_struct = structNew() />
<cfset extraArguments_struct['DomainName'] = "somedomain.com" />
<cfset return_xml = variables.smartermail_obj.callWs(page='svcUserAdmin', method='GetUsers', args=extraArguments_struct) />
If you want to find out which arguments you need, then just check the UI test pages!
In the example pages I created an option to manage the settings for multiple domains and email addresses in one time. This is actually pretty simple to do, since you only have to loop over a list, like this:
<cfset emailList = "email1@domain.com,email2@domain.com,email9@otherdomain.com" />
<cfloop list="#emailList#" index="email">
<cfset form.EmailAddress = email />
<cfset extraArguments_struct = structNew() />
<cfset extraArguments_struct['EmailAddress'] = email />
<cfset return_xml = variables.smartermail_obj.callWs(page="svcUserAdmin", method="GetUser", args=extraArguments_struct) />
<!--- you might want to do something with the xml you retrieved here --->
</cfloop>
When one of the parameters has multiple values (i.e. 3 mail addresses for 1 alias), then you need to send the 3 mailaddresses as an CRLF-delimited list, like this:
<cfset extraArguments_struct = structNew() />
<cfset extraArguments_struct['DomainName'] = "domain.com" />
<cfset extraArguments_struct['AliasName'] = "allclients" />
<cfset extraArguments_struct['Addresses'] = "info@client1.com
info@client2.com
peter@client3.com" />
<cfset return_xml = variables.smartermail_obj.callWs(page="svcAliasAdmin", method="AddAlias", args=extraArguments_struct) />
Debugging (new since version 1.2.0)
In case you need to debug the API calls, you can now simply save all request and response data to any scope you want.
To start, you need to add 2 arguments to the init function like this:
<cfset variables.smartermail_obj = createObject("component", "Smartermail").init(
serverURL="http://webmail.yourserver.com"
, wsUsername="your admin username"
, wsPassword="your admin password"
, debugMode=true
, debugDataScopeName="request / application / this / server") />
By default, debugMode is off. The default for the debugDataScopeName is "this", which means that the debug data will be stored inside the cfc.
The debug data will be stored as "SMDebugData", so for example application.SMDebugData. It is an array with structs, containing the keys Date, Title, and Data. But you can access this debug data even more easily, by calling
<cfset myDebugData = variables.smartermail_obj.getDebugData() />
Usefull?
I hope you like and use the code! If so, leave me a comment; I'd like it!
Better yet, if you need a coldfusion (or Railo!) developer, hire me!
| Viewed 11288 times
#1 by Ricardo - January 13, 2010 at 5:27 PM
I downloaded the package and tried to run, but it seems to miss a folder required by the Application.cfm, /wddx/methodArguments.wddx
Can you send that to me ?
Thanks.
#2 by Paul Klinkenberg - January 13, 2010 at 5:44 PM
I updated the zip file to include *all* the files: http://www.coldfusiondeveloper.nl/smartermail-api-wrapper/Smartermail-API-wrapper-coldfusion.zip
Let me know if you have any questions!
Regards, Paul
#3 by Ricardo - January 13, 2010 at 5:51 PM
Thanks for your attention. I'm hoping to successfully access our mail server though the API, since the tests I've done by reading SmarteTools documents were a failure.
I'll keep you posted of my results.
By the way, do you want a free email account at our domain CFDEVELOPERS.NET ? Just let me know which username you want.
Best regards,
Ricardo
#4 by Paul Klinkenberg - January 13, 2010 at 6:08 PM
(and paul@coldfusiondeveloper.nl is also quite catchy I think ;)
Hope to hear about your results!
Paul
#5 by Ricardo - January 15, 2010 at 6:06 PM
I am using your API successfully to check email accounts, get a list of users and aliases, add new user and add new alias.
One thing that I need to know is how to pass multiple addresses for an alias. When I send just one address in "params.Addresses" it works fine, but if I send multiple addresses in a comma or pipe delimited list, it creates the alias with none addresses.
I tried to send them as an array, then I got an error from your API.
Any light on that ?
Thanks.
#6 by Paul Klinkenberg - January 15, 2010 at 6:31 PM
You could've also found out by using the API UI btw :)
http://www.coldfusiondeveloper.nl/smartermail-api-wrapper/index.cfm?method=AddAlias&page=svcAliasAdmin
Good luck, Paul
#7 by Ricardo - January 15, 2010 at 7:20 PM
Here is the deal, I receive the operations request from a PHP page in a XML-RPC package, which I transform into ColdFusion structure, then do my validations, modify some parameters and then I call your API which converts my parameters into a SOAP and communicates with SmarterMail.
I found out that if I send the multiple addresses in my parameter "params.Addresses" as a CR-LF delimited list, IT WORKS!.
Then I transform your results back into XML-RPC for the PHP page to understand it.
I'm very happy with your API, it solved our big problem here.
I will blog about it in the near future and link to your blog.
Thanks for your good job.
#8 by Paul Klinkenberg - January 17, 2010 at 3:34 PM
Well, hope to see your blog post in the near future!
#9 by Ty Whalin - March 10, 2010 at 3:32 AM
Do you possibly have a simple solution for checking domain name availability? I have spent several days trying to make the code work but no luck yet.
I've done extensive searching for this type of process with CF but not much has came up. As a matter of fact that's how I found your wrapper. Is to complex for me at the moment buy I'm gaining CF speed.
THX in advance.
#10 by Paul Klinkenberg - March 10, 2010 at 11:15 AM
Good luck!
#11 by Ty Whalin - March 11, 2010 at 3:59 PM
What I'm trying to do is run a CGI_SCRIPT_NAME on my form and then output the information on my page instead of using the hardcoded url's Ben supplied.
At first there was an error with the <pre></pre> part in the MatchNoCase Expression and was getting a position not found error. After I got past that catch error it continues to say every name is available.
Thinking it might be something to do with the way my form submits. Set to get method by the way. If you've ever used beens code and got it to work let me know.
THX for your time.
#12 by Paul Klinkenberg - March 11, 2010 at 5:13 PM
On that page, it says "Search (.aero, .arpa, .asia, .biz, .cat, .com, .coop, .edu, .info, .int, .jobs, .mobi, .museum, .name, .net, .org, .pro, or .travel)"
I guess you're trying to check another extension, which is simply not supported.
If you check .com domains, it will work; I tested.
#13 by Jack - March 26, 2010 at 7:12 AM
I have installed your zip and I am unable to view the index.cfm in my browser. The error is
"Template Exception - in SMadminWrapper\index.cfm : line 83
Missing argument name.'"
I have not changed anything or added any code yet... Just tring to get it to load right now. Could you help.
#14 by Paul Klinkenberg - March 26, 2010 at 7:50 AM
#15 by Jack - March 29, 2010 at 4:58 PM
#16 by Sarah - April 28, 2010 at 10:44 AM
when making say a SOAP call?
#17 by Pardeep - May 2, 2010 at 9:02 PM
This API is frickin awesome time saver man. Thanks so much:)
#18 by Paul Klinkenberg - May 5, 2010 at 11:56 PM
@Sarah: I have made a new version of the cfc and the ui files, with which you can use paragraphed text (html text and/or line breaks). You can only find it in the svn browser, since I have had no time to make an official new release. Good luck with it!
#19 by paul - May 9, 2010 at 9:31 PM
I'm new to this - I'm trying to use the API to update a single email address
Can you give me a sample cfinvoke and relevant arguments that are needed to get going on this?
Thanks
Paul
#20 by Paul Klinkenberg - May 9, 2010 at 9:49 PM
The arguments, you can find when looking at the UI. You probably need UpdateUser in the svcUserAdmin: http://www.coldfusiondeveloper.nl/smartermail-api-wrapper/index.cfm?method=UpdateUser&page=svcUserAdmin
Hope it works for you! Paul
#21 by Grant B. - May 12, 2010 at 7:49 PM
I even tried GetRequestedUserSettings but smartermail simply ignores the 'disablegreylisting' value. It returns other string/value pairs but not 'disablegreylisting' ... actually also does the same with 'lockpassword'.
Any idea where I would find a list of the keys for version 4.3?
#22 by Paul Klinkenberg - May 13, 2010 at 11:31 AM
You can find instructions for your own api interface by going to those pages... By default it shows you the soap xml. The urls are shown when you use the UI available from this post.
Good luck!
#23 by Clay Owensby - December 1, 2010 at 2:11 PM
#24 by Paul Klinkenberg - December 1, 2010 at 2:23 PM
Good luck, Paul
#25 by Clay Owensby - December 1, 2010 at 7:10 PM
Connection Failure: Status code unavailable error. I have tried the domain and administrators credentials in the smartermail.cfc and either seem to work. Suggestions?
#26 by Clay Owensby - December 1, 2010 at 7:29 PM
#27 by Paul Klinkenberg - December 1, 2010 at 10:38 PM
#28 by Paul Klinkenberg - December 1, 2010 at 10:45 PM
Regards, paul
#29 by Clay Owensby - December 1, 2010 at 10:48 PM
#30 by Jacki - December 14, 2010 at 5:07 PM
#31 by Clay Owensby - December 14, 2010 at 5:31 PM
<cfhttpparam type="Header" name="Accept-Encoding" value="deflate;q=0" />
<cfhttpparam type="Header" name="TE" value="deflate;q=0" />
<cfhttpparam type="header" name="Content-Type" value="application/soap+xml" />
#32 by Clay owensby - December 16, 2010 at 10:44 PM
#33 by Jacki - December 17, 2010 at 12:15 AM
#34 by Clay Owensby - December 17, 2010 at 12:26 AM
#35 by Paul Klinkenberg - December 18, 2010 at 6:12 PM
#36 by Jacki - December 20, 2010 at 6:36 PM
#37 by Clay Owensby - December 23, 2010 at 4:47 PM
#38 by Eric Do - February 25, 2011 at 4:55 PM
<cfset variables.smartermail_obj = createObject("component", "Smartermail").init(serverURL="http://mail.wwb-mail.com:9998/", wsUsername="== REMOVED ===", wsPassword="== REMOVED ==") />
Is this because that SmarterMail server is running on port 9998 instead of 80?
If you go to this mail client address: http://mail.wwb-mail.com:9998/ and type in
email: XXXXXXXXXXXXX
password: XXXXXXXX
it will allow you to login. Can you please let me what I am missing.
Also, assume that I can login, what API that I need to call to create/add a New User from my CF page.
Please advice. Thank you in advance. Great works for putting this together.
#39 by Eric Do - February 25, 2011 at 5:35 PM
<cfhttpparam type="Header" name="Accept-Encoding" value="deflate;q=0" />
<cfhttpparam type="Header" name="TE" value="deflate;q=0" />
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetAllDomainsResponse xmlns="http://tempuri.org/">
<GetAllDomainsResult>
<Result>false</Result>
<ResultCode>-20</ResultCode>
<Message>Invalid Permissions.</Message>
<DomainNames />
</GetAllDomainsResult>
</GetAllDomainsResponse>
</soap:Body>
</soap:Envelope>
#40 by Eric Do - February 25, 2011 at 5:46 PM
Thanks,
The error occurred in C:\Inetpub\wwwroot\CRM\_wwb\api\SmarterMail\Smartermail.cfc: line 88
86 : <cfhttpparam type="Header" name="TE" value="deflate;q=0" />
87 : <cfhttpparam type="header" name="Content-Type" value="application/soap+xml" />
88 : <cfhttpparam type="body" value="#soapBody#" />
89 : </cfhttp>
90 :
#41 by Eric Do - February 25, 2011 at 5:56 PM
Great works Paul. You guys are awesome! This will save our time from having to get on the SmarterMail UI.
#42 by Paul Klinkenberg - February 26, 2011 at 1:21 AM
Due to your messages, I did 2 actions:
- I (finally) updated the code to include the "deflate" headers, which fixes a bug in Adobe CF, which gave you the "connection failure" message.
- I now made it more clear in the example pages, that the only valid logins you can use for the api wrapper, are Smartermail's "Domain admins" and "System admins".
@Everyone: a new version 1.3 is now available for download :-)
#43 by Eric Do - February 26, 2011 at 6:13 AM
I tested with the 5.0 version, everything seem to work perfect but for the 7.1 version, I can't seem to get pass the login page.
I received the 500 error message when try to login to the 7.1 version.
#44 by Paul Klinkenberg - February 26, 2011 at 1:18 PM
Also, you could check to see if the error is specific to your server / CF version, by testing the login via my test environment: http://www.railodeveloper.com/smartermail-api-wrapper/index.cfm
If you want professional assistance, you can mail me at paul at railodeveloper.com.
Cheers, Paul
#45 by Eric Do - February 28, 2011 at 6:54 PM
Now that we know are you the expert in SmarterMail and the CF bridge, when our guys need any professional consultant in the near future, we will inform you.
Your help is much appreciated, Eric.
#46 by Russ Michaels - March 21, 2011 at 4:21 AM
Interesting way of generating the SOAP requests too, certainly a lot less code than the way I was doing it anyway :-)
I have noticed one issue though, the smartermail.cfc can't find the wddx file if the calling template is in a different folder as the ExpandPath() function is working relative to the calling template and not the CFC.
You get around this by using a cfinclude instead.
<cfsavecontent variable="q"><cfinclude template="wddx/methodArguments.wddx"></cfsavecontent>
#47 by Russ Michaels - March 21, 2011 at 4:40 AM
#48 by Paul Klinkenberg - March 21, 2011 at 4:11 PM
I also use cfinvoke a lot, and then mostly use cfinvokeargument to add the arguments. I do not yet understand how the 'args' attribute could lead to problems with cfinvoke; could you explain? Cheers, Paul
#49 by Russ Michaels - March 26, 2011 at 1:10 AM
#50 by Paul Klinkenberg - March 26, 2011 at 4:06 PM
#51 by Eric Do - March 28, 2011 at 10:24 PM
When call the AddUser method to add a new user email account (assume that the new email account that I wish to create is eric123@myemaildomain.com), how do I make/specify 'eric123@myemaildomain.com' automatically insert into the Reply-To Email Address.
The reason because when the Reply-To Email Address is blank and when try to send email from eric123@myemaildomain.com to a Gmail or other client, it show 'eric123' instead of the actual Display Name (FirstName LastName) that is set when setup a new account.
Please advice and thank you in advance,
Eric
#52 by Humberto Fujitani - June 16, 2011 at 8:56 PM
This API is very good. I would just like to clarify a doubt about "SetSubscriberList" method:
I submit to my script a list of emails, separated by commas. My script uses the code below to handle this list and send it to the SmarterMail mailing list:
<cfsavecontent variable="listsub">
<cfoutput>
<cfloop index="destination" list="#form.emails#" delimiters=",">
#destination#
</ cfloop>
</ cfoutput>
</ cfsavecontent>
<cfset setList_struct = structNew() />
<cfset setList_struct['DomainName'] = "list.rtibrasil.com" />
<cfset setList_struct['ListName'] = "newsrti" />
<cfset setList_struct['Subscribers'] = "#listsub#" />
<cfset return_xml = variables.smartermail_obj.callWs(page="svcMailListAdmin", method="SetSubscriberList", args=setList_struct) />
However, when I look at subscribers of mailing list "newsrti", the list is empty. May you help me solve this?
Thanks,
Humberto
#53 by Paul Klinkenberg - June 17, 2011 at 9:34 AM
See the new version 1.3.1, which should fix this.
Paul
#54 by Humberto Fujitani - June 17, 2011 at 2:20 PM
Hello Paul,
Thanks for the new version, the "SetSubscriberList" method seems to work fine now.
Best regards,
Humberto
#55 by Andor Admiraal - September 24, 2011 at 9:42 PM
Great little tool. Really a big time saver for me, thanks! Did not encounter any bugs at all, works very smoothly for me.
One hint that other people might find useful. An easy way to directly use the XML the tool outputs, is the following:
1. Copy the XML code to the clipboard
2. Paste it into a new text file
3. Give the text file an .xml extension
4. Now you can open it as an XML table in Excel
Thanks again, regs from India
#56 by Paul Klinkenberg - September 25, 2011 at 8:27 PM
Normally, if I get a "new comment" email, I prepare myself for some bug fixing or explaining ;-)
Kind regards, Paul
#57 by Akos - January 18, 2012 at 11:59 AM
But now I'm trying to delete a user using the DsvcUserAdmin.DeleteUser().
The API comes back with DeleteUserResult, ResultCode 0, Result True.
I assume that means it's successful yet the user is not deleted from smartermail.
Any suggestions please?
#58 by Akos - October 31, 2012 at 3:32 PM
Does anyone have any solution to the above post #57 please ?