How to pragmatically set registered user status to pending and then manually send activation email
So, for the part preventing the activation, don't use:

if (Craft::$app-&gt;request-&gt;getIsSiteRequest())

Just do:

Event::on(
    Users::class,
    Users::EVENT_BEFORE_ACTIVATE_USER,
    function(Event $event){
        $formName = Craft::$app-&gt;getRequest()-&gt;post('group');
        if ($formName==='ypo' || $formName==="yp") {
           $event-&gt;isValid = false;
        }
    }
);


For the other part:

Event::on(
Elements::class,
Elements::EVENT_AFTER_SAVE_ELEMENT,
    function(Event $event){
        // Check it's a front end request
        if (Craft::$app-&gt;request-&gt;getIsSiteRequest()) {
            if($event-&gt;element instanceof \craft\elements\User) {
                $user = $event-&gt;element;
                if($event-&gt;isNew) {
                    $user-&gt;unverifiedEmail = $user-&gt;email;
                    Craft::$app-&gt;getElements()-&gt;saveElement($user, false);
                    $formName = Craft::$app-&gt;getRequest()-&gt;post('group');

                    if($formName==='ypo') {
                        Craft::$app-&gt;getUsers()-&gt;assignUserToGroups($user-&gt;id, [1]);
                    }
                    if($formName==='yp') {
                        Craft::$app-&gt;getUsers()-&gt;assignUserToGroups($user-&gt;id, [2]);
                        $emailSent = Craft::$app-&gt;getUsers()-&gt;sendActivationEmail($user);    
                    }
                }
            }
        }
    }
);


Because you don't enforce email verification in control panel/user settings, you are skipping populating the unverifiedEmail field for the new user which is done here and that was part of the issue too :)