Automatically Generate SPF records Upon Creation of an Addon Domain or Subdomain

double a ron

Aug 22, 2007
Hey guys,

I've successfully setup spf and domainkey records to be created when an account is created via WHM in /scripts/postwwwacct, but I am looking to also make cPanel automatically generate SPF and even domainkey records when a subdomain or addon domain is created by a user. Unfortunately postwwwacct isn't invoked when creating an addon or subdomain.

Is there a similar script that's invoked after the creation of an addon domain and/or subdomain that I can add the spf and domainkey setup script to? Perhaps I'll need to do something entirely different to make this happen..?

I really appreciate any hints in the right direction.


Well-Known Member
Staff member
Dec 17, 2009
Houston, TX
cPanel Access Level
Root Administrator
Hello (Aaron?)

You should take a look at cPanel function hooks. This hooks are language agnostic (just like your postwwwacct script), so you can write them in any language you want. It will be run as root when the user performs the specified cPanel API call. The API calls for the actions you describe are listed in the API2 AddonDomain and SubDomain modules.

Couple of things to keep in mind:
  • Make sure it is executable (700, to be exact) before you run register_hooks
  • You're script can NOT emit ANY output. You must properly suppress all output and errors (and optionally log to a destination of your choice). If you emit output, you will cause mal-formed returns for that API call.
  • The hook will run after the original action is performed. The hook is executed as a separate process. The hook has no control over the original action. ie, you can't "block" an API call with a function hook.

Best Regards,

double a ron

Aug 22, 2007
Forgive me for the ultra newb question, but what do I do when the module directory doesn't exist for addondomain? Just makdir with the module's name under hooks?

[email protected] [/usr/local/cpanel/hooks]# ll
total 21
drwxr-xr-x  19 root root  1024 Jul  3 03:43 ./
drwx--x--x  42 root wheel 2048 Jul 16 16:00 ../
-rw-r--r--   1 root root   909 May  6 11:14 README
drwxr-xr-x   2 root root  1024 Oct  9  2008 denyip/
drwxr-xr-x   2 root root  1024 Jul 16 17:31 email/
drwxr-xr-x   2 root root  1024 Oct  9  2008 frontpage/
drwxr-xr-x   2 root root  1024 Oct  9  2008 ftp/
drwxr-xr-x   2 root root  1024 Oct  9  2008 mime/
drwxr-xr-x   2 root root  1024 May  6 11:14 mysql/
drwxr-xr-x   2 root root  1024 Oct  9  2008 mysqlfe/
drwxr-xr-x   2 root root  1024 Oct  9  2008 net/
drwxr-xr-x   2 root root  1024 Oct  9  2008 nvdata/
drwxr-xr-x   2 root root  1024 Oct  9  2008 park/
drwxr-xr-x   2 root root  1024 May 31 22:52 passwd/
drwxr-xr-x   2 root root  1024 Oct  9  2008 postgres/
drwxr-xr-x   2 root root  1024 May 31 22:49 print/
drwxr-xr-x   2 root root  1024 Oct  9  2008 ssl/
drwxr-xr-x   2 root root  1024 Oct  9  2008 stats/
drwxr-xr-x   2 root root  1024 Oct  9  2008 statsbar/
drwxr-xr-x   2 root root  1024 Jul 16 17:31 subdomain/

The closest thing appears to be the park directory:

[email protected] [/usr/local/cpanel/hooks]# locate addondomain
[email protected] [/usr/local/cpanel/hooks]#

double a ron

Aug 22, 2007
Sooo, I added this and no joy:

[email protected] [/usr/local/cpanel/hooks/addondomain]# cat addaddondomain
use strict;
use AddonDomain::addaddondomain;
my %OPTS = @ARGV;
$ENV{USER} ="$OPTS{'user'}";
system q(/usr/local/cpanel/bin/domain_keys_installer $USER);
system q(/usr/local/cpanel/bin/spf_installer $USER);
[email protected] [/usr/local/cpanel/hooks/addondomain]#
I added the use strict; and use AddonDomain::addaddondomain; to the original script in postwwwacct. I figured I might get lucky and it would work in the api2 hook too :D But no such luck!

the only real obvious thing to me in my ignorance of perl/code is that it's not liking even the third line, but the api2 examples really make it seem like the third line is the right fit:

