Basic setup for multiple customers

I have a basic on-prem instance of RT that I’ve set up, and I’m still getting a feel for the UI.

My team needs to organize everything coming in at a customer level. We have multiple people at multiple customers that will interact with RT through email only. My team needs to be able to pull up a customer and see stats like the tickets for that customer, etc.

I’ve seen references in this forum to using separate queues for each customer. Would we need to have a separate helpdesk email for each customer to do this? Ideally I’d like to have a single email address, and some sort of way to sort the incoming tickets into the queue or other organizational system, preferably with as much automation as possible. I am currently attempting to compose a scrip that checks an incoming ticket requestor’s email domain. If the domain is new to RT, create a queue and a group, and add the user and the ticket to them. If it’s not a new domain, add the ticket to the existing queue, etc. I don’t really speak Perl, so this is slow going.

Am I on the right track here? Or is there a better way to do this?

Hi, RWM.
I suggest to configure filters in the email server to move incoming emails to specific folders based on these rules (domain in From: or whatever header/condition).
Then, you can fetch mails from every folder to the corresponding queue. Inbox will remain for unclassified emails and created to the default queue.

1 Like

Depends on your needs. You could also assign a CustomField with the customer name (or domain). Or have saved searches where you search based on domain.

1 Like

Your scrip idea should work. Your queue creation would of course have to not only create the queue but give your privileged users suitable rights to it (maybe via group membership and/or creating new groups and populating those with users). You also run the risk of creating lots of random queues if your system is internet facing and can get spam.

1 Like

The original meaning of a queue is the representation of a team working on the same type of tasks. We count about 45k customer, so a queue for each one is no option at all.

We use a CustomField “Customer-ID” to manage and report everything regarding the customer. So with the ID one can jump via deeplink direct into the CRM.
In our CRM we show tickets in the context of the customer via RT API. So every time one look at the customer in the CRM he or she see all tickets.

With a little javascript we show customers name and other information in RT based on the ID.

In the early time there were no connectin to the CRM. At that time we did a search in RT with the ‘Customer-ID’ to see all tickets belonging to a customer regardless which queue they are .
For comfort we linked the search to the Custom Field shown in the ticket. So you can see all tickets belongig to a customer in just with one click.

(We have queues for customer-side Installation, Incident-Management, ACL-Requests, email-configuration, domaintransfer and so on. So if we would have a queue per customer one has to organize the task with CustomFileds an monitor all queues for requests.)

It is possible to use the domain-part of the requestor as CustomField and fill it on arrival of an email. If you can ask another organizational system for (email, ID) you can insert an ID instead.

1 Like

We do it with a custom field as Andrew_Ruthven suggests. Currently that’s set manually as there’s no first-order customer/organisation object in RT that can be easily searched - but whilst writing this I’ve suddenly wondered if we could emulate that using an Asset category…
The Scrip would then do

  • Get email domain from incoming email
  • Lookup an appropriate Asset
  • Assign Custom Field
  • If no match - leave blank for manual investigation

Hmm, I see some experimentation coming on :slight_smile:

/time passes

Yes - I think it would work - I’ve tested creating a Catalog for Clients, and some relevant custom fields that I add only to that catalog, namely client name, client custom field id, domain name. I can control who accesses that catalog if necessary, and I can write scrip to do the lookup during the create phase of a ticket. The limitation is that one email domain can only be associated with one client ID custom field in Tickets. But that’s not a huge hardship to overcome.

If I can get the Scrip to work I’ll post a blog about it somewhere and link it back here.

Thank you to the OP for the inspiration for this idea :slight_smile:

2 Likes

Thanks for the replies. I’m fairly new to RT, but since it’s already been sort of pre-chosen as a part of our stack, I went ahead and signed up for a support contract from bestpractical.

I’ve been speaking to a support rep there. His recommendation was a single queue, with groups for each customer, and a custom role called “Customer”, with a scrip that routes tickets to the role/group based on some criteria (I’m pulling the domain out of the requestor email). I don’t speak Perl natively, but I’m starting to learn real quick since that seems to be all that’s in my way of getting this running.

My idea is to have a scrip that runs On Create Via Email, then pulls the domain out of the email address. If it’s a new domain, create a group and add the requestor to the group, and the group to the Customer role. Sounds good in my head, but I haven’t made it too far on the scrip yet. I’ve been leaning on ChatGPT to help me with the Perl (please hold your laughter). At this point, I’ve ironed out enough bugs so that it’s not throwing errors to syslog anymore, but it’s not making the group or anything. If anyone feels like diving in to my @#$% code, I’ll, I dunno Venmo you for a beer or something. :smile:

So in my scrip, I have Condition set to ‘On create via Email’, and I have the following code all contained within the ‘Custom action preparation code’ section. I have no idea if that’s the right way to do it. Again, pretty new at this. Here is the code I have so far. I started passing the variables to syslog just to check them. They look OK so far (which is to say none of them are erroring or returning as null), but at the moment I’m going back through and fixing the ones that give you a hash instead of the value I want. Any help would be SO appreciated!!!

# Get the current transaction
my $txn = $self->TransactionObj;

RT::Logger->debug("txn value: $txn");

# Check if the transaction is a Create ticket transaction
if ($txn->Type eq 'Create') {
    # Get the newly created ticket
    my $ticket = $self->TicketObj;
    RT::Logger->debug("ticket value: $ticket");


    # Get the requestor's email address
    my $requestor_email = $ticket->Requestors->UserMembersObj->First->EmailAddress;
    RT::Logger->debug("requestor_email value: $requestor_email");

    # Extract the domain from the requestor's email address
    my ($requestor_username, $requestor_domain) = $requestor_email =~ /^(.+)@(.+)$/;
    RT::Logger->debug("requestor_username value: $requestor_username");
    RT::Logger->debug("requestor_domain value: $requestor_domain");

    # Check if the extraction was successful
    if ($requestor_username && $requestor_domain) {
        # Find or create a group for the requestor
        my $group_name = "Customer_$requestor_domain";
        RT::Logger->debug("group_name value: $group_name");

        my $group = RT::Group->new($RT::SystemUser);
        RT::Logger->debug("group value: $group->Name");
        $group->LoadUserDefinedGroup($group_name);

        unless ($group->Id) {
            # Create the group with the specified domain
            $group->CreateUserDefinedGroup(
                Name        => $group_name,
                Description => "Group for customer $requestor_email",
                Domain      => $requestor_domain,
                Type        => 'UserDefined',
            );

            # Add the requestor to the group
            $group->AddMember($ticket->Requestors->UserMembersObj->First->Id);
        }

        # Add the group to the "Customer" role
        $ticket->AddWatcher(
            Type  => 'Group',
            PrincipalId => $group->PrincipalId,
            Role  => 'Customer',
        );
    } else {
        RT::Logger->error("Failed to extract domain from requestor's email address: $requestor_email");
    }
}

return 1;

Looking at the logic of your scrip, will only the first user from a customer domain be added to the group? The AddMember() method call is inside the conditional that creates the group. Of course this might be what you want, but if you want subsequent users from that customer to also go in the same group you’ll need the AddMember() outside of the unless block (you’re not checking the return from AddMember() so it won’t matter if it “fails” with a Group already has member error).

The RT::Group::CreateUserDefinedGroup() method only takes two parameters for the Name and Description. Internally it calls a _Create() routine that does have a Domain parameter, but that is set to UserDefined by the CreateUserDefinedGroup() method and used for name uniqueness validation. So ditch Domain and Type in your call.

You might not have to check the transaction type as your already doing an OnCreate condition but it shouldn’t hurt to leave it there.

1 Like