Managing Accounts via the Web or API/http

Account Creation - Web Interface

Account Creation - User Self Creation

Users can optionally create or sign-up for accounts via the web interface on the user port ie:

https://localhost:7443/cgi/user.cgi?cmd=user_check

There are several different methods, the method being used is specified per domain using the domain setting create user.

Account Creation - Manager

User administration is done via the "User accounts" option in the web admin contents.

https://localhost:7025/cgi/admin.cgi

This will display a page that allows you to lookup, create, modify and search for users. Once you have looked up an existing user you can change a user's password, edit any of the user's information including forwarding or delete them.

Domain administrators, configured by the manager_username setting, log in to the user self management interface:

https://localhost:7443/cgi/user.cgi

and have access to this users page for all the domains they manage.

Creating System Admin accounts

You can create additional system admin accounts for surgemail using the command:
    surgemail -password
To remove accounts you will need to edit and manually remove entries from admin.dat

Interfacing with the user management system, HTTP/API options.

The user management system is an HTTP based system using GET and POST commands to perform actions. If you want to provide some or all of these options elsewhere you can do so by interfacing with it using these HTTP commands. For example here is a simple HTTP form which will add a user.

However you should also consider the other two methods available to interface with accounts, which method you choose will depend on your precise needs.

1) the authent module can be talked to directly using the authent protocol https://netwinsite.com/authent
2) if the authent module is using a back end database (ldap, sql, etc...) then the backend database can be used directly.

To use the following examples to experiment with save them as htm files and open them in your browser. To use from a program you need to send the form as an http POST using tcpip. Many programming languages have a mechanism for easily sending web 'forms' from a program so will find this quite easy in some cases.


Access to nwauth via http

This group of forms provide simple access to the authent module functions directly, this can be used to add/del/modify/search user accounts. For these functions you must have the web admin user/password and send it using the normal http basic authentication method. While testing your web browser will prompt you for the user/password.

 

The action can be any of: nwauth_lookup, nwauth_set, nwauth_search, nwauth_del and mdir_del

The field 'a_info' is formatted like the raw authent module data, field="value" ... e.g.

fwd="user@domain.name" quota="20mb"

Here is a sample web page to test this with:

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="http://localhost:7026/cgi/admin.cgi">
<p>
Action: <INPUT TYPE="text" NAME="cmd" VALUE="nwauth_lookup"> or nwauth_set nwauth_mod nwauth_del nwauth_search or mdir_delete <br>
Name <INPUT TYPE="text" NAME="a_user" VALUE=""><br>
Pass <INPUT TYPE="text" NAME="a_pass" VALUE=""><br>
Info <INPUT TYPE="text" NAME="a_info" VALUE=""><br>
<INPUT TYPE="submit" NAME="Submit" VALUE="Submit">
</FORM>
</BODY>
</HTML>

The mdir_delete function is for deleting a single file from the users mdir folder, the additional paramter 'fname' should be passed. This can be used to remove spam settings.
The nwauth_mod option requires 7.3d-14 allows you to set specific fields, and all other fields are automatically retained. e.g. a_info could be set to:  fwd="user@xyz.com" phone="123456"
For 'nwauth_mod' The password will not be changed if the a_pass field is left blank, otherwise it will be changed.


Access to management interface via http

The following mechanisms use modified versions of the manager templates/interface to perform manager operations, for these a domain manager username/password is used.

 

