Skip to main content
************* PRERELEASE CONTENT *************
Previous sectionNext section

Using the Email Outbound Adapter

This chapter describes the behavior of the email outbound adapter (EnsLib.EMail.OutboundAdapter) and describes how to use this adapter in your productions. It discusses the following topics:

For settings not listed in this book, see “Settings in All Productions” in Managing Productions Productions.

Overall Behavior

Within a production, an outbound adapter is associated with a business operation that you create and configure. The business operation receives a message from within the production, looks up the message type, and executes the appropriate method. This method usually executes methods of the associated adapter.

The email outbound adapter (EnsLib.EMail.OutboundAdapter) provides settings that you use to specify the following:

  • The SMTP server to connect to and login details needed for that server, if any.

  • The default address to send email from (the From: header).

  • Recipients to add to any messages sent by the adapter, in addition to any hardcoded recipients.

It provides methods to do the following three actions:

  • Add a recipient to the To: list.

  • Add a recipient to the Cc: list.

  • Send a message.

Creating a Business Operation to Use the Adapter

To create a business operation to use the EnsLib.EMail.OutBoundAdapter, you create a new business operation class. Later, add it to your production and configure it.

You must also create appropriate message classes, if none yet exist. See “Defining Messages” in Developing Productions.

The following list describes the basic requirements of the business operation class:

  • Your business operation class should extend Ens.BusinessOperation.

  • In your class, the ADAPTER parameter should equal EnsLib.EMail.OutboundAdapter.

  • In your class, the INVOCATION parameter should specify the invocation style you want to use, which must be one of the following.

    • Queue means the message is created within one background job and placed on a queue, at which time the original job is released. Later, when the message is processed, a different background job will be allocated for the task. This is the most common setting.

    • InProc means the message will be formulated, sent, and delivered in the same job in which it was created. The job will not be released to the sender’s pool until the message is delivered to the target. This is only suitable for special cases.

  • Your class should define a message map that includes at least one entry. A message map is an XData block entry that has the following structure:

    XData MessageMap
    {
    <MapItems>
      <MapItem MessageType="messageclass">
        <Method>methodname</Method>
      </MapItem>
      ...
    </MapItems>
    }
    
    Copy code to clipboard
  • Your class should define all the methods named in the message map. These methods are known as message handlers. Each message handler should have the following signature:

    Method Sample(pReq As RequestClass, Output pResp As ResponseClass) As %Status
    Copy code to clipboard

    Here Sample is the name of the method, RequestClass is the name of a request message class, and ResponseClass is the name of a response message class. In general, these methods will refer to properties and methods of the Adapter property of your business operation.

  • For other options and general information, see “Defining a Business Operation Class” in Developing Productions.

The following example shows the general structure that you need:

Class EEMA.NewOperation1 Extends Ens.BusinessOperation 
{
Parameter ADAPTER = "EnsLib.EMail.OutboundAdapter";

Parameter INVOCATION = "Queue";

Method SampleCall(pRequest As Ens.Request,
                  Output pResponse As Ens.Response) As %Status
{
  Quit $$$ERROR($$$NotImplemented)
}

XData MessageMap
{
<MapItems>
  <MapItem MessageType="Ens.Request">
    <Method>SampleCall</Method>
  </MapItem>
</MapItems>
}
}
Copy code to clipboard
Note:

Studio provides a wizard that you can use to create a business operation stub similar to the preceding. To access this wizard, click File —> New and then click the Production tab. Then click Business Operation and click OK.

Creating Message Handler Methods

When you create a business operation class for use with EnsLib.EMail.OutboundAdapter, typically your biggest task is writing message handlers for use with this adapter, that is, methods that receive production messages and then send email messages via an SMTP server.

Each message handler method should have the following signature:

Method Sample(pReq As RequestClass, Output pResp As ResponseClass) As %Status
Copy code to clipboard

Here Sample is the name of the method, RequestClass is the name of a request message class, and ResponseClass is the name of a response message class.

In general, the method should do the following:

  1. Examine the inbound request message.

  2. Create an email message to send; for information, see “Creating Email Messages,” later in this chapter.

  3. Optionally call the AddRecipients(), AddCcRecipients(), and AddBccRecipients()methods of the Adapter property of your business operation. These methods add email addresses to the To:, Cc:, and Bcc: headers when you send the email message. These methods are discussed after these steps.

  4. Call the SendMessage() method of the Adapter property of your business operation:

        Set tSc=..Adapter.SendMail(email,.pf)
    
    Copy code to clipboard

    This method is discussed after these steps.

  5. Examine the response.

  6. Use information in the response to create a response message (an instance of Ens.Response or a subclass), which the method returns as output.

    For information on defining message classes, see “Defining Messages” in Developing Productions.

  7. Make sure that you set the output argument (pOutput). Typically you set this equal to the response message. This step is required.

  8. Return an appropriate status. This step is required.

