Skip to content

Send email with attachment

This operation is the library's single-attachment send path. Four public overloads let a caller supply the attachment as an open Stream, a file path, or an already-loaded Byte() array, with or without a message body; all four converge on the same SendWithAttach SOAP call once the attachment has been normalized to bytes.

Field Value
Operation ID MAIL-OP-004
Trigger Caller invokes any Mail.SendMailWithAttachment(...) overload.
Inputs inToAddress, inFromAddress, inSubject, optional inMessage, one attachment source (Stream, file path, or Byte()), and inAttachName.
Outputs An attachment byte payload for SendWithAttach; SOAP dispatch; the function returns True.
Primary components Mail.SendMailWithAttachment, GetStreamAsBytes, GetFileAsBytes, SAIFMail.clsSAIFMessage, AppGlobal.EnvironmentService
Entry point SAIF.Framework.Mail\MailServices.vb

Steps

  1. Determine the message body from the overload the caller selected.
  2. The stream/no-body overload always uses String.Empty as the message; it accepts no body parameter.
  3. The stream/body, file/body, and byte-array/body overloads forward the caller-supplied inMessage unchanged.
  4. Normalize the attachment source into the byte array SendWithAttach requires.
  5. For the stream overloads, call the local GetStreamAsBytes(inStream) helper (BR-005).

    • If inStream Is Nothing, the helper returns Nothing immediately rather than raising an exception (BR-005).
    • Otherwise the helper allocates a buffer sized from inStream.Length and reads starting at the stream's current position.

    Origin: These sub-steps are implemented in Read a stream into bytes and are executed on behalf of this operation. - For the file-path overload, call the local GetFileAsBytes(inFilePath) helper (BR-004). - The helper opens the file, allocates a buffer sized from FS.Length, reads the file's bytes, and closes the stream in Finally regardless of outcome (BR-004). - If opening or reading the file raises an exception, the helper re-throws it with Throw ex (BR-004).

    Origin: These sub-steps are implemented in Read a file into bytes and are executed on behalf of this operation. - For the byte-array overload, the caller-supplied inAttachment array is forwarded unchanged — no copy, validation, or size check is performed. 3. Create a new SAIFMail.clsSAIFMessage SOAP client. 4. Look up the mail endpoint by calling AppGlobal.EnvironmentService.GetConfigSetting("legacyMailServiceUrl") and assign the result to the proxy's Url property (BR-001). - AppGlobal.EnvironmentService lazily instantiates the environment-service implementation appropriate to the current execution context. - GetConfigSetting returns the resolved setting value from an override or cached configuration data, or throws if the key cannot be found.

Origin: Steps 4.1–4.2 are implemented in Retrieve a configuration setting (SAIF.Framework.Security.EnvironmentApi) and are executed on behalf of this operation. 5. Call SendWithAttach(inToAddress, inFromAddress, inSubject, message, attachmentBytes, inAttachName). 6. Dispose the SOAP proxy and clear the module-level reference. 7. Return True once the dispatch path completes (BR-003). - On failure: exceptions from attachment normalization, configuration lookup, or the SOAP call itself all propagate to the caller unmodified, because this method never catches them.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([SendMailWithAttachment call]) --> Source{Attachment source}
    Source -->|Stream| Stream[Read stream into bytes]
    Source -->|File path| File[Read file into bytes]
    Source -->|Byte array| Bytes[Reuse caller bytes]
    Stream --> Proxy[Create clsSAIFMessage]
    File --> Proxy
    Bytes --> Proxy
    Proxy --> Url[Resolve legacyMailServiceUrl]
    Url --> Send[Call SendWithAttach]
    Send --> Dispose[Dispose proxy]
    Dispose --> End([Return True])

Failure and edge-case behavior

  • Both byte-conversion helpers size their buffer with Length as a VB array upper bound rather than an element count, so an attachment converted from a stream or a file always carries one extra, zero-valued trailing byte.
  • Neither helper rewinds its source before reading; a stream that has already been partially consumed produces an attachment payload that is only partially populated, and there is no compensating logic in this operation.
  • A Nothing stream input becomes a Nothing attachment array rather than an exception, so SendWithAttach can be invoked with no attachment data even though an attachment overload was selected.
  • The operation always calls SendWithAttach; it never selects the generated proxy's SendWithAttachAsText method, so there is no plain-text-specific attachment path distinct from the one described here.

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