A form to 'add' a user:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main"      METHOD="POST" ACTION="https://localhost:7443/cgi/user.cgi">
<br> Fieldsd normally set to type Hidden to tell it what to do.
<INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="lcmd" VALUE="user_create">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="user_fields" VALUE="user_id,quota,alias_quota,sms_quota,smsto">
<br> Domain admin user: <INPUT TYPE="text" NAME="username"      VALUE="X"><br>
Domain Admin Pass: <INPUT TYPE="text" NAME="password"      VALUE="Y"><br>
Name <INPUT TYPE="text" NAME="lusername" VALUE=""><br>
Pass <INPUT TYPE="text" NAME="lpassword" VALUE=""><br>
uid <INPUT TYPE="text" NAME="user_id" VALUE=""><br>
SMS Phone Number <INPUT TYPE="text" NAME="smsto" VALUE=""><br>
Disk Quota<INPUT TYPE="text" NAME="quota" VALUE=""><br>
Alias Quota<INPUT TYPE="text" NAME="alias_quota" VALUE=""><br>
SMS Quota<INPUT TYPE="text" NAME="sms_quota" VALUE=""><br>
<INPUT TYPE="submit" NAME="Submit" VALUE="Add      user">
</FORM>
</BODY>
</HTML>

This can also be done using a simple http query with the same fields, e.g.


https://localhost:7443/cgi/user.cgi?cmd=cmd_user_login&lcmd=user_create&show=simple_msg.xml&user_fields=user_id&username=ADMIN@THIS.DOMAIN&password=ADMINPASSWORD&lusername=NEWUSER@THIS.DOMAIN&lpassword=NEWUSERPASSWORD

A form to 'delete' a user:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="https://localhost:7443/cgi/user.cgi"> <br>Fields normally set to type Hidden to tell it what to do. <INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="lcmd" VALUE="user_delete">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="user_fields" VALUE="user_id,quota,alias_quota,sms_quota,smsto"> <br>Domain admin user: <INPUT TYPE="text" NAME="username" VALUE="X"><br> Domain Admin Pass: <INPUT TYPE="text" NAME="password" VALUE="Y"><br>
Name <INPUT TYPE="text" NAME="lusername" VALUE=""><br>
Pass <INPUT TYPE="text" NAME="lpassword" VALUE=""><br>
uid <INPUT TYPE="text" NAME="user_id" VALUE=""><br>
SMS Phone Number <INPUT TYPE="text" NAME="smsto" VALUE=""><br>
Disk Quota<INPUT TYPE="text" NAME="quota" VALUE=""><br>
Alias Quota<INPUT TYPE="text" NAME="alias_quota" VALUE=""><br>
SMS Quota<INPUT TYPE="text" NAME="sms_quota" VALUE=""><br>
<INPUT TYPE="submit" NAME="Submit" VALUE="Del User">
</FORM>
</BODY>
</HTML>

A form to Show user fields:

 

(as above but change lcmd)

<INPUT TYPE="text" NAME="lcmd" VALUE="user_details">

You may need to add the begin/end list to simple_msg.xml template e.g.

<?xml version="1.0" ?>

<rss version="2.0">

<xml_status>||xml_status||</xml_status>

<response>||message||</response>

<response2>||message2||</response2>

||begin_list||

<info_||user_info_label||>||user_info_value||</info_||user_info_label||>

||end_list||

</rss>

 

 

A form to Modify/Save changes to a user:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="https://localhost:7443/cgi/user.cgi">
<br>Fields normally set to type Hidden to tell it what to do.
<INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="lcmd" VALUE="user_updatex">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="user_fields" VALUE="user_id,quota,alias_quota,sms_quota,smsto">
<br>Domain admin user: <INPUT TYPE="text" NAME="username" VALUE="X"><br>
Domain Admin Pass: <INPUT TYPE="text" NAME="password" VALUE="Y"><br>
Name <INPUT TYPE="text" NAME="lusername" VALUE=""><br>
Pass <INPUT TYPE="text" NAME="lpassword" VALUE=""><br>
uid <INPUT TYPE="text" NAME="user_id" VALUE=""><br>
SMS Phone Number <INPUT TYPE="text" NAME="smsto" VALUE=""><br>
Disk Quota<INPUT TYPE="text" NAME="quota" VALUE=""><br>
Alias Quota<INPUT TYPE="text" NAME="alias_quota" VALUE=""><br>
SMS Quota<INPUT TYPE="text" NAME="sms_quota" VALUE=""><br>
<INPUT TYPE="submit" NAME="Submit" VALUE="Modify User">
</FORM>
</BODY>
</HTML>

