---
title: SAIF.Framework.Mail operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: SAIF Documentation Generator
last_reviewed: 2026-07-30
library: SAIF.Framework.Mail
reference_type: package
---

# SAIF.Framework.Mail operations and processes

`SAIF.Framework.Mail` exposes six operations through the shared `Mail` module: four public send operations that dispatch messages through the legacy `clsSAIFMessage.asmx` SOAP service, and two internal byte-conversion helpers that the attachment-sending operation relies on to turn a stream or a file into a payload the SOAP proxy can transmit. This page is the operation catalog and cross-operation hub for this library. Each operation's detailed, step-by-step logic lives in its own page under `operations/`.

## Operation catalog
| Operation | Intent | Trigger | Inputs | Outputs | Rules | Tables | SQL |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [Send subject-only email](operations/send-subject-only-email.md) | Send a message that carries only recipients and a subject, with no body text | Caller invokes `Mail.SendMail(inToAddress, inFromAddress, inSubject, [isHtml])` | Recipient address, sender address, subject, optional HTML flag | One `SendMail`/`SendMailAsText` SOAP request; function returns `True` | [BR-001](business-rules.md#br-001-mail-is-always-routed-through-the-configured-legacy-mail-service-url), [BR-002](business-rules.md#br-002-html-body-is-the-default-format), [BR-003](business-rules.md#br-003-send-operations-always-report-success-regardless-of-actual-outcome) | — | — |
| [Send email with body](operations/send-email-with-body.md) | Send a message that includes an explicit body | Caller invokes `Mail.SendMail(inToAddress, inFromAddress, inSubject, inMessage, [isHtml])` | Recipient address, sender address, subject, message body, optional HTML flag | One `SendMail`/`SendMailAsText` SOAP request; function returns `True` | [BR-001](business-rules.md#br-001-mail-is-always-routed-through-the-configured-legacy-mail-service-url), [BR-002](business-rules.md#br-002-html-body-is-the-default-format), [BR-003](business-rules.md#br-003-send-operations-always-report-success-regardless-of-actual-outcome) | — | — |
| [Send email with options](operations/send-email-with-options.md) | Send a message that may carry attachments and/or linked resources | Caller invokes either overload of `Mail.SendMailWithOptions(...)` | Recipient address, sender address, subject, optional message body, HTML flag, optional attachment/linked-resource arrays | One `SendEmail` SOAP request; function returns `True` | [BR-001](business-rules.md#br-001-mail-is-always-routed-through-the-configured-legacy-mail-service-url), [BR-003](business-rules.md#br-003-send-operations-always-report-success-regardless-of-actual-outcome) | — | — |
| [Send email with attachment](operations/send-email-with-attachment.md) | Send a message that carries exactly one attachment, regardless of how the caller supplied it | Caller invokes any overload of `Mail.SendMailWithAttachment(...)` | Recipient address, sender address, subject, optional message body, one attachment source (`Stream`, file path, or `Byte()`), attachment name | Attachment converted to bytes when needed; one `SendWithAttach` SOAP request; function returns `True` | [BR-001](business-rules.md#br-001-mail-is-always-routed-through-the-configured-legacy-mail-service-url), [BR-003](business-rules.md#br-003-send-operations-always-report-success-regardless-of-actual-outcome), [BR-004](business-rules.md#br-004-file-handles-are-always-released-but-the-original-exceptions-stack-trace-is-reset), [BR-005](business-rules.md#br-005-a-nothing-stream-input-yields-a-nothing-byte-array-instead-of-an-exception) | — | — |
| [Read a file into bytes](operations/read-file-into-bytes.md) | Convert a file on disk into the byte payload the SOAP proxy expects for an attachment | Attachment pipeline calls `GetFileAsBytes(inPath)` | File system path | `Byte()` payload, or a propagated exception | [BR-004](business-rules.md#br-004-file-handles-are-always-released-but-the-original-exceptions-stack-trace-is-reset) | — | — |
| [Read a stream into bytes](operations/read-stream-into-bytes.md) | Convert a stream into the byte payload the SOAP proxy expects for an attachment | Attachment pipeline calls `GetStreamAsBytes(inStream)` | Open `Stream` reference (or `Nothing`) | `Byte()` payload, or `Nothing` when no stream was supplied | [BR-005](business-rules.md#br-005-a-nothing-stream-input-yields-a-nothing-byte-array-instead-of-an-exception) | — | — |

## Process flow diagram
The following diagram visualizes how a caller's choice of send operation and attachment source funnels into a single dispatch-and-return pattern shared by every operation in this library.

```mermaid
flowchart TD
    Start([Caller invokes a Mail send operation]) --> Select[Select send overload]
    Select --> Resolve[Resolve legacyMailServiceUrl]
    Resolve --> Attachment{Attachment source supplied?}
    Attachment -->|No| Dispatch[Call SendMail / SendMailAsText / SendEmail]
    Attachment -->|Stream| StreamBytes[Read stream into bytes]
    Attachment -->|File path| FileBytes[Read file into bytes]
    Attachment -->|Byte array| DispatchAttach[Call SendWithAttach]
    StreamBytes --> DispatchAttach
    FileBytes --> DispatchAttach
    Dispatch --> Dispose[Dispose SOAP proxy]
    DispatchAttach --> Dispose
    Dispose --> Done([Return True])
```

## Inherited operations and processes

Operations in this section originate from base classes or services provided by dependency framework libraries. They are inherited or delegated, not implemented in this library.

### From `EnvironmentServiceBase` (`SAIF.Framework.Security.EnvironmentApi`)

| Operation | Intent | Provided by | Origin | Embedded in |
| --- | --- | --- | --- | --- |
| Retrieve a configuration setting | Resolve `legacyMailServiceUrl` from developer overrides, cached configuration, or the loaded Environment API configuration | `IEnvironmentService.GetConfigSetting` | `SAIF.Framework.Security.EnvironmentApi` | [Send subject-only email](operations/send-subject-only-email.md), [Send email with body](operations/send-email-with-body.md), [Send email with options](operations/send-email-with-options.md), [Send email with attachment](operations/send-email-with-attachment.md) |

> **Origin**: This operation is defined in [SAIF.Framework.Security.EnvironmentApi](../saif-framework-security-environmentapi/operations-processes.md#retrieve-a-configuration-setting) and its step-by-step logic is embedded inline (with `> Origin` callouts) in the consuming operation detail pages.

## Failure and edge-case behavior
- Every send operation returns `True` once its dispatch path completes; none of them inspects a response value from the remote service, so the return value cannot be used to detect a silent delivery failure.
- `GetFileAsBytes` and `GetStreamAsBytes` both size their buffers using `Length` as a VB array upper bound rather than an element count, so each resulting byte array carries one extra, zero-initialized trailing byte.
- `GetStreamAsBytes` reads starting at the stream's current position rather than rewinding it first, so a partially consumed stream produces a payload that is only partially populated.
- `GetFileAsBytes` closes its `FileStream` unconditionally in a `Finally` block; if the stream is never successfully opened, that cleanup step can itself raise a `NullReferenceException`.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [Configuration](configuration.md)
- [API reference](api/index.md)

## Sources
- SAIF.Framework.Mail\MailServices.vb
- SAIF.Framework.Mail\Web References\SAIFMail\Reference.vb
- SAIF.Framework.Security\AppGlobal.vb
- SAIF.Framework.Security.EnvironmentApi\Core\Services\IEnvironmentService.cs
- SAIF.Framework.Security.EnvironmentApi\Services.Common\EnvironmentServiceBase.cs
