Recommended Approach for Email Classification Using Multiple Inbound Email Trigger Flows

ShumaS
Tera Contributor

Hello Community,

I would like to get feedback on the architecture of an inbound email processing solution.

## Background

We receive various types of emails that must be processed differently based on conditions such as sender, subject, and email content.

In addition, any email that does not explicitly match a defined processing rule should ultimately be classified as Junk.


## Proposed Architecture

I am considering implementing this using multiple Inbound Email Trigger Flows.

The system property `glide.hub.flow.inbound_email_trigger.show_advanced` would be enabled so that multiple flows can be configured and ordered.


### Processing Flow

1. An initial flow (Order = 0) receives the email and leaves it in the Inbox state.
2. Multiple business-specific flows (Order > 0) evaluate the email and perform their respective processing.
3. When a flow successfully processes the email, it updates the email status to `Received`.
4. A final flow (Order = 9999) evaluates the email:
- If the status is `Received`, no further action is taken.
- If the status is not `Received`, the email is classified as Junk.


### Goals

- Separate processing logic into independent flows.
- Simplify future maintenance and addition of new email-processing rules.
- Ensure that any email not matched by a processing rule is automatically treated as Junk.


## Questions


### 1. Is this architecture reasonable?

Has anyone implemented a similar pattern using multiple Inbound Email Trigger Flows?

In particular, are there any concerns with:

- Using the Order field to control processing sequence across multiple flows?
- Using the email status as a flag to indicate whether an email has already been processed?


### 2. Inbound Email Trigger Flow vs. Inbound Email Action

For this type of requirement, would you recommend:

- Inbound Email Trigger Flows
- Inbound Email Actions

I would appreciate recommendations from the perspectives of:

- Maintainability
- Scalability
- Processing order control
- Performance
- ServiceNow best practices


### 3. Status Update Visibility Across Flows

If multiple Inbound Email Trigger Flows are executed for the same email, can a later flow reliably determine whether an earlier flow has changed the email status (for example, to `Received`)?

Are there any transaction, execution-order, or timing considerations that could affect this design?

Any guidance, best practices, or alternative approaches would be greatly appreciated.


Thank you.

5 REPLIES 5

Tejas Adhalrao
Mega Sage

hi @ShumaS ,

I would suggest using multiple Inbound Email Trigger Flows if you want to keep the processing logic separated, but I would be careful with the proposed status-based approach.

A few things to consider:

  1. Execution order: Use the Order field to control the sequence, but don't assume that setting a higher order alone guarantees that all previous processing has completed in every scenario. Verify the execution behavior in your ServiceNow release.

  2. Email status: I would avoid using the email status as the only indicator that a particular business rule has processed the email. It is better to maintain an explicit processing result or matched-rule indicator if your design requires it.

  3. Final Junk flow: Before classifying an email as Junk, make sure all intended processing rules have had a chance to evaluate it. Otherwise, a valid email could be classified as Junk because of an execution or configuration issue.

  4. Flows vs. Inbound Email Actions: Flows are useful for separating business logic and making it easier to maintain. Inbound Email Actions are also a good option for traditional email processing, especially when you need to create or update records based on the sender, subject, or email body.

For your requirement, I would consider a central classification step that evaluates the email and identifies the matching processing rule, then routes it to the appropriate flow or action. If no rule matches, classify it as Junk after the classification is complete.

Before implementing this, I would test whether status changes made by one Inbound Email Trigger Flow are visible to subsequent flows in your specific release, including cases where a flow exits without matching the email.

 

Regards,

Tejas

Hello Tejas,

Thank you for your response.
 
I agree with your concerns regarding the status-based approach and I understand the recommendation to introduce a central classification step.
 
However, I would like to better understand the trade-offs between a centralized classification model and the alternative approach of multiple Inbound Email Trigger Flows with a final catch-all flow.
 
As discussed by Tarun Rekand, one possible architecture is:
 
Alternative:
- Multiple Inbound Email Trigger Flows, each responsible for a specific email-processing rule.
- A final catch-all flow that classifies unmatched emails as Junk.
 
Another approach is:
 
Centralized Classification:
- One central classification flow evaluates all conditions.
- The flow routes processing to the appropriate subflow/action.
- If no rule matches, the email is classified as Junk.
 
From a maintainability perspective, my impression is that the alternative approach offers stronger separation of concerns.
 
For example:
 
- Each email-processing rule exists in its own flow.
- A change to one business rule only affects the corresponding flow.
- Independent development and testing are easier.
- The risk of introducing regressions into unrelated email-processing logic is reduced.
 
By contrast, in a centralized classification flow:
 
- Every new rule requires modification of the central classifier.
- All routing conditions are maintained in a single place.
- As the number of email types grows, the classifier may become increasingly complex.
- A change to the routing logic potentially impacts a shared component used by every inbound email.
 