Example to create a domain (note this uses manager port):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="https://localhost:7025/cgi/admin.cgi">

<br> Fields normally set to type Hidden to tell it what to do.
<INPUT TYPE="text" NAME="cmd" VALUE="global_misc_save"> <br>
<INPUT TYPE="text" NAME="misc_settings" VALUE="domain_name,url_host,manager_email,manager_username,manager_password,create_user,create_max"> <INPUT TYPE="text" NAME="misc_cmd" VALUE="special"> <INPUT TYPE="text" NAME="domainid" VALUE="-1">
<p>

(mx) Domain: <INPUT TYPE="text" NAME="name" VALUE="new.domain"><br>
(A) Host Name: <INPUT TYPE="text" NAME="url_host" VALUE="mail.new.domain"><br>
Manager email: <INPUT TYPE="text" NAME="manager_email" VALUE="test@new.domain"><br>
Manager account: <INPUT TYPE="text" NAME="manager_username" VALUE="test@new.domain"><br>
Manager password: <INPUT TYPE="text" NAME="manager_password" VALUE="secret"><br>
<p>
<INPUT TYPE="text" NAME="force_page" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="doframes" VALUE="false">
<INPUT TYPE="submit" NAME="Submit" VALUE="Add Domain">
</FORM>
</BODY>
</HTML>

Delete a domain:

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main"      METHOD="POST" ACTION="https://localhost:7025/cgi/admin.cgi">
<INPUT TYPE="text" NAME="cmd" VALUE="domain_delete">      <br>
<INPUT TYPE="text" NAME="domainid" VALUE="-1">
<p>
Domain: <INPUT TYPE="text" NAME="domain" VALUE="new.domain"><br>
Delete users<INPUT TYPE="text" NAME="delete_users"      VALUE="true"><br>
Delete files<INPUT TYPE="text" NAME="delete_files"      VALUE="true"><br>
<p>
<INPUT TYPE="text" NAME="force_page" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="doframes" VALUE="false">
<INPUT TYPE="submit" NAME="Submit" VALUE="Delete      Domain">
</FORM>
</BODY>
</HTML>
   

Check if a domain exists

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main"      METHOD="POST" ACTION="https://localhost:7025/cgi/admin.cgi">
<INPUT TYPE="text" NAME="cmd" VALUE="domain_exists">      <br>
<INPUT TYPE="text" NAME="domainid" VALUE="-1">
<p>
Domain: <INPUT TYPE="text" NAME="domain" VALUE="new.domain"><br>
Delete users<INPUT TYPE="text" NAME="delete_users"      VALUE="true"><br>
Delete files<INPUT TYPE="text" NAME="delete_files"      VALUE="true"><br>
<p>
<INPUT TYPE="text" NAME="force_page" VALUE="simple_msg.xml">
<INPUT TYPE="text" NAME="doframes" VALUE="false">
<INPUT TYPE="submit" NAME="Submit" VALUE="Check Domain">
</FORM>
</BODY>
</HTML>
   

Copy files to the users mdir folder:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="http://localhost/cgi/user.cgi">
<br>Fields normally set to type Hidden to tell it what to do.
<INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<br>Domain admin user: <INPUT TYPE="text" NAME="username" VALUE="test1"><br>
Domain Admin Pass: <INPUT TYPE="text" NAME="password" VALUE="test"><br>
<hr>
Name <INPUT TYPE="text" NAME="lusername" VALUE="test2"><br>
Action: <INPUT TYPE="text" NAME="lcmd" VALUE="mdir_copy"> <br>
Path: <INPUT TYPE="text" NAME="mdir_path" VALUE="c:\surgemail\xmdir"> <br>
<INPUT TYPE="submit" NAME="Submit" VALUE="DoAction">
</FORM>
</BODY>
</HTML>

Set contents of a file in the users mdir folder

        <HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="http://localhost/cgi/user.cgi">
<INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<br>Domain admin user: <INPUT TYPE="text" NAME="username" VALUE="test1"><br>
Domain Admin Pass: <INPUT TYPE="text" NAME="password" VALUE="test"><br><hr>
Name <INPUT TYPE="text" NAME="lusername" VALUE="test2"><br>
Action: <INPUT TYPE="text" NAME="lcmd" VALUE="user_setfile"> <br>
File to set: <INPUT TYPE="text" NAME="fname" VALUE="testfile.txt"> <br>
Contents <textarea NAME="contents"></textarea NAME="contents"> <br>
<INPUT TYPE="submit" NAME="Submit" VALUE="DoAction">
</FORM></BODY></HTML>

Delete a file from the users mdir folder:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML><HEAD></HEAD><BODY><FORM NAME="Main" METHOD="POST" ACTION="http://localhost/cgi/user.cgi">
<br>Fields normally set to type Hidden to tell it what to do.
<INPUT TYPE="text" NAME="cmd" VALUE="cmd_user_login">
<INPUT TYPE="text" NAME="show" VALUE="simple_msg.xml">
<br>Domain admin user: <INPUT TYPE="text" NAME="username" VALUE="test1"><br>
Domain Admin Pass: <INPUT TYPE="text" NAME="password" VALUE="test"><br>
<hr>
Name <INPUT TYPE="text" NAME="lusername" VALUE="test2"><br>
Action: <INPUT TYPE="text" NAME="lcmd" VALUE="rules_delete"> <br>
File to delete: <INPUT TYPE="text" NAME="filename" VALUE="mailbox.dat"> <br>
<INPUT TYPE="submit" NAME="Submit" VALUE="DoAction">
</FORM>
</BODY>
</HTML>

For responses you can setup an xml file, something like this: simple_msg.xml contains (this is placed in the surgemail/web folder)

<?xml version="1.0" ?>
       <rss version="2.0">
       <xml_status>||xml_status||</xml_status>
       <response>||message||</response>
       <response2>||message2||</response2>
       </rss>
 

NOTE:

  • The username and password fields, these should contain the username and password of a domain admin user (see manager_username).
  • The user_fields field specifies the names of the fields containing user information to add.
  • The new users name and password are supplied in the lusername and lpassword fields.
  • The show field is used to select the output page. This file must exist in the surgemail web directory. It is not required to be XML, that was just used as an example of a format you might easily be able to parse. The content of the file may be absolutely anything you require.

Essentially what happens above is that SurgeMail carries out the cmd "cmd_user_login" using the username and password given. Once complete it looks for an lcmd, in this case user_create, it then copies all variables in the format "l<variable>" to "<variable>" so lusername is copied to username and lpassword is copied to password and then it executes user_create creating the new user.

This same process can be used with any lcmd value, provided you supply the fields required either directly (as is done with user_id, smsto, quota, alias_quota, ans sms_quota) or using l<variable> when they collide with variables required for the previous command i.e. lusername and lpassword above.

Because the show field allows you to control the format of the replies you can interface the user management system programatically, in other words write a complete custom user interface or add to an existing user interface. SurgeMail outputs a number of values which will aid in this, for example cmd_result which is equal to "success" or "failure". SurgeMail returns a utoken variable when a domain admin logs in, this utoken can be passed to carry out additional commands, instead of logging in for every request. Alternatively you can send requests to the web admin interface, this method is often cleaner, easier and more flexible. To find out the values required for each command consider using DSpy.

Using utoken

The above form essentially piggy backs a user_create command on a login command, required because you have to authenticate to create users. If you intend to send and receive the data using a program instead of a fixed html form then you have some better, and often simpler alternatives. The first is that you could send the login command by itself and store the resulting authentication token AKA "utoken". You can pass this utoken with another command instead of piggy backing every command on a login command.

Using the web admin instead