Available Methods

The adapter provides the following methods:

SendMail
Method SendMail(pMailMessage As %Net.MailMessage,
                Output pFailedRecipients As %ListOfDataTypes) As %Status
Copy code to clipboard

Given an email message, this method sends the message by means of the configured SMTP server. It returns, as output, as list of failed recipients, if the SMTP server returns this information.

AddRecipients
Method AddRecipients(pMailMessage As %Net.MailMessage,
                     pRecipients As %String)
Copy code to clipboard

Given an email message, this method adds the listed email addresses to the To: header of the message.

AddCcRecipients
Method AddCcRecipients(pMailMessage As %Net.MailMessage,
                       pRecipients As %String)
Copy code to clipboard

Given an email message, this method adds the listed email addresses to the Cc: header of the message.

AddBccRecipients
Method AddBccRecipients(pMailMessage As %Net.MailMessage,
                       pRecipients As %String)
Copy code to clipboard

Given an email message, this method adds the listed email addresses to the Bcc: header of the message. When sending an email there must be at least one address in the To: or Cc: header.

ContinueAfterBadSendSet
Method ContinueAfterBadSendSet(%val As %Integer) as %Status
Copy code to clipboard

If %val is true, the adapter continues to send the message if one or more of the recipients have an invalid address. The default is true.

Example

A method might look like the following:

Method SendMultipartEmailMessage(pRequest As EEMA.MultipartEmailMsg,
Output pResponse As Ens.Response) As %Status
{
    Set part1=##class(%Net.MailMessage).%New()
    Do part1.TextData.Write(pRequest.Message1)
    Set part2=##class(%Net.MailMessage).%New()
    Do part2.TextData.Write(pRequest.Message2)
    Set part3=##class(%Net.MailMessage).%New()
    Do part3.TextData.Write(pRequest.Message3)

    Set email=##class(%Net.MailMessage).%New()
    Set email.Subject=pRequest.Subject
    Set email.IsMultiPart=1
    Do email.Parts.SetAt(part1,1)
    Do email.Parts.SetAt(part2,2)
    Do email.Parts.SetAt(part3,3)

    Set tSc=..Adapter.SendMail(email,.pf)
    Set pResponse=##class(EEMA.EmailFailedRecipients).%New()
    Set pResponse.FailedRecipients=pf

    if pf.Count()'=""
    {
        set count=pf.Count()
        for i=1:1:count
        {
            $$$TRACE("Failed recipient:"_pf.GetAt(i))
            }
        }

    Quit tSc
}
Copy code to clipboard

For information on creating email messages, see the next section.

Creating Email Messages

A message can have one or more parts; each part contains content and can include headers. The message itself also has headers. The following sections discuss the topics:

Note:

You should be aware of the requirements of the SMTP server that you are using. For example, some SMTP servers require that you include a Subject: header. Similarly, some SMTP servers do not permit arbitrary From: headers.

Creating an Email Message

To create an email message, do the following:

  1. Create an instance of %Net.MailMessage.

    Tip:

    You can specify a character set as the argument to %New(); if you do so, that sets the Charset property for the message.

    For background information on character translation in InterSystems IRIS®, see “Localization Support” in the Orientation Guide for Server-Side Programming.

  2. Set the To, From, and Subject properties of your instance. These properties are required.

    • To — The list of email addresses to which this message will be sent. This property is a standard InterSystems IRIS list; to work with it, you use the standard list methods: Insert(), GetAt(), RemoveAt(), Count(), and Clear().

    • From — The email address this message is sent from.

    • Subject — The subject of the message.

  3. Optionally set Date, Cc, Bcc, and other properties. For details, see “Basic Headers,” later in this chapter.

  4. If you are creating a single-part message, specify the contents and headers as described in “Specifying the Content and Headers of a Message Part.”

  5. Or, if you are creating a multipart message, do the following:

    1. Set the IsMultiPart property to 1.

    2. Set the MultiPartType property to one of the following: "related", "alternative", or "mixed".

    3. For each part that the message should contain, create an instance of %Net.MailMessagePart. Then specify the contents and headers as described in “Specifying the Content and Headers of a Message Part.”

    4. For the parent email message, set the Parts property, which is an array. Insert each child message part into this array.

