---
title: SAIF.Framework.Mail architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: <owner>
last_reviewed: 2026-07-23
library: SAIF.Framework.Mail
reference_type: package
---

# SAIF.Framework.Mail architecture

`SAIF.Framework.Mail` is a thin, stateless utility library that exposes a simplified static API (`Public Module Mail`) for sending email through a legacy ASMX/SOAP mail service (`clsSAIFMessage.asmx`). It contains no business objects or persistent state; every public function marshals parameters into a generated SOAP proxy call and returns.

## Responsibilities
- Provide a single, simplified entry point (`Public Module Mail`) for sending email with subject-only, subject+body, HTML/plain-text, and attachment (stream, file path, byte array) variants.
- Marshal caller-supplied parameters into calls against the generated `SAIFMail.clsSAIFMessage` SOAP proxy.
- Resolve the target mail service endpoint at call time from environment configuration (`legacyMailServiceUrl`) rather than using the design-time default baked into `app.config`/Settings.
- Provide small file/stream utility helpers (`GetFileAsBytes`, `GetStreamAsBytes`) used internally to prepare attachment byte arrays.

## Component boundaries
- **`Public Module Mail`** (`MailServices.vb`): the sole public-facing component. Exposes all `SendMail`/`SendMailWithOptions`/`SendMailWithAttachment` overloads and the two constants (`STANDARD_DISCLAIMER`, `DO_NOT_REPLY`). Holds no state between calls (each function instantiates and disposes its own proxy instance).
- **`SAIFMail.clsSAIFMessage`** (`Web References\SAIFMail\Reference.vb`): an auto-generated ASMX/SOAP client proxy (`Inherits System.Web.Services.Protocols.SoapHttpClientProtocol`) representing the remote legacy mail web service boundary. This is generated code, not hand-authored, and is treated as an external service client rather than a library component.
- **Configuration boundary**: endpoint resolution is delegated to `AppGlobal.EnvironmentService.GetConfigSetting("legacyMailServiceUrl")`, which is defined outside this library in [SAIF.Framework.Security](../saif-framework-security/overview.md)/[SAIF.Framework.Security.EnvironmentApi](../saif-framework-security-environmentapi/overview.md). `SAIF.Framework.Mail` only consumes this service; it does not define or host it.

## Interaction model
- Callers invoke one of the `Mail` module's public `Send*` functions directly; there is no factory, DI container, or session/state object involved.
- Each function follows the same fixed sequence: instantiate `SAIFMail.clsSAIFMessage` → override the proxy's `Url` from `AppGlobal.EnvironmentService.GetConfigSetting("legacyMailServiceUrl")` → invoke one SOAP operation (`SendMail`, `SendMailAsText`, `SendWithAttach`, or `SendEmail`) → dispose the proxy → return `True`.
- The module always returns `True` regardless of the SOAP call's actual outcome; no exception handling or success/failure branching surrounds the SOAP invocation itself.*
- Attachment-oriented overloads convert their input (stream, file path, or byte array) into a byte array via the internal `GetStreamAsBytes`/`GetFileAsBytes` helpers before invoking `SendWithAttach`.

The following diagram shows high-level component interactions.

```mermaid
flowchart TD
	A[Caller code] --> B[Public Module Mail<br>MailServices.vb]
	B --> C[AppGlobal.EnvironmentService<br>SAIF.Framework.Security]
	B --> D[SAIFMail.clsSAIFMessage<br>generated SOAP proxy]
	D --> E[Legacy ASMX mail service<br>clsSAIFMessage.asmx]
```

The following diagram shows the primary request/response sequence for a typical send operation.

```mermaid
sequenceDiagram
	participant Caller
	participant Mail as Public Module Mail
	participant Env as AppGlobal.EnvironmentService
	participant Proxy as clsSAIFMessage proxy
	participant Svc as Legacy ASMX mail service
	Caller->>Mail: SendMail(to, from, subject, [message], [isHtml])
	Mail->>Proxy: New clsSAIFMessage()
	Mail->>Env: GetConfigSetting("legacyMailServiceUrl")
	Env-->>Mail: endpoint URL
	Mail->>Proxy: Set Url
	Mail->>Proxy: SendMail / SendMailAsText / SendWithAttach / SendEmail
	Proxy->>Svc: SOAP request
	Svc-->>Proxy: SOAP response
	Proxy-->>Mail: (result not branched on)*
	Mail-->>Caller: True
```

## Design constraints
- No business object base classes (`clsBusinessBase`, `clsBusinessCollectionBase`, `IBusinessCriteria`) are used; this library is not a BOF data-access component.
- The library is stateless — every public function creates and disposes its own proxy instance rather than sharing a client across calls.
- The remote service endpoint must be resolvable via `AppGlobal.EnvironmentService.GetConfigSetting("legacyMailServiceUrl")` at runtime; this couples the library to the `SAIF.Framework.Security` layer for a single configuration key.
- The SOAP proxy (`clsSAIFMessage`) is generated code checked into the library via a classic ASMX Web Reference, not a NuGet package or project reference; it cannot be regenerated without the original WSDL tooling.
- No `.cs` files exist in this library; all source is VB.NET.

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

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- SAIF.Framework.Mail\MailServices.vb
- SAIF.Framework.Mail\SAIF.BOF.Framework.Mail.vbproj
- SAIF.Framework.Mail\app.config
- SAIF.Framework.Mail\Web References\SAIFMail\Reference.vb
- SAIF.Framework.Mail\My Project\Settings.Designer.vb