Another option uses the web admin interface instead of the domain admin one. You would connect to the web admin port 7026 (non https port) and send your request to /cgi/admin.cgi. This interface uses basic HTTP authentication, so instead of performing a login you simply need to send a special HTTP header with every request. This header contains the encoded username and password for the web admin interface, it's value is fixed, it does not change unless you change the username and/or password, so, find out the value and simply send that with every request. To find out the value consider using DSpy.

Using DSpy

DSpy (download) is a simple windows application which listens on a specified port for connections. When it accepts a connection it also connects to another specified ip and port. It reads data from each connection and passes it all through to the other while logging the entire conversation to disk. This allows you to "spy" on the data going from one port to the other. It cannot be used with HTTPS ports to spy on encrypted conversations. For example you might tell it to listen on port 8080 and connect to 127.0.0.1 on port 7026, eg:

c:\>dspy -port 8080 -to 127.0.0.1:7026

Then you would type the following url into your browser:

http://127.0.0.1:8080/cgi/admin.cgi

and you should see the web admin interface. Perform the action you want your interface to be able to carry out, and look in the dspy.log file for the http headers and request data required to do it, duplicate the authentication header (if required) and the form content to perform this action with your own interface.

You can download dspy.zip here.

If you need more information on this subject please contact surgemail-support@netwinsite.com.

Advanced Per User Services

Access to the SurgeMail's POP / IMAP / SMTP facilities can be controlled on a per user basis by defining a series of access groups (g_access_group). Users can belong to one or more access groups. Each access group has a IP based wildcarded limitation of POP, IMAP and SMTP access and is defined in surgemail.ini. The domain manager is able to change these settings for the user accounts within their domain.

Note that the groups defined by these settings can be used by many others settings to define those settings for users in these groups, eg. g_user_access, g_admin_access, g_quota, g_user_alias, g_user_sms_quota, g_user_send_max, g_user_send_rule, g_user_list_quota, authent_info_grp, web_access_grp

Membership of this group is checked against the "Access Type" setting (NWAuth field: mailaccess) in the authentication database.

eg. You could charge WebMail users for pop access privileges:

g_access_group group="paid_user" access_pop="*" access_imap="*" access_smtp="*"

g_access_group group="free_user" access_pop="webmail.svr.ip" access_imap="webmail.svr.ip" access_smtp="webmail.svr.ip"

with "Access type" set to "free_user" / "paid_user" on accounts page or equivalently in NWAuth authentication database:

marijn@mydomain.com:{ssha}tVANQo...:created="1060034937" mailaccess="free_user" ...

Or the following would use three arbitrary fields (SuspendedEmail, AllowedPOP, AllowedIMAP) in the authentication database to define the whether POP / IMAP / Webmail / SMTP services can be used on an individual per user basis.

g_access_group group="webmailonly" access_pop="" access_imap="1.2.3.4" access_smtp="*"
g_access_group group="imap" access_pop="" access_imap="*" access_smtp=""
g_access_group group="allowpop" access_pop="*" access_imap="" access_smtp=""
g_access_group group="suspendemail" access_pop="!*" access_imap="!*" access_smtp="!*"

g_group_field field="SuspendedEmail" value="0" group="webmailonly"
g_group_field field="SuspendedEmail" value="1" group="suspendemail"
g_group_field field="AllowedPOP" value="1" group="allowpop"
g_group_field field="AllowedIMAP" value="1" group="allowimap"

g_authent_info name="Suspended Email" field="SuspendedEmail" access="domadmin" default="0"
g_authent_info name="Allowed POP" field="AllowedPOP" access="domadmin"
g_authent_info name="Allowed IMAP" field="AllowedIMAP" access="domadmin"

marijn@mydomain.com:{ssha}tVANQo...:created="1060034937" SuspendedEmail="0" AllowedPOP="" AllowedIMAP="1"

In this case four groups are defined (webmailonly, SuspendedEmail, AllowedPOP, AllowedIMAP) with membership based on the (SuspendedEmail, AllowedPOP and AllowedIMAP) databse fields. The use of g_group_field has the same effect as manually setting "Access Type" to the combined group membership of "webmailonly,allowimap" for user marijn@mydomain.com.

