[BUG?] Wrong `sys_groupid` in `mail_user` when created via Remote API

Discussion in 'Developers' Forum' started by fazelukario, Feb 26, 2025.

  1. fazelukario

    fazelukario Member

    When creating mailbox via ISPConfig Remote API `sys_groupid` set to 1 instead of 0.

    And it can't be updated with `mail_user_update` method or set explicitly when creating (`client_id` not set and `sys_userid` + `sys_groupid` manualy set).

    When created via GUI:
    upload_2025-2-26_2-44-56.png

    When created via API:
    upload_2025-2-26_2-45-25.png

    `client_id` is right and equal to 0.

    When looking in database table there is no users with "`sys_groupid` = 1", there only one user (admin) with "`sys_groupid` = 0", "`sys_userid = 1`" and "`client_id` = 0".

    @till Question is: Is this is ok? Does this affect the work?
     
  2. fazelukario

    fazelukario Member

    Same for `mail_spamfilter_user_add`
     
  3. variable99

    variable99 Member

    I extensively use API for mailbox creation. Show your code part where you create mailbox. For me there is no problems with IDs.
     
    Last edited: Feb 26, 2025
    till likes this.
  4. till

    till Super Moderator Staff Member ISPConfig Developer

    I guess the most likely reason is either an issue in the code that uses the API or some inconsistency in the dbispconfig database, which then leads to choosing the wrong group. We use the API e.g. for the Migration Tool too and there are no issues with generating permissions here.
     
  5. fazelukario

    fazelukario Member

    @variable99 @till There 100% no problem with code, because at the moment there no code, currently I'm testing and reversing API with postman (because ISPC API docs mess barely exist).

    Here's request body send to API:

    Code:
    curl --location 'https://ispc.domain.tld/remote/json.php?mail_user_add' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "session_id": "some_sessid",
        "client_id": 0,
        "params": {
            "server_id": 1,
            "email": "[email protected]",
            "login": "[email protected]",
            "password": "randompassword",
            "name": "remoteapitest",
            "uid": 5000,
            "gid": 5000,
            "maildir": "/var/vmail/domain.tld/remoteapitest",
            "maildir_format": "maildir",
            "quota": 0,
            "cc": "[email protected]",
            "homedir": "/var/vmail",
            "autoresponder": "n",
            "autoresponder_subject": "Out of office reply",
            "move_junk": "y",
            "purge_trash_days": 0,
            "purge_junk_days": 0,
            "postfix": "y",
            "access": "y",
            "disableimap": "n",
            "disablepop3": "n",
            "disabledeliver": "n",
            "disablesmtp": "n",
            "backup_interval": "weekly",
            "backup_copies": 4
        }
    }'
     
  6. variable99

    variable99 Member

    Here is snippet from working code in PHP:
    PHP:
            // add new email user
            
    $newEmailUser $this->panelServer
            
    ->with(
                [
                    
    'client_id' => $this->website->ispc_user_id,
                    
    'server_id' => 10,
                    
    'email' => $valid_data['email_address'] . '@' $this->website->domain,
                    
    'login' => $valid_data['email_address'] . '@' $this->website->domain,
                    
    'password' => $valid_data['password1'],
                    
    'name' => !empty($valid_data['sender_name']) && isset($valid_data['sender_name']) ? $valid_data['sender_name'] : $valid_data['email_address'],
                    
    'uid' => 5000,
                    
    'gid' => 5000,
                    
    'maildir' => '/var/vmail/' $this->website->domain '/' $valid_data['email_address'],
                    
    'quota' => 2147483648// 2 GB
                    
    'cc' => !empty($valid_data['send_incoming_copies']) && isset($valid_data['send_incoming_copies']) ? $valid_data['send_incoming_copies'] : '',
                    
    'homedir' => '/var/vmail',
                    
    'autoresponder' => !isset($valid_data['autoresponder_enable']) || $valid_data['autoresponder_enable'] === false 'n' 'y',
                    
    'autoresponder_start_date' => $valid_data['autoresponder_start_date'],
                    
    'autoresponder_end_date' => $valid_data['autoresponder_end_date'],
                    
    'autoresponder_text' => $valid_data['autoresponder_text'],
                    
    'autoresponder_subject' => $valid_data['autoresponder_title'],
                    
    'move_junk' => 'y',
                    
    'custom_mailfilter' => '',
                    
    'postfix' => 'y',
                    
    'access' => 'y',
                    
    'disableimap' => !isset($valid_data['disable_imap']) || $valid_data['disable_imap'] === false 'n' 'y',
                    
    'disablepop3' => !isset($valid_data['disable_pop3']) || $valid_data['disable_pop3'] === false 'n' 'y',
                    
    'disabledeliver' => isset($valid_data['enable_receiving']) && $valid_data['enable_receiving'] === true 'n' 'y',
                    
    'disablesmtp' => !isset($valid_data['disable_sending']) || $valid_data['disable_sending'] === false 'n' 'y',
                    
    'purge_trash_days' => 90,
                    
    'purge_junk_days' => 90,
                    
    'backup_interval' => isset($valid_data['mail_backups_enable']) && $valid_data['mail_backups_enable'] === true 'daily' '',
                    
    'backup_copies' => isset($valid_data['mail_backups_enable']) && $valid_data['mail_backups_enable'] === true '',
                ]
            )
            ->
    addMailuser()
            ->
    response();
    Your "client_id" is outside of Params.

    P.S. There is no need to "reverse" anything as there is very nice examples and sort of docs. Attached remoting_client zip where you will find most of the API examples and params. Everything else - just read API it-self. It is self-explanatory. Of course it is a LOT to be desired, but it covers ~80% of what ISPC can do from GUI.
    P.P.S. Attached also Helper class for API wrapper in PHP ispconfig3.zip. To initialize it like this:


    PHP:
    <?php

        
    public function prepareServer()
        {
            
    // get panel server data
            
    $server = new \Models\Servers();
            
    $server->load(['ispc_server_id = ?'1]);

            if (
    $server->dry()) {
                return 
    false;
            }

            return new \
    Helpers\ISPConfig3(
                [
                    
    'host' => 'https://' $server->hostname ':' $server->port,
                    
    'user' => $server->api_user,
                    
    'pass' => $server->api_password
                
    ]
            );
        }

    $this->panelServer $this->helper->prepareServer();

            
    // add new forwarder
            
    $newForward $this->panelServer
            
    ->with(
                [
                    
    'client_id' => $this->website->ispc_user_id,
                    
    'server_id' => 10,
                    
    'source' => $valid_data['forward_email_address'] . '@' $this->website->domain,
                    
    'destination' => $valid_data['forward_targets'],
                    
    'type' => 'forward',
                    
    'allow_send_us' => !isset($valid_data['send_as']) || $valid_data['send_as'] === false 'n' 'y',
                    
    'active' => !isset($valid_data['forward_enable']) || $valid_data['forward_enable'] === false 'n' 'y',
                ]
            )
            ->
    addMailForward()
            ->
    response();

    $newForward json_decode($newForwardtrue);
    <...>

     

    Attached Files:

    Last edited: Feb 26, 2025
    till likes this.
  7. fazelukario

    fazelukario Member

    @variable99 docs are unusable, according to them `client_id` should be outside of `params`.

    Also I've tried passing `client_id` inside `params` as you suggested but got the same result.
     
  8. fazelukario

    fazelukario Member

    @till Any ideas what's wrong?
     
  9. variable99

    variable99 Member

    What I have learned in past 2 years almost daily working with ISPC API - you must have patience and 99% of problems arrive of you do not understanding how API or ISPC itself works.

    Let's disassemble points of possible failure. Here is API portion which adds mail user:
    PHP:
    //* Add mail domain
        
    public function mail_user_add($session_id$client_id$params){
            global 
    $app;

            if (!
    $this->checkPerm($session_id'mail_user_add')){
                throw new 
    SoapFault('permission_denied''You do not have the permissions to access this function.');
                return 
    false;
            }

            
    // Email addresses must always be lower case
            
    $params['email'] = strtolower($params['email']);

            
    //* Check if mail domain exists
            
    $email_parts explode('@'$params['email']);
            
    $tmp $app->db->queryOneRecord("SELECT domain FROM mail_domain WHERE domain = ? AND domain NOT IN (SELECT SUBSTR(source,2) FROM mail_forwarding WHERE type = 'aliasdomain')"$email_parts[1]);
            if(
    $tmp['domain'] != $email_parts[1]) {
                throw new 
    SoapFault('mail_domain_does_not_exist''Mail domain - '.$email_parts[1].' - does not exist as primary.');
                return 
    false;
            }

            
    //* Set a few params to non empty values that will be overwritten by mail_plugin
            
    if (!isset($params['uid'])) $params['uid'] = -1;
            if (!isset(
    $params['gid'])) $params['gid'] = -1;
            if (!isset(
    $params['maildir_format'])) $params['maildir_format'] = 'maildir';

            
    $mailuser_id $this->insertQuery('../mail/form/mail_user.tform.php'$client_id$params'mail:mail_user:on_after_insert');
            return 
    $mailuser_id;
        }
    Take a look at the bottom of the func, it uses tform in '/usr/local/ispconfig/interface/web/mail/form'. Inspect your request and be sure that it is INT you have passing into client_id, not string or something undefined. Check your database.
    There is nothing magical happening here. Once you understand how flow of API takes place - you will be able to revert your CURL step-by-step.
     
  10. fazelukario

    fazelukario Member

    @variable99 As I say before, data is totally correct, `client_id` send as INT.
     
    Last edited: Feb 27, 2025
  11. variable99

    variable99 Member

    Well, than tough luck. Community will not solve your problem. Only you can debug it properly. You may try to buy membership for priority support.
     
  12. pyte

    pyte Well-Known Member HowtoForge Supporter

    Here is an working example:
    Code:
    #!/bin/bash
    
    set -e
    
    remote_user=APIUSER
    remote_password=APIUSERPASS
    remote_url='https://DOMAIN.TLD:8080/remote/json.php'
    
    restCall() {
        curl -sS -X POST -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d "${2}" "${remote_url}?${1}"
    }
    
    # Log in
    session_id=`restCall login "{\"username\": \"${remote_user}\",\"password\": \"${remote_password}\"}" | jq -r '.response'`
    if [[ $isession == "false" ]]; then
        echo "Login failed!"
        exit 1
    fi
    
    #restCall client_get "{\"session_id\": \"$session_id\",\"client_id\":{\"customer_no\": \"100000\"}}"
    
    restCall mail_user_add "{
        \"session_id\": \"$session_id\",
        \"client_id\": \"301\",
        \"params\": {
            \"server_id\": 1,
            \"email\": \"[email protected]\",
            \"login\": \"[email protected]\",
            \"password\": \"howtoforge\",
            \"name\": \"api\",
            \"uid\": 5000,
            \"gid\": 5000,
            \"maildir\": \"/var/vmail/DOMAIN.TLD/api\",
            \"quota\": 5242880,
            \"cc\": \"\",
            \"homedir\": \"/var/vmail\",
            \"autoresponder\": \"n\",
            \"autoresponder_start_date\": \"\",
            \"autoresponder_end_date\": \"\",
            \"autoresponder_text\": \"hallo\",
            \"autoresponder_subject\": \"Out of office reply\",
            \"move_junk\": \"n\",
            \"purge_trash_days\": \"0\",
            \"purge_junk_days\": \"0\",
            \"custom_mailfilter\": \"spam\",
            \"postfix\": \"n\",
            \"access\": \"n\",
            \"disableimap\": \"n\",
            \"disablepop3\": \"n\",
            \"disabledeliver\": \"n\",
            \"disablesmtp\": \"n\"
        }
    }"
    The sys_userid and sys_groupid were correctly set when I tested this in my setup. When using this script the according values are:
    sys_userid 2434
    sys_groupid 2433


    Using the panel as "admin":
    sys_userid 1
    sys_groupid 2433


    When using the customer login:
    sys_userid 2434
    sys_groupid 2433



    Seems fine to me
     
    till likes this.
  13. fazelukario

    fazelukario Member

    Thanks for response! But unfortunately I got the same result using your script, sys_userid 1 when using your script (and API in general) while creating with panel as "admin" sys_userid 0.
     

Share This Page