---
title: MX record lookup
summary: Resolves a domain's mail-exchanger records and returns them ordered by preference.
status: draft
owner: SAIF Documentation
last_reviewed: 2026-07-30
library: SAIF.Framework.DNS
reference_type: package
operation_id: OP-DNS-001
trigger: Caller invokes Resolver.MXLookup
---

# MX record lookup

This operation is the library's dedicated convenience path for mail-exchanger resolution. Rather than asking callers to assemble a `Question` themselves, it builds a single MX query, delegates the network round trip to [Generic DNS lookup](generic-dns-lookup.md), then narrows and orders the reply so the caller receives a ready-to-use, preference-sorted list of mail exchangers.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-DNS-001 |
| **Trigger** | Caller requests MX records for a domain |
| **Inputs** | `domain`, `dnsServer` |
| **Outputs** | Sorted `MXRecord[]` (or `null`); may throw `ArgumentNullException`, `ArgumentException`, `ArgumentOutOfRangeException`, `NoResponseException`, or `InvalidResponseException` |
| **Primary components** | `Resolver.MXLookup`, `Request`, `Question`, `Resolver.Lookup`, `MXRecord.CompareTo` |
| **Entry point** | `SAIF.Framework.DNS\Resolver.cs` |

## Steps

1. Confirm that `domain` and `dnsServer` are not null before any request object is created ([BR-001](../business-rules.md#br-001-lookup-arguments-must-not-be-null)).
   - On failure: throw `ArgumentNullException` and stop; no request is sent.
2. Create a new `Request`, taking the class defaults of recursion-desired querying and the standard-query opcode.
3. Create a `Question` for the supplied `domain`, fixing the type to `DnsType.MX` and the class to `DnsClass.IN`.
   - The constructor rejects domain strings shorter than 1 character or longer than 255 characters ([BR-002](../business-rules.md#br-002-domain-name-length-must-be-1-255-characters)).
   - The constructor rejects an undefined or `None` `DnsType` ([BR-003](../business-rules.md#br-003-dnstype-must-be-a-defined-non-none-enum-value)).
   - The constructor rejects an undefined or `None` `DnsClass` ([BR-004](../business-rules.md#br-004-dnsclass-must-be-a-defined-non-none-enum-value)).
4. Add the question to the request, making it the only question in the outbound message.
5. Delegate to [Generic DNS lookup](generic-dns-lookup.md) to serialize, transmit, and parse the request/response round trip.
   - If the delegated lookup throws `NoResponseException` or `InvalidResponseException`, let the exception propagate unchanged to this operation's caller.
6. Check whether the returned `Response` is `null`.
   - If `null`: return `null` immediately, without inspecting any answers.
7. Walk `response.Answers` and retain only the entries whose runtime type is exactly `MXRecord`.
   - If an entry is any other record type: discard it and continue to the next answer.
8. Copy the retained MX entries into a typed `MXRecord[]`.
9. Sort the array with `Array.Sort`, which relies on `MXRecord.CompareTo` to place lower preference numbers first and to break equal-preference ties by descending domain-name comparison ([BR-008](../business-rules.md#br-008-mx-records-are-ordered-by-ascending-preference)).
10. Return the sorted `MXRecord[]` to the caller.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller invokes MXLookup]) --> V[Validate domain and dnsServer]
	V --> Q[Build Request with MX Question]
	Q --> L[Delegate to Generic DNS lookup]
	L --> D{Response is null?}
	D -->|Yes| EndNull([Return null])
	D -->|No| F[Filter Answers to MXRecord entries]
	F --> S[Sort by ascending preference]
	S --> EndOk([Return sorted MXRecord array])
```

## Failure and edge-case behavior

- A null `domain` or `dnsServer` fails immediately with `ArgumentNullException`, before any socket is opened.
- An out-of-range domain length, or an invalid `DnsType`/`DnsClass`, fails while the `Question` is being constructed.
- Answer entries that are not `MXRecord` are silently ignored rather than converted or reported.
- A successful response containing zero MX answers yields an empty array, which is distinct from the `null` returned when the underlying response itself is `null`.
- Any transport (`NoResponseException`) or parsing (`InvalidResponseException`) failure raised by the delegated lookup is returned to the caller unchanged.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- SAIF.Framework.DNS\Resolver.cs
- SAIF.Framework.DNS\Question.cs
- SAIF.Framework.DNS\MXRecord.cs