Actual access that is granted is worked out by processing the g_access_group rules in the order they are defined in surgemail.ini building up from no access. So if you want "suspendedemail" to override "allowpop" you need to make sure the "suspendedemail" g_access_group entry is after the "allowpop" g_access_group in the surgemail.ini file.

User access settings

There are many features provided in the user self management and domain administrator interfaces and it is common to want to enable or disable some or all of these features. SurgeMail uses user_access settings to do this, see g_user_access and g_admin_access for details on the various options.

Account Status

The account status field in the authentication database allows the domain controller to easily enable / disable individual mail accounts. This is the "Account Status" setting in the Web Admin interface (NWAuth field: mailstatus). This setting can have one of the following values:

 

Incoming SMTP

POP WEB IMAP Sending SMTP Response codes
ok,good Y Y Y Y Y  
suspended Y N N N N Account suspended.
cancelled N N N N N Account cancelled
banned,bad N N N N N This account has been banned for inappropriate use.
closed N N N N N Account closed.
paydue,due Y Y Y Y Y  
payup Y N N N N Please pay to continue service.
readonly N Y Y Y N Account is only allowed to read email.

These messages responses can be modified using the g_mailstatus_message:

g_mailstatus_message state="cancelled" message="Account cancelled,
    please email postmaster@mydomain.com for further information"

or adding an "id" field to the authentication database and using this to supply a customised URL for updating account information:

g_mailstatus_message state="payup" message="Payment is overdue
    for $full_name$, click http://myurl.com/cgi/mycgi.cgi?user=$id$ to update
    account"

Individual user bounce message setting: bounce_msg

In versions 3.8g-12 and later you can use bounce_msg, e.g.

C:\surgemail>nwauth -path .
       lookup test2@star
       +OK test2@star config 0 bounce_msg="please send to me@here.com"

Then when you send a message to that account you will get an smtp rejection:

550 Bounce_msg: please send to me@here.com


Restricting accounts to "local only"

You may want to setup a goup of users (eg students, untrusted staff etc) who should be able to email within themselves and email trusted staff accounts but not email other internet accounts. There are several possibilities for implementing this in surgemail. The easiest way is to implement this using g_user_send_rule / g_user_receive_rule rules:

1) Setup appropriate rules to allow inbound / outbound mail based on group membership and create an access group which you can use to apply these

g_user_receive_rule group="local" from="*@mydomain.com"
g_user_send_rule group="local" to="*@mydomain.com"
g_access_group group="local" access_pop="*" access_imap="*" access_smtp="*" access_incoming="*"

2) Assign membership of this group to the relevant accounts on the accounts page.

The rules above will allow accounts on mydomain.com that have "local" group membership to only send and receive mail to / from local accounts. Other possible relevant configuration options:

1) You could set this up as a separate "localonly" domain for easier management and configuration. In this case the rules are likely to be something like:

to allow sending between users and to main domain:

g_user_receive_rule group="local" from="*@localonly,*@mydomain.com"
g_user_send_rule group="local" to="*@localonly,*@mydomain.com"

to allow sending to main domain, but not between users:

g_user_receive_rule group="local" from="*@mydomain.com"
g_user_send_rule group="local" to="*@mydomain.com"

2) You may want to setup a restricted administrator account to allow user creation and addition and quota management but not change access group membership. In this case, make sure it setup as a separate localonly domain and then setup a rule something like:

g_authent_info_grp group="internal_manager" fields="none,quota" tag="dummy_tag"

and make sure the account to adminster these restricted accounts is a domain manager, and also has assigned internal_manager group priviliges.

3) A similar effect can be achieved with mfilter rules, but in this case full configuration is done in mfilter.rul and it has to be the main server administrator that makes any configuration changes.
eg:

recipients
  if (isin("from","fred@mydomain.com")) then
    if (!isin("recipient", "mydomain.com")) bounce "Sorry you can only send to mydomain.com"
  end if
end recipients