def user(conn, sAMAccountName: str, newpass: str, ou: str = "DefaultOU", lifetime: int = 0):
    """
    Add a new user

    :param sAMAccountName: sAMAccountName for new user
    :param newpass: password for new user
    :param ou: Organizational Unit for new user
    :param lifetime: lifetime of new user in seconds, if non-zero creates it as a dynamic object
    """
    if ou == "DefaultOU":
        container = None
        for obj in next(
            conn.ldap.bloodysearch(conn.ldap.domainNC, attr=["wellKnownObjects"])
        )["wellKnownObjects"]:
            if "GUID_USERS_CONTAINER_W" == obj.binary_value:
                container = obj.dn
                break
        if not container:
            LOG.warning(
                "Default container for users not found, defaulting to CN=Users,"
                + conn.ldap.domainNC
            )
            container = "cn=Users" + conn.ldap.domainNC
        user_dn = f"cn={sAMAccountName},{container}"
    else:
        user_dn = f"cn={sAMAccountName},{ou}"

    attr = {
        "objectClass": ["top", "person", "organizationalPerson", "user"],
        "distinguishedName": user_dn,
        "sAMAccountName": sAMAccountName,
        "userAccountControl": 544,
        "unicodePwd": '"%s"' % newpass,
    }

    if lifetime > 0:
        attr["objectClass"].append("dynamicObject")
        attr["entryTTL"] = lifetime

    conn.ldap.bloodyadd(user_dn, attributes=attr)
    LOG.info(f"[+] {sAMAccountName} created")

    Add a new user

    :param sAMAccountName: sAMAccountName for new user
    :param newpass: password for new user
    :param ou: Organizational Unit for new user
    :param lifetime: lifetime of new user in seconds, if non-zero creates it as a dynamic object
    
bloodyAD/cli_modules/add.py