Specifying the Content and Headers of a Message Part

  1. If the message is not plain text, set the following properties to indicate the kind of message you are creating:

    • If this is an HTML message, set the IsHTML property to 1.

    • If this is a binary message, set the IsBinary property to 1.

  2. To specify the desired character set of the message and its headers, set the Charset property as needed.

    Important:

    It is important to specify the character set before you add the contents of the message.

    For background information on character translation in InterSystems IRIS, see “Localization Support” in the Orientation Guide for Server-Side Programming.

  3. Add the contents of the message:

    • For plain text or HTML, use the TextData property, which is an instance of %FileCharacterStream. You do not need to specify the TranslateTable property of this stream; that occurred automatically when you specified the character set of the mail message.

      The system automatically translates the character encoding to the encoding that you specified in the previous step.

    • For binary data, use the BinaryData property, which is an instance of %FileBinaryStream.

    Tip:

    When you specify the Filename property of the stream, be sure to use a directory to which the users will have write access.

    To work with these properties, use the standard stream methods: Write(), WriteLine(), Read(), ReadLine(), Rewind(), MoveToEnd(), and Clear(). You can also use the Size property of the stream, which gives you the size of the message contents.

Specifying the Message Headers

As noted previously, both the message itself and each part of a message has a set of headers.

The %Net.MailMessage and %Net.MailMessagePart classes provide properties that give you easy access to the most commonly used headers, but you can add any header you need. This section provides information on all the headers as well as how to create custom headers.

Note:

The headers of a given message part are in the character set specified by the Charset property of that part.

Basic Headers

Set the following properties (only in %Net.MailMessage) to specify the most commonly used headers of the message itself:

  • To — (Required) The list of email addresses to which this message will be sent. This property is a standard InterSystems IRIS list; to work with it, you use the standard list methods: Insert(), GetAt(), RemoveAt(), Count(), and Clear().

  • From — (Required) The email address this message is sent from.

  • Date — The date of this message.

  • Subject — A string containing the subject for this message.

  • Sender — The actual sender of the message.

  • Cc — The list of carbon copy addresses to which this message will be sent.

  • Bcc — The list of blind carbon copy addresses to which this message will be sent.

Note:

You should be aware of the requirements of the SMTP server that you are using. For example, some SMTP servers require that you include a Subject: header. Similarly, some SMTP servers do not permit arbitrary From: headers.

Content-Type Header

When you send the message, the Content-Type header for the message and for each message part is automatically set as follows:

  • If the message is plain text (IsHTML equals 0 and IsBinary equals 0), the Content-Type header is set to "text/plain".

  • If the message is HTML (IsHTML equals 1 and IsBinary equals 0), the Content-Type header is set to "text/html".

  • If the message is binary (IsBinary equals 1), the Content-Type header is set to "application/octet-stream".

  • If the message is multipart, the Content-Type header is set as appropriate for the value of the MultiPartType property.

Both %Net.MailMessage and %Net.MailMessagePart provide the ContentType property, which gives you access to the Content-Type header.

Content-Transfer-Encoding Header

Both %Net.MailMessage and %Net.MailMessagePart provide the ContentTransferEncoding property, which provides an easy way to specify the Content-Transfer-Encoding header of the message or the message part.

This property can be one of the following: "base64" "quoted-printable" "7bit" "8bit"

The default is as follows:

  • For a binary message or message part: "base64"

  • For a text message or message part: "quoted-printable"

Custom Headers

With both %Net.MailMessage and %Net.MailMessagePart, you can set or get custom headers by accessing the Headers property, which is an array with the following structure:

Array Key Array Value
Name of the header, such as "Priority" Value of the header

You use this property to contain additional headers such as priority. For example:

 Do msg.Headers.SetAt("Urgent","Priority")
Copy code to clipboard

Adding Attachments

You can add attachments to an email message or message part. To do so, use the following methods of %Net.MailMessagePart or %Net.MailMessage):

Each of these methods adds the attachment to the Parts array of the original message (or message part), and automatically sets the IsMultiPart property to 1.

AttachFile
method AttachFile(Dir As %String,
                  File As %String,
                  isBinary As %Boolean = 1,
                  charset As %String = "",
                  ByRef count As %Integer) as %Status
Copy code to clipboard

Attaches the given file to the email message. By default the file is sent as a binary attachment, but you can specify instead that it is text. You can also specify the character set that the file uses if it is text. (For background information on character translation in InterSystems IRIS, see “Localization Support” in the Orientation Guide for Server-Side Programming.)

Specifically, this method creates an instance of %Net.MailMessagePart and places the contents of the file in the BinaryData or TextData property as appropriate, and sets the Charset property and TextData.TranslateTable properties if needed. The method returns, by reference, an integer that indicates the position of this new message part within the Parts array.

This method also sets the Dir and FileName properties of the message or message part.

AttachNewMessage
method AttachNewMessage() as %Net.MailMessagePart
Copy code to clipboard

Creates a new instance of %Net.MailMessage, adds it to the message, and returns the newly modified parent message or message part.