[email protected] [/usr/local/cpanel/hooks/addondomain]# tail -n50 /usr/local/cpanel/logs/error_log
[2011-07-21 05:52:44 -0400] warn [cpanel] Cpanel::AdminBin::adminstor(hooks) set error in context park at /usr/local/cpanel/Cpanel/ line 86
        Cpanel::AdminBin::adminstor('hooks', 'addondomain::addaddondomain', HASH(0x9e69704)) called at /usr/local/cpanel/Cpanel/ line 34
        Cpanel::EventHandler::hook('addondomain', 'addaddondomain', HASH(0x8ce30a0), ARRAY(0x9e69620)) called at /usr/local/cpanel/Cpanel/ line 79
        Cpanel::EventHandler::post_event(2, 'post', 'addondomain', 'addaddondomain', HASH(0x8ce30a0), ARRAY(0x9e69620)) called at /usr/local/cpanel/Cpanel/Api2/ line 101
        Cpanel::Api2::Exec::api2_exec('AddonDomain', 'addaddondomain', HASH(0x9205bb0), HASH(0x8ce30a0)) called at cpanel line 621
        main::real_cpexectag('<?cp AddonDomain::addaddondomain(\'% %\',result,reason) newdomain=$FORM{\'domain\'},dir=$FORM{\'dir\'},subdomain=$FORM{\'user\'},pass=$FORM{\'pass\'} ?>') called at cpanel line 3881
        main::dotag_finished_headers(1) called at cpanel line 3712
        main::cpanel_parseblock('<cpanel setvar="headerimg=../images/topsubdomains.gif">\x0A<cpanel setvar="dprefix=../">\x0A<cpanel Branding="include(stdheader.html)">\x0A\x0A<style type="text/css">\x0A<?cp Branding::spritelist(.spriteicon_img_mini {float:left;margin-right:5px;background: url\\{leftparenthesis}"%"\\{rightparenthesis};} %,@spriteurl,images::#icon-${img}_mini {background-position\\{colon}0 -${cssposition}px;width\\{colon}${width}px;height\\{colon}${height}px; }:) imgtype=icon,subtype=img,method=scale_60percent,format=png,img=addondomain ?>\x0A</style>\x0A\x0A<div class="body-content"> \x0A\x0A<div class="h1Title"><div class="spriteicon_img_mini" id="icon-addondomain_mini"></div><cpanel langprint="INDXAddonDomains"></div>\x0A\x0A<h2><cpanel langprint="AODAddition"></h2>\x0A\x0A<!--\x0A<?cp AddonDomain::addaddondomain(\'% %\',result,reason) newdomain=$FORM{\'domain\'},dir=$FORM{\'dir\'},subdomain=$FORM{\'user\'},pass=$FORM{\'pass\'} ?>\x0A-->\x0A\x0A<cpanelif !$CPERROR{\'addondomain\'}>\x0A\x09<div class="success_details"><cpanel Locale="maketext(\'The addon domain \xE2\x80\x9C[_1]\xE2\x80\x9D has been created.\',$FORM{\'domain\'})"></div>\x0A\x09<!-- <cpanel Ftp="addftp($FORM{\'user\'},$FORM{\'pass\'},$FORM{\'dir\'},,,$FORM{\'dir\'})"> -->\x0A\x09<cpanel langprint="AODGoFileMgr">: <a target="_blank" href="../filemanager/index.html?dir=<cpanel uriprint="$homedir">/<cpanel uriprint="$FORM{\'dir\'}">" class="ajaxfiles"><cpanel langprint="TFileManager"></a>\x0A</cpanelif>\x0A\x0A<cpanelif $CPERROR{\'addondomain\'} || $CPERROR{\'ftp\'}>\x0A\x09<div class="error_details">\x0A        <cpanel print="$CPERROR{\'addondomain\'}">\x0A        <cpanel print="$CPERROR{\'ftp\'}">\x09\x09\x0A\x09</div>\x0A</cpanelif>\x0A\x0A<div class="return-link"><a href="index.html">&larr; <cptext "Go Back"></a></div>\x0A\x0A</div><!-- end body-content -->\x0A\x0A<cpanel Branding="include(stdfooter.html)">\x0A') called at cpanel line 3627
        main::cpanel_parse(GLOB(0x8fad35c)) called at cpanel line 5011
        main::run_standard_mode() called at cpanel line 420
/usr/local/cpanel/bin/ftpadmin : Syncing Ftp Databases....
[email protected] [/usr/local/cpanel/hooks/addondomain]#

I imagine this is something silly that I'm not doing right, but I would really appreciate any push in the right direction. Thanks so much.

double a ron

Aug 22, 2007
Ah, I just removed the use portion of the script and it appears to like it much more, but still no joy. It appears that the user argument isn't valid here, and it needs some kind of domain argument instead.

[2011-07-21 06:04:08 -0400] info [parkadmin] Creating Addon domain '' on ''.
/usr/local/cpanel/bin/domain_keys_installer: usage: /usr/local/cpanel/bin/domain_keys_installer <user> at /usr/local/cpanel/bin/domain_keys_installer line 20.
/usr/local/cpanel/bin/spf_installer: usage: /usr/local/cpanel/bin/spf_installer <user> at /usr/local/cpanel/bin/spf_installer line 19.
/usr/local/cpanel/bin/ftpadmin : Syncing Ftp Databases....
[email protected] [/usr/local/cpanel/hooks/addondomain]#