---
title: Send email with options
summary: Sends a message through the `SendEmail` SOAP endpoint, allowing callers to attach optional attachments and linked resources without any library-local transformation of those arrays.
status: draft
owner: SAIF Documentation Generator
last_reviewed: 2026-07-30
library: SAIF.Framework.Mail
reference_type: package
operation_id: MAIL-OP-003
trigger: Caller invokes either `Mail.SendMailWithOptions(...)` overload.
---

# Send email with options

This operation is the richest send path in the library: it targets the `SendEmail` SOAP method, which — unlike the plain `SendMail`/`SendMailAsText` methods — accepts arrays of attachments and linked resources (such as inline images referenced from an HTML body). The two public overloads differ only in whether the caller supplies a message body; both funnel into the same dispatch logic.

| Field | Value |
| --- | --- |
| **Operation ID** | MAIL-OP-003 |
| **Trigger** | Caller invokes either `Mail.SendMailWithOptions(...)` overload. |
| **Inputs** | `inToAddress`, `inFromAddress`, `inSubject`, optional `inMessage`, `isHtml`, optional `SAIFMail.clsAttachment()` and `SAIFMail.clsLinkedResource()` arrays. |
| **Outputs** | SOAP dispatch to `SendEmail`; the function returns `True`. |
| **Primary components** | `Mail.SendMailWithOptions`, `SAIFMail.clsSAIFMessage`, `AppGlobal.EnvironmentService` |
| **Entry point** | `SAIF.Framework.Mail\MailServices.vb` |

## Steps

1. If the caller used the overload that omits `inMessage`, delegate immediately to the full overload, passing `String.Empty` as the body.
2. In the full overload, create a new `SAIFMail.clsSAIFMessage` SOAP client.
3. Look up the mail endpoint by calling `AppGlobal.EnvironmentService.GetConfigSetting("legacyMailServiceUrl")` and assign the result to the proxy's `Url` property ([BR-001](../business-rules.md#br-001-mail-is-always-routed-through-the-configured-legacy-mail-service-url)).
   - `AppGlobal.EnvironmentService` lazily selects the environment-service implementation appropriate to the current host context.
   - `GetConfigSetting` refreshes configuration as needed and returns the resolved `legacyMailServiceUrl` value from overrides or cached configuration.
   - If the key cannot be resolved, execution ends by exception before `SendEmail` is ever invoked.

   > **Origin**: Steps 3.1–3.3 are implemented in [Retrieve a configuration setting](../../saif-framework-security-environmentapi/operations/retrieve-configuration-setting.md) (`SAIF.Framework.Security.EnvironmentApi`) and are executed on behalf of this operation.
4. Call `SendEmail(inToAddress, inFromAddress, inSubject, inMessage, isHtml, attachments, linkedResources)`.
   - `attachments` and `linkedResources` are forwarded to the SOAP proxy exactly as supplied — the operation performs no local inspection, deduplication, or size validation of either array.
   - If either optional array is `Nothing`, that `Nothing` value passes through to the proxy unchanged.
5. Dispose the SOAP proxy and clear the module-level reference.
6. Return `True` once the dispatch path completes ([BR-003](../business-rules.md#br-003-send-operations-always-report-success-regardless-of-actual-outcome)).
   - On failure: exceptions from configuration lookup or the SOAP call propagate to the caller, because this method has no `Try...Catch` block.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start([SendMailWithOptions call]) --> Body{Message overload used?}
    Body -->|No body overload| Delegate[Delegate with String.Empty]
    Body -->|Body overload| Proxy[Create clsSAIFMessage]
    Delegate --> Proxy
    Proxy --> Url[Resolve legacyMailServiceUrl]
    Url --> Send[Call SendEmail]
    Send --> Dispose[Dispose proxy]
    Dispose --> End([Return True])
```

## Failure and edge-case behavior

- Neither the attachment array nor the linked-resource array is normalized, deduplicated, or size-checked before it reaches the SOAP proxy; any such validation would have to happen on the caller's side.
- The no-body overload adds no behavior of its own beyond substituting `String.Empty` before delegating to the full overload.
- There is no fallback or retry logic in `MailServices.vb` if endpoint resolution fails — the operation simply fails outward to the caller.

## Related documentation
- [Operations and processes](../operations-processes.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