AttachEmail
method AttachEmail(mailmsg As %Net.MailMessage)
Copy code to clipboard

Given an email message (an instance of %Net.MailMessage), this method adds it to the message.

Note:

This method sets ContentType to "message/rfc822". In this case, you cannot add any other attachments.

For examples, see the class reference for the %Net.MailMessagePart class.

Example

For example:

ClassMethod CreateTextMessage() As %Net.MailMessage
{
    Set msg = ##class(%Net.MailMessage).%New()
    set msg.From = "test@test.com"
    Do msg.To.Insert("xxx@xxx.com")
    Do msg.Cc.Insert("yyy@yyy.com")
    Do msg.Bcc.Insert("zzz@zzz.com")
    Set msg.Subject="subject line here"
    Set msg.IsBinary=0
    Set msg.IsHTML=0
    Do msg.TextData.Write("This is the message.")

    Quit msg
}
Copy code to clipboard

Example

This section presents an example that allows you to send simple single-part or multipart email messages that contain string content. In a production system, you would probably use streams instead of strings. Because this example uses strings, however, you can easily test it by means of the production testing page.

First, the request message class for the single-part message is as follows:

Class EEMA.SimpleMsg Extends Ens.Request
{

Property Subject As %String(MAXLEN = 100);

Property Message As %String(MAXLEN = 5000);

}
Copy code to clipboard

The request message class for the multipart message is next. This class can contain a three-part message.

Class EEMA.MultipartMsg Extends Ens.Request
{

Property Subject As %String(MAXLEN = 100);

Property Part1 As %String(MAXLEN = 5000);

Property Part2 As %String(MAXLEN = 5000);

Property Part3 As %String(MAXLEN = 5000);

}
Copy code to clipboard

The following business operation can accept either of these messages, create the appropriate email message, and send that via the configured SMTP server:

Class EEMA.EmailOperation Extends Ens.BusinessOperation
{

Parameter ADAPTER = "EnsLib.EMail.OutboundAdapter";

Parameter INVOCATION = "Queue";

Method SendSimpleMessage(pRequest As EEMA.SimpleMsg,
Output pResponse As Ens.Response) As %Status
{
    Set email=##class(%Net.MailMessage).%New()

    //Get info from pReq
    Do email.TextData.Write(pRequest.Message)
    Set email.Subject=pRequest.Subject

    //simple case--do not check for failed recipients
    Set tSc=..Adapter.SendMail(email)

    //send an empty response message after message is sent
    Set pResponse=##class(Ens.Response).%New()

    ;Quit tSc
}

Method SendMultipartEmailMessage(pRequest As EEMA.MultipartMsg,
Output pResponse As Ens.Response) As %Status
{
    Set part1=##class(%Net.MailMessage).%New()
    Do part1.TextData.Write(pRequest.Part1)
    Set part2=##class(%Net.MailMessage).%New()
    Do part2.TextData.Write(pRequest.Part2)
    Set part3=##class(%Net.MailMessage).%New()
    Do part3.TextData.Write(pRequest.Part3)

    Set email=##class(%Net.MailMessage).%New()
    Set email.Subject=pRequest.Subject
    Set email.IsMultiPart=1
    Do email.Parts.SetAt(part1,1)
    Do email.Parts.SetAt(part2,2)
    Do email.Parts.SetAt(part3,3)

    //simple case--do not check for failed recipients
    Set tSc=..Adapter.SendMail(email)

    //send an empty response message after message is sent
    Set pResponse=##class(Ens.Response).%New()

    Quit tSc
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="EEMA.SimpleMsg">
        <Method>SendSimpleMessage</Method>
    </MapItem>
    <MapItem MessageType="EEMA.MultipartMsg">
        <Method>SendMultipartEmailMessage</Method>
    </MapItem>
</MapItems>
}

}
Copy code to clipboard

Adding and Configuring the Business Operation

To add your business operation to a production, use the Management Portal to do the following:

  1. Add an instance of your custom business operation class to the production.

  2. Enable the business operation.

  3. Specify an SMTP mail server and credentials needed to access it.

  4. Optionally specify additional addresses for the email messages.

  5. Run the production.

Specifying How to Log Into the SMTP Server

To specify the SMTP server to use and any associated login credentials, specify values for the following settings of EnsLib.EMail.OutboundAdapter:

For example, you could use values like the following:

Setting Value
SMTP Server smtp.hotpop.com
SMTP Port 25
Credentials hotpop

In this example, hotpop is the ID of the production credentials that consist of the username isctest@hotpop.com and the corresponding password.

Specifying Additional Email Addresses

You can use the following settings of EnsLib.EMail.OutboundAdapter to specify email addresses for email messages sent by this adapter:

For any settings not listed here, see Configuring Productions.