Table of Contents

Class Contact

Namespace
MailFathom.Domain.Contacts
Assembly
MailFathom.Domain.dll

Holds one person the book knows: their name, every address they use, and what the owner recorded about them.

public sealed class Contact
Inheritance
Contact
Inherited Members

Remarks

A contact is a person rather than an address, which is the whole reason the book exists rather than a list. One person uses a work address, a personal one, and an old one they still receive on; a record keyed on the address could not say those were the same person, so the record is the person and the addresses hang off them. Which address to use by default is the owner's choice, kept as PreferredAddress, never an ordering accident.

Matching is decided here and nowhere else. Two addresses name the same mailbox when NormalizedAddress is equal, which upper-cases the whole address rather than only its domain. RFC 5321 makes the local part case-sensitive and almost no provider honours that, so a rule that split Anna@example.test from anna@example.test would store one person twice for a distinction their mail server does not make. The cost is stated rather than hidden: a server that genuinely distinguishes them is served one contact where it has two mailboxes. Nothing else in the book compares addresses any other way, and the same value is what a stored row is indexed by.

It is an entity rather than a value: Id is what makes two records the same person, and every method here answers with a new instance carrying that same identity. Value equality would be the wrong question to be able to ask of it — two people with one name and one address are still two contacts if the owner recorded them as such.

Everything on this record but Id and Origin is personal data about a third party. It is never logged, never a metric dimension, and never written into a failure message; the identifier is what a failure names.

Fields

MaximumAddressCount

How many addresses one person may be recorded as using.

MaximumAddressLength

The greatest length one address may carry.

Properties

Addresses

Gets every address this person uses, the preferred one first and the rest in comparison order.

AmendedAt

Gets when this contact was last amended, which equals RecordedAt until one happens.

DisplayName

Gets the name the owner recorded for this person.

Id

Gets what addresses this person, which no amendment and no promotion ever changes.

Note

Gets what the owner wrote about this person, or null when they wrote nothing.

Origin

Gets how this contact came to be in the book, which decides who may amend it.

PreferredAddress

Gets the address to use when something addresses this person without naming which of theirs to use.

RecordedAt

Gets when this contact entered the book.

Methods

AmendedWith(ContactDisplayName, IReadOnlyCollection<EmailAddress>, EmailAddress, ContactNote?, DateTimeOffset)

Produces this contact with the parts an amendment replaced, keeping its identity, origin, and arrival.

Create(ContactId, ContactDisplayName, IReadOnlyCollection<EmailAddress>, EmailAddress, ContactNote?, ContactOrigin, DateTimeOffset, DateTimeOffset)

Builds a contact from what an owner or collection supplied, enforcing every invariant the book rests on.

Holds(EmailAddress)

Answers whether this person uses the given address.

IsAmendableBy(ContactOrigin)

Answers whether a writer of the given origin may amend this contact.

IsPromotableBy(ContactOrigin)

Answers whether a writer of the given origin may promote this contact.

PromotedToAsserted(DateTimeOffset)

Produces this contact as one the owner has taken responsibility for.