Because of these characteristics, my initial assumption is that the alternative approach may scale better from a maintenance and governance perspective.
 
Would you still recommend the centralized classification approach?
 
If so, could you explain the advantages it provides over the alternative architecture?
 
In particular, I would be interested in understanding whether you see benefits regarding:
 
- Reliability of execution
- Platform best practices
- Trigger evaluation behavior
- Flow ordering and determinism
- Operational support and troubleshooting
 
In other words, if the alternative architecture and the centralized classification architecture can both satisfy the functional requirements, what are the main reasons to prefer the centralized model?
 
Thank you for your insights.

Tarun Rekandar
Mega Guru

Hi @ShumaS ,

 

Architecture for inbound email processing with multiple Inbound Email Trigger Flows

Your goals—separation of logic, easy maintenance, and Junk as the default—are reasonable. However, I would change the mechanism.

The problem:

The design uses the email status as a shared flag between independent flows, and the final flow (Order = 9999) infers that nothing matched based on that flag. This approach is fragile for three reasons.

  1. Timing: Separate flows are not guaranteed to run sequentially, with each update committed before the next flow starts. The final flow could read the status before an earlier flow writes Received, causing a correctly processed email to be marked as Junk.

  2. Ownership of the field: The inbound email engine manages the email's type and state as processing finishes. A flow's update might be overwritten or conflict with the engine's processing.

  3. Silent failures: If a business flow fails halfway, the email may still appear unprocessed, causing the final flow to mark it as Junk and hide the underlying problem.

Also, test how Order behaves in your ServiceNow release. If the trigger uses first-match-wins behavior, a later flow might never execute after an earlier flow claims the email.

Recommended remedy: One dispatcher flow with subflows

  • Use a single Inbound Email trigger flow that evaluates the sender, subject, and body through If / Else If branches.

  • Each branch calls a sub-flow containing the relevant business logic.

  • The final Else branch handles unmatched emails and marks them as Junk.

  • This avoids using email status as a shared flag and makes the routing logic easier to maintain.

  • When adding a new rule, add a branch and a corresponding sub-flow.

  • If the rules grow, consider using a rules table containing sender patterns, subject patterns, and routing information.

Alternatives

Separate flows plus a catch-all:
Keep the specific flows and add a final flow without conditions that marks unmatched emails as Junk. Use this approach only after verifying the trigger execution and ordering behavior in your release.

Inbound Email Actions:
Use ordered actions with Stop processing enabled where appropriate, followed by a catch-all action that handles unmatched emails. Verify the behavior in your instance.

Answers to your questions
1. Is it reasonable?

The goals are reasonable, but using email status as an indicator that another flow has processed the email is risky. Use ordering only after confirming how the trigger handles multiple matching flows.

 

2. Flows or Actions?

  1. Maintainability: Flows offer visual logic and reusable sub-flows.

  2. Order control: Inbound Email Actions provide established ordering and Stop processing behavior.

  3. Performance: Both can work well at normal email volumes.

  4. Best practice: Choose one mechanism for a given routing process to avoid conflicts between flows and actions.

3. Can a later flow reliably see an earlier flow's status change?

Do not assume that it can. Execution timing, transaction behavior, and the inbound email engine's handling of status fields can affect the result.

 

If you need to keep separate flows, consider a dedicated custom field or tracking table. However, this does not automatically eliminate timing issues. A single dispatcher with subflows provides a more centralized approach.

 

Regards,

Tarun

Hello tarunrekand,

Thank you for the detailed explanation.
I understand the concerns regarding using the email status as a shared processing flag, and I agree that approach may not be reliable.
 
However, I would like to better understand your recommendation of "One dispatcher flow with subflows" compared to the alternative approach you mentioned ("Separate flows plus a catch-all").
My current preference is the alternative approach using multiple Inbound Email Trigger Flows and a final catch-all flow that classifies unmatched emails as Junk.
 
The reason is maintainability and isolation of change.
 
With a dispatcher pattern, every time a new email-processing rule is added or an existing condition is modified, the central dispatcher flow must be updated. This means a change to one routing condition affects a shared component that is used by all email-processing scenarios.
 
By contrast, with separate flows:
 
- Each email-processing rule can be implemented in its own flow.
- Changes are isolated to the specific flow being modified.
- The risk of unintentionally impacting unrelated email-processing logic is reduced.
- Development and testing can be performed more independently.
 
Because of this, my initial impression is that the "Separate flows plus a catch-all" approach may provide better modularity and lower maintenance risk as the number of email-processing rules grows.
 
Could you elaborate on why you would still recommend the dispatcher pattern over separate flows plus a catch-all?
 
Specifically, are there technical advantages related to:
 
- Execution reliability
- Trigger evaluation behavior
- Performance
- Flow ordering
- Platform best practices
 
that would outweigh the maintainability benefits of keeping the flows separate?
 
Thank you.