<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://m204wiki.rocketsoftware.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=SNelson</id>
	<title>m204wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://m204wiki.rocketsoftware.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=SNelson"/>
	<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Special:Contributions/SNelson"/>
	<updated>2026-05-04T02:22:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68088</id>
		<title>Email class</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68088"/>
		<updated>2014-03-20T18:18:40Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class is a high level,&lt;br /&gt;
object oriented interface to client sockets that lets you write a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; SMTP&lt;br /&gt;
(Simple Mail Transfer Protocol) request without knowledge of socket level programming&lt;br /&gt;
or the format of SMTP requests and responses.&lt;br /&gt;
 &lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods let a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; program act as an SMTP client.&lt;br /&gt;
SMTP clients send mail requests&lt;br /&gt;
to an SMTP server, not directly to other SMTP clients.&lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods only support communication with SMTP servers.&lt;br /&gt;
 &lt;br /&gt;
An SMTP server will &amp;quot;store and forward&amp;quot; mail it receives.&lt;br /&gt;
This means that all&lt;br /&gt;
messages are first received in entirety on the SMTP server,&lt;br /&gt;
then the server attempts to deliver it to the recipients.&lt;br /&gt;
Mail delivery can be delayed by a server that is down or too busy to&lt;br /&gt;
accept connections.&lt;br /&gt;
&amp;quot;Store and forward&amp;quot; gives the SMTP server the ability&lt;br /&gt;
to retry delivery without making the SMTP client wait for completion.&lt;br /&gt;
 &lt;br /&gt;
A server might try to deliver a message for as long as a week or more.&lt;br /&gt;
This, of course, makes it impractical for a client to wait for delivery&lt;br /&gt;
confirmation, so the SMTP protocol does not provide such information.&lt;br /&gt;
A &amp;quot;success&amp;quot; response from an SMTP server indicates&lt;br /&gt;
only that the server has accepted the request and will&lt;br /&gt;
attempt to deliver the mail to the recipients.&lt;br /&gt;
 &lt;br /&gt;
Most SMTP servers will at least confirm that&lt;br /&gt;
any domain names in the recipient list are valid, but they cannot confirm that an&lt;br /&gt;
actual recipient name is valid.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;div id=&amp;quot;jport&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
You must define a Janus &amp;lt;var&amp;gt;[[JANUS CLSOCK|CLSOCK]]&amp;lt;/var&amp;gt; port to use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
If you supply the IP address&lt;br /&gt;
of the server and the port number in the port definition, SMTP&lt;br /&gt;
applications need only know the Janus port name to communicate with the server.&lt;br /&gt;
The following example defines a client socket port for use by SMTP applications.&lt;br /&gt;
For more detailed information about defining&lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; client socket ports, see &amp;lt;var&amp;gt;[[JANUS DEFINE]]&amp;lt;/var&amp;gt; and &amp;lt;var&amp;gt;[[JANUS CLSOCK]]&amp;lt;/var&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;JANUS DEFINE MYSMTP * CLSOCK 5 REMOTE 198.242.244.100 25&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039;&lt;br /&gt;
To use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects under versions of Model 204 earlier than 7.5, you must have licensed &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/var&amp;gt;, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus Sockets]]&amp;lt;/var&amp;gt;, &#039;&#039;&#039;and&#039;&#039;&#039; &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus SOAP]]&amp;lt;/var&amp;gt;. Under version 7.5 and later,&lt;br /&gt;
you do not require &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt;. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information about using SOUL objects, see [[Object oriented programming in SOUL]] and&lt;br /&gt;
[[Getting started with OOP for User Language programmers]].&lt;br /&gt;
&lt;br /&gt;
==Email class summary==&lt;br /&gt;
The following capabilities are provided by the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Creating general purpose e-mail for SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Sending general purpose e-mail via SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Setting e-mail content using &amp;lt;var&amp;gt;[[Longstrings]]&amp;lt;/var&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Sending MIME content (attachments and alternative content)&lt;br /&gt;
&amp;lt;li&amp;gt;Sending to multiple recipients&lt;br /&gt;
&amp;lt;li&amp;gt;Access to status (error or confirmation messages)&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; object to generate SMTP messages&lt;br /&gt;
(e-mail) to send to an SMTP server.&lt;br /&gt;
To construct a request, you use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to set and inspect&lt;br /&gt;
header information, content, and attachments.&lt;br /&gt;
To send e-mail, you use the &amp;lt;var&amp;gt;[[Mail (Email function)|Mail]]&amp;lt;/var&amp;gt; method.&lt;br /&gt;
 &lt;br /&gt;
[[List of Email methods]] contains a list of all the methods in the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
==Dummy SMTP Server example==&lt;br /&gt;
This is an example of a very basic SMTP Server which simple excepts &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects from a SMTP client in turn sends a response.&lt;br /&gt;
It does not store or retrieve messages.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Dummy SMTP Server===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;emclass.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* encoding enumerations.                                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
enumeration encoding&lt;br /&gt;
   public&lt;br /&gt;
   value base64&lt;br /&gt;
   value none&lt;br /&gt;
   end  public&lt;br /&gt;
end enumeration&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* emailPart class.                                                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class emailPart&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
   variable headers is object stringlist&lt;br /&gt;
   variable body is object stringlist&lt;br /&gt;
   function type is string len 255&lt;br /&gt;
   function encoding is string len 255&lt;br /&gt;
   function name is string len 255&lt;br /&gt;
   function contentlist is object stringlist&lt;br /&gt;
   function content is longstring&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return complete contentlist from an emailPart                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function contentlist is object stringlist&lt;br /&gt;
 &lt;br /&gt;
return %this:body&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Decode and return content from an emailPart                         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function content is longstring&lt;br /&gt;
 &lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 128&lt;br /&gt;
%encoding is string len 128&lt;br /&gt;
%lf   is string len 1&lt;br /&gt;
%i    is float&lt;br /&gt;
%j    is float&lt;br /&gt;
%content is longstring&lt;br /&gt;
%concat  is boolean initial(True)&lt;br /&gt;
%temp    is longstring&lt;br /&gt;
 &lt;br /&gt;
if %this:body eq null then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%lf = &#039;0A&#039;:x&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:body:count&lt;br /&gt;
   if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
      %content = %content with %this:body(%i)&lt;br /&gt;
   elseif %this:encoding eq &#039;quoted-printable&#039; then&lt;br /&gt;
      %temp = %this:body(%i):Unspace(Leading=False, Trailing=True, -&lt;br /&gt;
         Compress=False)&lt;br /&gt;
      if %concat = False then&lt;br /&gt;
         %content = %content %lf&lt;br /&gt;
      end if&lt;br /&gt;
      for %j from 1 to %temp:Length - 2&lt;br /&gt;
         if %temp:Substring(%j, 1) = &#039;=&#039; then&lt;br /&gt;
            %content = %content %temp:Substring(%j + 1, 2): -&lt;br /&gt;
            HexToString:AsciiToEbcdic(characterEncode=true)&lt;br /&gt;
            %j = %j + 2&lt;br /&gt;
         else&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end if&lt;br /&gt;
      end for&lt;br /&gt;
      if %j &amp;lt;= %temp:Length then&lt;br /&gt;
         for %j from %j to %temp:Length&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end for&lt;br /&gt;
      end if&lt;br /&gt;
      if %content:Right(1) = &#039;=&#039; then&lt;br /&gt;
         %concat = True&lt;br /&gt;
         %content = %content:TrimRight(1)&lt;br /&gt;
      else&lt;br /&gt;
         %concat = False&lt;br /&gt;
      end if&lt;br /&gt;
   else&lt;br /&gt;
      %content = %content %this:body(%i) with %lf&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
   %content = %content:base64ToString&lt;br /&gt;
   if %this:type:left(5) = &#039;text/&#039; then&lt;br /&gt;
      %content = %content:AsciiToEbcdic(CharacterEncode=true)&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %content&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the name (if present) of an emailPart                        *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function name is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%name is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Disposition:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; filename=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; name=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%name = %name:word(2, spaces=&#039; =&#039;)&lt;br /&gt;
if %name:left(1) = &#039;&amp;quot;&#039; then %name = %name:trimLeft(1); end if&lt;br /&gt;
if %name:right(1) = &#039;&amp;quot;&#039; then %name = %name:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
return %name&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the encoding (if present) of an emailPart                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function encoding is string len 255&lt;br /&gt;
 &lt;br /&gt;
%enc  is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
   %enc = %temp:word(2)&lt;br /&gt;
   if %enc:left(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimLeft(1); end if&lt;br /&gt;
   if %enc:right(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimRight(1); end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
if %enc = &#039;&#039; then %enc = &#039;7bit&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %enc&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the content type of an emailPart                             *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function type is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%type = %temp:word(2)&lt;br /&gt;
if %type:left(1) = &#039;&amp;quot;&#039; then %type = %type:trimLeft(1); end if&lt;br /&gt;
if %type:right(1) = &#039;&amp;quot;&#039; then %type = %type:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
if %type = &#039;&#039; then %type = &#039;text/plain&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %type&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* receivedEmail class.                                                *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class receivedEmail&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
  variable headers is object stringlist&lt;br /&gt;
  variable body is object stringlist&lt;br /&gt;
  variable rcptList is object stringlist&lt;br /&gt;
  variable fromHost is string len 128&lt;br /&gt;
  variable from     is string len 128&lt;br /&gt;
 &lt;br /&gt;
  function header -&lt;br /&gt;
    (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
     is string len 255&lt;br /&gt;
  function contentList (%x is float) is object stringlist&lt;br /&gt;
  function part (%number is float) is object emailPart&lt;br /&gt;
  function parts is float&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a header from the email message                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function header -&lt;br /&gt;
   (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
   is string len 255&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 255&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %toke  = %this:headers(%i):stringTokenizer&lt;br /&gt;
   %token = %toke:nextToken:toUpper&lt;br /&gt;
   %toke:discard&lt;br /&gt;
   if %name:toUpper eq %token then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %i &amp;gt; %this:headers:count then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%token = %this:headers(%i)&lt;br /&gt;
if %this:headers(%i):right(1) ne &#039;;&#039; then return %token; end if&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:headers:count&lt;br /&gt;
   %token = %token %this:headers(%i)&lt;br /&gt;
   if %this:headers(%i):right(1) ne &#039;;&#039; then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %token&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a &amp;quot;part&amp;quot; of an email message as an emailPart object.         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function part (%number is float) is object emailPart&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 72&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%encoding is string len 255&lt;br /&gt;
%partNumber is float&lt;br /&gt;
%cont is boolean initial(false)&lt;br /&gt;
%mime is boolean initial(false)&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
 &lt;br /&gt;
%part = new&lt;br /&gt;
%part:headers = new&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%part:headers = new&lt;br /&gt;
%part:body = new&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i) then&lt;br /&gt;
         %partNumber = %partNumber + 1&lt;br /&gt;
         if %partNumber = %number then loop end; end if&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %this:body(%i) eq &#039;&#039; then loop end; end if&lt;br /&gt;
      %part:headers:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i):substring(1, %bound:length) then&lt;br /&gt;
         loop end;&lt;br /&gt;
      end if&lt;br /&gt;
      %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
else&lt;br /&gt;
   assert %number eq 1&lt;br /&gt;
   for %i from 1 to %this:headers:count&lt;br /&gt;
      %temp = %this:headers(%i)&lt;br /&gt;
      if &#039;Content-&#039;:toUpper eq %temp:word(1):left(8):toUpper then&lt;br /&gt;
         %part:headers:add(%temp)&lt;br /&gt;
         for %i from %i + 1 to %this:headers:count&lt;br /&gt;
            if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
            %part:headers:add(%this:headers(%i))&lt;br /&gt;
         end for&lt;br /&gt;
         %i = %i - 1&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
     %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %part&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return number of &amp;quot;parts&amp;quot; of an email message.                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function parts is float&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 128&lt;br /&gt;
%parts is float&lt;br /&gt;
%temp  is longstring&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
else&lt;br /&gt;
   return 1&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%parts = 0&lt;br /&gt;
for %i from 1 to %this:body:count&lt;br /&gt;
   if %bound = %this:body(%i) then&lt;br /&gt;
      %parts = %parts + 1&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %parts&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* smtpDriver class.                                                   *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class smtpDriver&lt;br /&gt;
    public shared&lt;br /&gt;
       subroutine -&lt;br /&gt;
       run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
    end public shared&lt;br /&gt;
 &lt;br /&gt;
   subroutine run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
 &lt;br /&gt;
      %receivedEmail is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * SMTP server program.                                          *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * Static values used by the server.                             *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      %serverId         is string len 80 initial -&lt;br /&gt;
            (&amp;quot;host.sirius-software.com running Model 204 SMTP server&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * End of static values used by the server.                      *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      local subroutine (stringList):audit&lt;br /&gt;
      %i  is float&lt;br /&gt;
      for %i from 1 to %this:count&lt;br /&gt;
         auditText {%i}: {%this(%i)}&lt;br /&gt;
      end for&lt;br /&gt;
      end subroutine&lt;br /&gt;
 &lt;br /&gt;
      %remail                 is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      %msg                    is string len 128&lt;br /&gt;
      %client                 is string len 128&lt;br /&gt;
      %command                is string len 16&lt;br /&gt;
      %email                  is object receivedEmail&lt;br /&gt;
      %esmtp                  is boolean initial(false)&lt;br /&gt;
      %from                   is string len 128&lt;br /&gt;
      %by                     is string len 128&lt;br /&gt;
      %received               is string len 255&lt;br /&gt;
      %dateTime               is string len 128&lt;br /&gt;
      %inputLength            is float&lt;br /&gt;
      %inputLine              is longstring&lt;br /&gt;
      %sock                   is object socket&lt;br /&gt;
      %toke                   is object stringTokenizer&lt;br /&gt;
      %token                  is string len 128&lt;br /&gt;
 &lt;br /&gt;
      %sock = serverSocket&lt;br /&gt;
 &lt;br /&gt;
      %sock:set(&#039;CHAR&#039;, &#039;CHAR&#039;)&lt;br /&gt;
      %sock:set(&#039;LINEND&#039;, &#039;0D0A&#039;)&lt;br /&gt;
      %sock:set(&#039;PRSTOK&#039;, &#039;0D0A&#039;)&lt;br /&gt;
 &lt;br /&gt;
      %dateTime = -&lt;br /&gt;
         %(system):currentTimeString(&#039;DD Mon YYYY HH:MI:SS&#039;)&lt;br /&gt;
      %sock:sendWithLineEnd( -&lt;br /&gt;
         &amp;quot;220 &amp;quot; with %serverId with &amp;quot; on &amp;quot; with %dateTime)&lt;br /&gt;
 &lt;br /&gt;
      %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
 &lt;br /&gt;
      %toke = %inputLine:stringTokenizer&lt;br /&gt;
 &lt;br /&gt;
      %command = %toke:nextToken:toUpper&lt;br /&gt;
      if %command eq &#039;EHLO&#039; then&lt;br /&gt;
         %esmtp = true&lt;br /&gt;
      elseIf %command ne &#039;HELO&#039; then&lt;br /&gt;
         auditText *** Incorrect hello message received, -&lt;br /&gt;
            command={%command}, closing connection&lt;br /&gt;
         %sock:close&lt;br /&gt;
         stop&lt;br /&gt;
      end if&lt;br /&gt;
 &lt;br /&gt;
      %client = %toke:nextToken&lt;br /&gt;
      %msg = &amp;quot;250 Hello &amp;quot; with %client with -&lt;br /&gt;
         &amp;quot; I&#039;m delighted to meet you&amp;quot;&lt;br /&gt;
      %sock:sendWithLineEnd(%msg)&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Entering main SMTP loop for {%client}&lt;br /&gt;
      repeat forever&lt;br /&gt;
         %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
         %toke = %inputLine:stringTokenizer&lt;br /&gt;
         %command = %toke:nextToken:toUpper&lt;br /&gt;
         if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
         if %command ne &#039;MAIL&#039; then&lt;br /&gt;
            auditText **** Unexpected command {%command} received, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %token = %toke:nextToken&lt;br /&gt;
         if %token:left(5):toUpper ne &#039;FROM:&#039; then&lt;br /&gt;
            auditText **** MAIL followed by {%token} not -&lt;br /&gt;
               FROM:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %from = %token:substring(6)&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email = new&lt;br /&gt;
         %email:rcptList = new&lt;br /&gt;
 &lt;br /&gt;
         %toke = %sock:info(&#039;REMOTE&#039;):stringTokenizer&lt;br /&gt;
         %email:fromHost = %toke:nextToken&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            %toke = %inputLine:stringTokenizer&lt;br /&gt;
            %command = %toke:nextToken:toUpper&lt;br /&gt;
            if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
            if %command ne &#039;RCPT&#039; then loop end; end if&lt;br /&gt;
            %token = %toke:nextToken&lt;br /&gt;
            if %token:left(3):toUpper ne &#039;TO:&#039; then&lt;br /&gt;
               auditText **** RCPT followed by {%token} not -&lt;br /&gt;
                  TO:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
               jump to close&lt;br /&gt;
            end if&lt;br /&gt;
            %email:rcptList:add(%token:substring(4))&lt;br /&gt;
            %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         if %email:rcptList:count eq 0 then&lt;br /&gt;
            auditText **** No RCPT TO:s received after a -&lt;br /&gt;
               MAIL FROM:, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
 &lt;br /&gt;
         if %command ne &#039;DATA&#039; then&lt;br /&gt;
            auditText **** No DATA received after a RCPT TO:, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;354 End data with a single &#039;.&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email:headers = new&lt;br /&gt;
         setText %received = Received: from {%email:fromHost} by -&lt;br /&gt;
            {%serverid} ; -&lt;br /&gt;
            {%(system):currentTimeString(&#039;Wkd, DD Mon YYYY HH:MI:SS&#039;)}&lt;br /&gt;
         %email:headers:add(%received)&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine = &#039;&#039; then loop end; end if&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:headers:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %email:body = new&lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:body:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 E-mail received&amp;quot;)&lt;br /&gt;
      end repeat&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
      quit:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** QUIT received&lt;br /&gt;
      %sock:sendWithLineEnd(&amp;quot;221 Bye&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      close:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Terminating SMTP connection&lt;br /&gt;
      %sock:close&lt;br /&gt;
 &lt;br /&gt;
      %email:%processEmail&lt;br /&gt;
 &lt;br /&gt;
    end subroutine&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;driver.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UTABLE LNTBL 128&lt;br /&gt;
b&lt;br /&gt;
 &lt;br /&gt;
i emclass.ul&lt;br /&gt;
 &lt;br /&gt;
local subroutine (receivedEmail):process&lt;br /&gt;
 &lt;br /&gt;
%i     is float&lt;br /&gt;
%j     is float&lt;br /&gt;
%x     is float&lt;br /&gt;
%ls    is longstring&lt;br /&gt;
%op    is string len 8&lt;br /&gt;
%temp  is string len 255&lt;br /&gt;
%ename is string len 255&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%tp    is float&lt;br /&gt;
 &lt;br /&gt;
%tp = 0&lt;br /&gt;
setText %ename = CSURF_EMAIL_{$sir_date(&#039;YYMMDDHHMISS&#039;)}&lt;br /&gt;
%x = $bldproc(%tp, %ename, &#039;OPEN&#039;)&lt;br /&gt;
assert %x eq 0&lt;br /&gt;
*&lt;br /&gt;
* Get attachments and copy content to output procedure&lt;br /&gt;
*&lt;br /&gt;
%op = &#039;APPEND&#039;&lt;br /&gt;
for %i from 1 to %this:parts&lt;br /&gt;
   %part = %this:part(%i)&lt;br /&gt;
   for %j from 1 to %part:headers:count&lt;br /&gt;
      %temp = %part:headers(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
   for %j from 1 to %part:body:count&lt;br /&gt;
      %temp = %part:body(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
end subroutine&lt;br /&gt;
 &lt;br /&gt;
%(smtpDriver):run(process)&lt;br /&gt;
 &lt;br /&gt;
end&lt;br /&gt;
USE Fred&lt;br /&gt;
DISPLAY PROCEDURE 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
==SMTP examples==&lt;br /&gt;
Examples follow in which &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects are used to create and send a request to an SMTP server.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Basic e-mail example===&lt;br /&gt;
This example uses most of the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to send a simple message to three recipients.&lt;br /&gt;
The local &amp;lt;var&amp;gt;CLSOCK&amp;lt;/var&amp;gt; port used is named &amp;lt;code&amp;gt;SPAM&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
 &lt;br /&gt;
%letter object Email&lt;br /&gt;
%h      longstring&lt;br /&gt;
%t      longstring&lt;br /&gt;
%name   longstring&lt;br /&gt;
%nick   string len 64&lt;br /&gt;
 &lt;br /&gt;
%letter = new&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;C_Coolidge@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;SilentCal&#039;&lt;br /&gt;
%letter:AddRecipient(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;D_Eisenhower@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;Ike&#039;&lt;br /&gt;
%letter:AddCc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = L_Johnson@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;LBJ&#039;&lt;br /&gt;
%letter:AddBcc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%letter:Sender(&#039;a_huckster@bankandtrustme.com&#039;)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Subject:&#039;&lt;br /&gt;
%t = &#039;Lower Mortgage Rates&#039;&lt;br /&gt;
%letter:AddHeader(%h, %t)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Great deal of debt for you!&#039;&lt;br /&gt;
%letter:SetBody(%h)&lt;br /&gt;
 &lt;br /&gt;
%letter:mail(&#039;SPAM&#039;, 0)&lt;br /&gt;
 &lt;br /&gt;
print %letter:GetReplyCode with &#039; - &#039; with -&lt;br /&gt;
      %letter:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%letter:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===E-mail with attachment===&lt;br /&gt;
In the following example, an image is attached to a short e-mail message.&lt;br /&gt;
The attachment is produced from a member of a local &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; procedure file&lt;br /&gt;
using &amp;lt;var&amp;gt;Stringlist&amp;lt;/var&amp;gt; class methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
%rolex is object Email&lt;br /&gt;
%sl   is object Stringlist&lt;br /&gt;
%procdata   is object Stringlist&lt;br /&gt;
%jpg longstring&lt;br /&gt;
%t longstring&lt;br /&gt;
%temp string len 255&lt;br /&gt;
%procfile string len 10&lt;br /&gt;
%procname string len 63&lt;br /&gt;
%q float&lt;br /&gt;
%rc float&lt;br /&gt;
 &lt;br /&gt;
%rolex = new&lt;br /&gt;
%sl   = new&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;jbgood@netscape.net&#039;&lt;br /&gt;
%rolex:AddRecipient(%t, &#039;JB&#039;)&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;cberry@ucantbee-sirius.com&#039;&lt;br /&gt;
%rolex:Sender(%t)&lt;br /&gt;
%rolex:AddHeader(&#039;Subject:&#039;, &#039;watch this...&#039;)&lt;br /&gt;
 &lt;br /&gt;
text to %sl&lt;br /&gt;
 I want an authentic imitation Rolex watch. Something like&lt;br /&gt;
 the one shown in this image. Know anyone who&#039;s got one?&lt;br /&gt;
end text&lt;br /&gt;
%rolex:SetBody(%sl, encoding=&#039;none&#039;, type=&#039;text/plain&#039;)&lt;br /&gt;
 &lt;br /&gt;
%procfile = &#039;MYPROC&#039;&lt;br /&gt;
%procname = &#039;FAKE5.JPG&#039;&lt;br /&gt;
%rc = $procopn(%procname, %procfile)&lt;br /&gt;
if %rc ne 0 then&lt;br /&gt;
   print &#039;Can&#039;&#039;t open procedure &#039; with %procname    -&lt;br /&gt;
    with &#039; in file &#039; with %procfile with &#039;, rc = &#039;  -&lt;br /&gt;
    with %rc&lt;br /&gt;
   stop&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%procdata = new&lt;br /&gt;
%procdata:appendOpenProcedure&lt;br /&gt;
%jpg = %procData:binaryProcedureDecode&lt;br /&gt;
%rolex:AddPart(%jpg, type=&#039;image/jpg&#039;, name=&#039;Rolex1.jpg&#039;)&lt;br /&gt;
 &lt;br /&gt;
print %rolex:mail(&#039;MYSMTP&#039;, 0) &#039; is return from Mail method&#039;&lt;br /&gt;
print %rolex:GetReplyCode &#039; is return from GetReplyCode&#039;&lt;br /&gt;
print %rolex:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%rolex:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
If the request is successful, results like the following display at the terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;0 is return from Mail method&lt;br /&gt;
221 is return from GetReplyCode&lt;br /&gt;
ucantbee-sirius.com running IBM VM SMTP Level 320&lt;br /&gt;
   closing connection&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==List of Email methods==&lt;br /&gt;
The [[List of Email methods|&amp;quot;List of Email methods&amp;quot;]] shows all the class methods.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets User Language coding considerations]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Sample Janus Sockets programs]]&lt;br /&gt;
&amp;lt;li&amp;gt;Socket-level interfaces:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets $functions|$functions]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Socket class]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Higher-level interfaces: &lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Email class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[HTTP Helper|HTTP Helper classes]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[LDAP class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus FTP Server]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Telnet Server]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Janus Sockets]] &lt;br /&gt;
[[Category:System classes]]&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68084</id>
		<title>Email class</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68084"/>
		<updated>2014-03-20T18:03:58Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class is a high level,&lt;br /&gt;
object oriented interface to client sockets that lets you write a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; SMTP&lt;br /&gt;
(Simple Mail Transfer Protocol) request without knowledge of socket level programming&lt;br /&gt;
or the format of SMTP requests and responses.&lt;br /&gt;
 &lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods let a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; program act as an SMTP client.&lt;br /&gt;
SMTP clients send mail requests&lt;br /&gt;
to an SMTP server, not directly to other SMTP clients.&lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods only support communication with SMTP servers.&lt;br /&gt;
 &lt;br /&gt;
An SMTP server will &amp;quot;store and forward&amp;quot; mail it receives.&lt;br /&gt;
This means that all&lt;br /&gt;
messages are first received in entirety on the SMTP server,&lt;br /&gt;
then the server attempts to deliver it to the recipients.&lt;br /&gt;
Mail delivery can be delayed by a server that is down or too busy to&lt;br /&gt;
accept connections.&lt;br /&gt;
&amp;quot;Store and forward&amp;quot; gives the SMTP server the ability&lt;br /&gt;
to retry delivery without making the SMTP client wait for completion.&lt;br /&gt;
 &lt;br /&gt;
A server might try to deliver a message for as long as a week or more.&lt;br /&gt;
This, of course, makes it impractical for a client to wait for delivery&lt;br /&gt;
confirmation, so the SMTP protocol does not provide such information.&lt;br /&gt;
A &amp;quot;success&amp;quot; response from an SMTP server indicates&lt;br /&gt;
only that the server has accepted the request and will&lt;br /&gt;
attempt to deliver the mail to the recipients.&lt;br /&gt;
 &lt;br /&gt;
Most SMTP servers will at least confirm that&lt;br /&gt;
any domain names in the recipient list are valid, but they cannot confirm that an&lt;br /&gt;
actual recipient name is valid.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;div id=&amp;quot;jport&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
You must define a Janus &amp;lt;var&amp;gt;[[JANUS CLSOCK|CLSOCK]]&amp;lt;/var&amp;gt; port to use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
If you supply the IP address&lt;br /&gt;
of the server and the port number in the port definition, SMTP&lt;br /&gt;
applications need only know the Janus port name to communicate with the server.&lt;br /&gt;
The following example defines a client socket port for use by SMTP applications.&lt;br /&gt;
For more detailed information about defining&lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; client socket ports, see &amp;lt;var&amp;gt;[[JANUS DEFINE]]&amp;lt;/var&amp;gt; and &amp;lt;var&amp;gt;[[JANUS CLSOCK]]&amp;lt;/var&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;JANUS DEFINE MYSMTP * CLSOCK 5 REMOTE 198.242.244.100 25&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039;&lt;br /&gt;
To use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects under versions of Model 204 earlier than 7.5, you must have licensed &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/var&amp;gt;, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus Sockets]]&amp;lt;/var&amp;gt;, &#039;&#039;&#039;and&#039;&#039;&#039; &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus SOAP]]&amp;lt;/var&amp;gt;. Under version 7.5 and later,&lt;br /&gt;
you do not require &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt;. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information about using SOUL objects, see [[Object oriented programming in SOUL]] and&lt;br /&gt;
[[Getting started with OOP for User Language programmers]].&lt;br /&gt;
&lt;br /&gt;
==Email class summary==&lt;br /&gt;
The following capabilities are provided by the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Creating general purpose e-mail for SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Sending general purpose e-mail via SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Setting e-mail content using &amp;lt;var&amp;gt;[[Longstrings]]&amp;lt;/var&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Sending MIME content (attachments and alternative content)&lt;br /&gt;
&amp;lt;li&amp;gt;Sending to multiple recipients&lt;br /&gt;
&amp;lt;li&amp;gt;Access to status (error or confirmation messages)&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; object to generate SMTP messages&lt;br /&gt;
(e-mail) to send to an SMTP server.&lt;br /&gt;
To construct a request, you use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to set and inspect&lt;br /&gt;
header information, content, and attachments.&lt;br /&gt;
To send e-mail, you use the &amp;lt;var&amp;gt;[[Mail (Email function)|Mail]]&amp;lt;/var&amp;gt; method.&lt;br /&gt;
 &lt;br /&gt;
[[List of Email methods]] contains a list of all the methods in the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
==Dummy SMTP Server example==&lt;br /&gt;
This is an example of very basic SMTP Service which simple excepts &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects from a SMTP client and response back to the client.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Dummy SMTP Server example===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;emclass.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* encoding enumerations.                                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
enumeration encoding&lt;br /&gt;
   public&lt;br /&gt;
   value base64&lt;br /&gt;
   value none&lt;br /&gt;
   end  public&lt;br /&gt;
end enumeration&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* emailPart class.                                                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class emailPart&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
   variable headers is object stringlist&lt;br /&gt;
   variable body is object stringlist&lt;br /&gt;
   function type is string len 255&lt;br /&gt;
   function encoding is string len 255&lt;br /&gt;
   function name is string len 255&lt;br /&gt;
   function contentlist is object stringlist&lt;br /&gt;
   function content is longstring&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return complete contentlist from an emailPart                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function contentlist is object stringlist&lt;br /&gt;
 &lt;br /&gt;
return %this:body&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Decode and return content from an emailPart                         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function content is longstring&lt;br /&gt;
 &lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 128&lt;br /&gt;
%encoding is string len 128&lt;br /&gt;
%lf   is string len 1&lt;br /&gt;
%i    is float&lt;br /&gt;
%j    is float&lt;br /&gt;
%content is longstring&lt;br /&gt;
%concat  is boolean initial(True)&lt;br /&gt;
%temp    is longstring&lt;br /&gt;
 &lt;br /&gt;
if %this:body eq null then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%lf = &#039;0A&#039;:x&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:body:count&lt;br /&gt;
   if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
      %content = %content with %this:body(%i)&lt;br /&gt;
   elseif %this:encoding eq &#039;quoted-printable&#039; then&lt;br /&gt;
      %temp = %this:body(%i):Unspace(Leading=False, Trailing=True, -&lt;br /&gt;
         Compress=False)&lt;br /&gt;
      if %concat = False then&lt;br /&gt;
         %content = %content %lf&lt;br /&gt;
      end if&lt;br /&gt;
      for %j from 1 to %temp:Length - 2&lt;br /&gt;
         if %temp:Substring(%j, 1) = &#039;=&#039; then&lt;br /&gt;
            %content = %content %temp:Substring(%j + 1, 2): -&lt;br /&gt;
            HexToString:AsciiToEbcdic(characterEncode=true)&lt;br /&gt;
            %j = %j + 2&lt;br /&gt;
         else&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end if&lt;br /&gt;
      end for&lt;br /&gt;
      if %j &amp;lt;= %temp:Length then&lt;br /&gt;
         for %j from %j to %temp:Length&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end for&lt;br /&gt;
      end if&lt;br /&gt;
      if %content:Right(1) = &#039;=&#039; then&lt;br /&gt;
         %concat = True&lt;br /&gt;
         %content = %content:TrimRight(1)&lt;br /&gt;
      else&lt;br /&gt;
         %concat = False&lt;br /&gt;
      end if&lt;br /&gt;
   else&lt;br /&gt;
      %content = %content %this:body(%i) with %lf&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
   %content = %content:base64ToString&lt;br /&gt;
   if %this:type:left(5) = &#039;text/&#039; then&lt;br /&gt;
      %content = %content:AsciiToEbcdic(CharacterEncode=true)&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %content&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the name (if present) of an emailPart                        *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function name is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%name is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Disposition:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; filename=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; name=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%name = %name:word(2, spaces=&#039; =&#039;)&lt;br /&gt;
if %name:left(1) = &#039;&amp;quot;&#039; then %name = %name:trimLeft(1); end if&lt;br /&gt;
if %name:right(1) = &#039;&amp;quot;&#039; then %name = %name:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
return %name&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the encoding (if present) of an emailPart                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function encoding is string len 255&lt;br /&gt;
 &lt;br /&gt;
%enc  is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
   %enc = %temp:word(2)&lt;br /&gt;
   if %enc:left(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimLeft(1); end if&lt;br /&gt;
   if %enc:right(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimRight(1); end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
if %enc = &#039;&#039; then %enc = &#039;7bit&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %enc&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the content type of an emailPart                             *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function type is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%type = %temp:word(2)&lt;br /&gt;
if %type:left(1) = &#039;&amp;quot;&#039; then %type = %type:trimLeft(1); end if&lt;br /&gt;
if %type:right(1) = &#039;&amp;quot;&#039; then %type = %type:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
if %type = &#039;&#039; then %type = &#039;text/plain&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %type&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* receivedEmail class.                                                *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class receivedEmail&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
  variable headers is object stringlist&lt;br /&gt;
  variable body is object stringlist&lt;br /&gt;
  variable rcptList is object stringlist&lt;br /&gt;
  variable fromHost is string len 128&lt;br /&gt;
  variable from     is string len 128&lt;br /&gt;
 &lt;br /&gt;
  function header -&lt;br /&gt;
    (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
     is string len 255&lt;br /&gt;
  function contentList (%x is float) is object stringlist&lt;br /&gt;
  function part (%number is float) is object emailPart&lt;br /&gt;
  function parts is float&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a header from the email message                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function header -&lt;br /&gt;
   (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
   is string len 255&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 255&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %toke  = %this:headers(%i):stringTokenizer&lt;br /&gt;
   %token = %toke:nextToken:toUpper&lt;br /&gt;
   %toke:discard&lt;br /&gt;
   if %name:toUpper eq %token then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %i &amp;gt; %this:headers:count then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%token = %this:headers(%i)&lt;br /&gt;
if %this:headers(%i):right(1) ne &#039;;&#039; then return %token; end if&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:headers:count&lt;br /&gt;
   %token = %token %this:headers(%i)&lt;br /&gt;
   if %this:headers(%i):right(1) ne &#039;;&#039; then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %token&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a &amp;quot;part&amp;quot; of an email message as an emailPart object.         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function part (%number is float) is object emailPart&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 72&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%encoding is string len 255&lt;br /&gt;
%partNumber is float&lt;br /&gt;
%cont is boolean initial(false)&lt;br /&gt;
%mime is boolean initial(false)&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
 &lt;br /&gt;
%part = new&lt;br /&gt;
%part:headers = new&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%part:headers = new&lt;br /&gt;
%part:body = new&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i) then&lt;br /&gt;
         %partNumber = %partNumber + 1&lt;br /&gt;
         if %partNumber = %number then loop end; end if&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %this:body(%i) eq &#039;&#039; then loop end; end if&lt;br /&gt;
      %part:headers:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i):substring(1, %bound:length) then&lt;br /&gt;
         loop end;&lt;br /&gt;
      end if&lt;br /&gt;
      %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
else&lt;br /&gt;
   assert %number eq 1&lt;br /&gt;
   for %i from 1 to %this:headers:count&lt;br /&gt;
      %temp = %this:headers(%i)&lt;br /&gt;
      if &#039;Content-&#039;:toUpper eq %temp:word(1):left(8):toUpper then&lt;br /&gt;
         %part:headers:add(%temp)&lt;br /&gt;
         for %i from %i + 1 to %this:headers:count&lt;br /&gt;
            if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
            %part:headers:add(%this:headers(%i))&lt;br /&gt;
         end for&lt;br /&gt;
         %i = %i - 1&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
     %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %part&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return number of &amp;quot;parts&amp;quot; of an email message.                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function parts is float&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 128&lt;br /&gt;
%parts is float&lt;br /&gt;
%temp  is longstring&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
else&lt;br /&gt;
   return 1&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%parts = 0&lt;br /&gt;
for %i from 1 to %this:body:count&lt;br /&gt;
   if %bound = %this:body(%i) then&lt;br /&gt;
      %parts = %parts + 1&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %parts&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* smtpDriver class.                                                   *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class smtpDriver&lt;br /&gt;
    public shared&lt;br /&gt;
       subroutine -&lt;br /&gt;
       run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
    end public shared&lt;br /&gt;
 &lt;br /&gt;
   subroutine run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
 &lt;br /&gt;
      %receivedEmail is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * SMTP server program.                                          *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * Static values used by the server.                             *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      %serverId         is string len 80 initial -&lt;br /&gt;
            (&amp;quot;host.sirius-software.com running Model 204 SMTP server&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * End of static values used by the server.                      *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      local subroutine (stringList):audit&lt;br /&gt;
      %i  is float&lt;br /&gt;
      for %i from 1 to %this:count&lt;br /&gt;
         auditText {%i}: {%this(%i)}&lt;br /&gt;
      end for&lt;br /&gt;
      end subroutine&lt;br /&gt;
 &lt;br /&gt;
      %remail                 is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      %msg                    is string len 128&lt;br /&gt;
      %client                 is string len 128&lt;br /&gt;
      %command                is string len 16&lt;br /&gt;
      %email                  is object receivedEmail&lt;br /&gt;
      %esmtp                  is boolean initial(false)&lt;br /&gt;
      %from                   is string len 128&lt;br /&gt;
      %by                     is string len 128&lt;br /&gt;
      %received               is string len 255&lt;br /&gt;
      %dateTime               is string len 128&lt;br /&gt;
      %inputLength            is float&lt;br /&gt;
      %inputLine              is longstring&lt;br /&gt;
      %sock                   is object socket&lt;br /&gt;
      %toke                   is object stringTokenizer&lt;br /&gt;
      %token                  is string len 128&lt;br /&gt;
 &lt;br /&gt;
      %sock = serverSocket&lt;br /&gt;
 &lt;br /&gt;
      %sock:set(&#039;CHAR&#039;, &#039;CHAR&#039;)&lt;br /&gt;
      %sock:set(&#039;LINEND&#039;, &#039;0D0A&#039;)&lt;br /&gt;
      %sock:set(&#039;PRSTOK&#039;, &#039;0D0A&#039;)&lt;br /&gt;
 &lt;br /&gt;
      %dateTime = -&lt;br /&gt;
         %(system):currentTimeString(&#039;DD Mon YYYY HH:MI:SS&#039;)&lt;br /&gt;
      %sock:sendWithLineEnd( -&lt;br /&gt;
         &amp;quot;220 &amp;quot; with %serverId with &amp;quot; on &amp;quot; with %dateTime)&lt;br /&gt;
 &lt;br /&gt;
      %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
 &lt;br /&gt;
      %toke = %inputLine:stringTokenizer&lt;br /&gt;
 &lt;br /&gt;
      %command = %toke:nextToken:toUpper&lt;br /&gt;
      if %command eq &#039;EHLO&#039; then&lt;br /&gt;
         %esmtp = true&lt;br /&gt;
      elseIf %command ne &#039;HELO&#039; then&lt;br /&gt;
         auditText *** Incorrect hello message received, -&lt;br /&gt;
            command={%command}, closing connection&lt;br /&gt;
         %sock:close&lt;br /&gt;
         stop&lt;br /&gt;
      end if&lt;br /&gt;
 &lt;br /&gt;
      %client = %toke:nextToken&lt;br /&gt;
      %msg = &amp;quot;250 Hello &amp;quot; with %client with -&lt;br /&gt;
         &amp;quot; I&#039;m delighted to meet you&amp;quot;&lt;br /&gt;
      %sock:sendWithLineEnd(%msg)&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Entering main SMTP loop for {%client}&lt;br /&gt;
      repeat forever&lt;br /&gt;
         %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
         %toke = %inputLine:stringTokenizer&lt;br /&gt;
         %command = %toke:nextToken:toUpper&lt;br /&gt;
         if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
         if %command ne &#039;MAIL&#039; then&lt;br /&gt;
            auditText **** Unexpected command {%command} received, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %token = %toke:nextToken&lt;br /&gt;
         if %token:left(5):toUpper ne &#039;FROM:&#039; then&lt;br /&gt;
            auditText **** MAIL followed by {%token} not -&lt;br /&gt;
               FROM:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %from = %token:substring(6)&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email = new&lt;br /&gt;
         %email:rcptList = new&lt;br /&gt;
 &lt;br /&gt;
         %toke = %sock:info(&#039;REMOTE&#039;):stringTokenizer&lt;br /&gt;
         %email:fromHost = %toke:nextToken&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            %toke = %inputLine:stringTokenizer&lt;br /&gt;
            %command = %toke:nextToken:toUpper&lt;br /&gt;
            if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
            if %command ne &#039;RCPT&#039; then loop end; end if&lt;br /&gt;
            %token = %toke:nextToken&lt;br /&gt;
            if %token:left(3):toUpper ne &#039;TO:&#039; then&lt;br /&gt;
               auditText **** RCPT followed by {%token} not -&lt;br /&gt;
                  TO:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
               jump to close&lt;br /&gt;
            end if&lt;br /&gt;
            %email:rcptList:add(%token:substring(4))&lt;br /&gt;
            %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         if %email:rcptList:count eq 0 then&lt;br /&gt;
            auditText **** No RCPT TO:s received after a -&lt;br /&gt;
               MAIL FROM:, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
 &lt;br /&gt;
         if %command ne &#039;DATA&#039; then&lt;br /&gt;
            auditText **** No DATA received after a RCPT TO:, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;354 End data with a single &#039;.&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email:headers = new&lt;br /&gt;
         setText %received = Received: from {%email:fromHost} by -&lt;br /&gt;
            {%serverid} ; -&lt;br /&gt;
            {%(system):currentTimeString(&#039;Wkd, DD Mon YYYY HH:MI:SS&#039;)}&lt;br /&gt;
         %email:headers:add(%received)&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine = &#039;&#039; then loop end; end if&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:headers:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %email:body = new&lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:body:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 E-mail received&amp;quot;)&lt;br /&gt;
      end repeat&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
      quit:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** QUIT received&lt;br /&gt;
      %sock:sendWithLineEnd(&amp;quot;221 Bye&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      close:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Terminating SMTP connection&lt;br /&gt;
      %sock:close&lt;br /&gt;
 &lt;br /&gt;
      %email:%processEmail&lt;br /&gt;
 &lt;br /&gt;
    end subroutine&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;driver.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UTABLE LNTBL 128&lt;br /&gt;
b&lt;br /&gt;
 &lt;br /&gt;
i emclass.ul&lt;br /&gt;
 &lt;br /&gt;
local subroutine (receivedEmail):process&lt;br /&gt;
 &lt;br /&gt;
%i     is float&lt;br /&gt;
%j     is float&lt;br /&gt;
%x     is float&lt;br /&gt;
%ls    is longstring&lt;br /&gt;
%op    is string len 8&lt;br /&gt;
%temp  is string len 255&lt;br /&gt;
%ename is string len 255&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%tp    is float&lt;br /&gt;
 &lt;br /&gt;
%tp = 0&lt;br /&gt;
setText %ename = CSURF_EMAIL_{$sir_date(&#039;YYMMDDHHMISS&#039;)}&lt;br /&gt;
%x = $bldproc(%tp, %ename, &#039;OPEN&#039;)&lt;br /&gt;
assert %x eq 0&lt;br /&gt;
*&lt;br /&gt;
* Get attachments and copy content to output procedure&lt;br /&gt;
*&lt;br /&gt;
%op = &#039;APPEND&#039;&lt;br /&gt;
for %i from 1 to %this:parts&lt;br /&gt;
   %part = %this:part(%i)&lt;br /&gt;
   for %j from 1 to %part:headers:count&lt;br /&gt;
      %temp = %part:headers(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
   for %j from 1 to %part:body:count&lt;br /&gt;
      %temp = %part:body(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
end subroutine&lt;br /&gt;
 &lt;br /&gt;
%(smtpDriver):run(process)&lt;br /&gt;
 &lt;br /&gt;
end&lt;br /&gt;
USE Fred&lt;br /&gt;
DISPLAY PROCEDURE 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
==SMTP examples==&lt;br /&gt;
Examples follow in which &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects are used to create and send a request to an SMTP server.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Basic e-mail example===&lt;br /&gt;
This example uses most of the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to send a simple message to three recipients.&lt;br /&gt;
The local &amp;lt;var&amp;gt;CLSOCK&amp;lt;/var&amp;gt; port used is named &amp;lt;code&amp;gt;SPAM&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
 &lt;br /&gt;
%letter object Email&lt;br /&gt;
%h      longstring&lt;br /&gt;
%t      longstring&lt;br /&gt;
%name   longstring&lt;br /&gt;
%nick   string len 64&lt;br /&gt;
 &lt;br /&gt;
%letter = new&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;C_Coolidge@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;SilentCal&#039;&lt;br /&gt;
%letter:AddRecipient(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;D_Eisenhower@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;Ike&#039;&lt;br /&gt;
%letter:AddCc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = L_Johnson@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;LBJ&#039;&lt;br /&gt;
%letter:AddBcc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%letter:Sender(&#039;a_huckster@bankandtrustme.com&#039;)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Subject:&#039;&lt;br /&gt;
%t = &#039;Lower Mortgage Rates&#039;&lt;br /&gt;
%letter:AddHeader(%h, %t)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Great deal of debt for you!&#039;&lt;br /&gt;
%letter:SetBody(%h)&lt;br /&gt;
 &lt;br /&gt;
%letter:mail(&#039;SPAM&#039;, 0)&lt;br /&gt;
 &lt;br /&gt;
print %letter:GetReplyCode with &#039; - &#039; with -&lt;br /&gt;
      %letter:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%letter:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===E-mail with attachment===&lt;br /&gt;
In the following example, an image is attached to a short e-mail message.&lt;br /&gt;
The attachment is produced from a member of a local &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; procedure file&lt;br /&gt;
using &amp;lt;var&amp;gt;Stringlist&amp;lt;/var&amp;gt; class methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
%rolex is object Email&lt;br /&gt;
%sl   is object Stringlist&lt;br /&gt;
%procdata   is object Stringlist&lt;br /&gt;
%jpg longstring&lt;br /&gt;
%t longstring&lt;br /&gt;
%temp string len 255&lt;br /&gt;
%procfile string len 10&lt;br /&gt;
%procname string len 63&lt;br /&gt;
%q float&lt;br /&gt;
%rc float&lt;br /&gt;
 &lt;br /&gt;
%rolex = new&lt;br /&gt;
%sl   = new&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;jbgood@netscape.net&#039;&lt;br /&gt;
%rolex:AddRecipient(%t, &#039;JB&#039;)&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;cberry@ucantbee-sirius.com&#039;&lt;br /&gt;
%rolex:Sender(%t)&lt;br /&gt;
%rolex:AddHeader(&#039;Subject:&#039;, &#039;watch this...&#039;)&lt;br /&gt;
 &lt;br /&gt;
text to %sl&lt;br /&gt;
 I want an authentic imitation Rolex watch. Something like&lt;br /&gt;
 the one shown in this image. Know anyone who&#039;s got one?&lt;br /&gt;
end text&lt;br /&gt;
%rolex:SetBody(%sl, encoding=&#039;none&#039;, type=&#039;text/plain&#039;)&lt;br /&gt;
 &lt;br /&gt;
%procfile = &#039;MYPROC&#039;&lt;br /&gt;
%procname = &#039;FAKE5.JPG&#039;&lt;br /&gt;
%rc = $procopn(%procname, %procfile)&lt;br /&gt;
if %rc ne 0 then&lt;br /&gt;
   print &#039;Can&#039;&#039;t open procedure &#039; with %procname    -&lt;br /&gt;
    with &#039; in file &#039; with %procfile with &#039;, rc = &#039;  -&lt;br /&gt;
    with %rc&lt;br /&gt;
   stop&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%procdata = new&lt;br /&gt;
%procdata:appendOpenProcedure&lt;br /&gt;
%jpg = %procData:binaryProcedureDecode&lt;br /&gt;
%rolex:AddPart(%jpg, type=&#039;image/jpg&#039;, name=&#039;Rolex1.jpg&#039;)&lt;br /&gt;
 &lt;br /&gt;
print %rolex:mail(&#039;MYSMTP&#039;, 0) &#039; is return from Mail method&#039;&lt;br /&gt;
print %rolex:GetReplyCode &#039; is return from GetReplyCode&#039;&lt;br /&gt;
print %rolex:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%rolex:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
If the request is successful, results like the following display at the terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;0 is return from Mail method&lt;br /&gt;
221 is return from GetReplyCode&lt;br /&gt;
ucantbee-sirius.com running IBM VM SMTP Level 320&lt;br /&gt;
   closing connection&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==List of Email methods==&lt;br /&gt;
The [[List of Email methods|&amp;quot;List of Email methods&amp;quot;]] shows all the class methods.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets User Language coding considerations]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Sample Janus Sockets programs]]&lt;br /&gt;
&amp;lt;li&amp;gt;Socket-level interfaces:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets $functions|$functions]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Socket class]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Higher-level interfaces: &lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Email class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[HTTP Helper|HTTP Helper classes]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[LDAP class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus FTP Server]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Telnet Server]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Janus Sockets]] &lt;br /&gt;
[[Category:System classes]]&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68083</id>
		<title>Email class</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68083"/>
		<updated>2014-03-20T18:03:00Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class is a high level,&lt;br /&gt;
object oriented interface to client sockets that lets you write a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; SMTP&lt;br /&gt;
(Simple Mail Transfer Protocol) request without knowledge of socket level programming&lt;br /&gt;
or the format of SMTP requests and responses.&lt;br /&gt;
 &lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods let a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; program act as an SMTP client.&lt;br /&gt;
SMTP clients send mail requests&lt;br /&gt;
to an SMTP server, not directly to other SMTP clients.&lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods only support communication with SMTP servers.&lt;br /&gt;
 &lt;br /&gt;
An SMTP server will &amp;quot;store and forward&amp;quot; mail it receives.&lt;br /&gt;
This means that all&lt;br /&gt;
messages are first received in entirety on the SMTP server,&lt;br /&gt;
then the server attempts to deliver it to the recipients.&lt;br /&gt;
Mail delivery can be delayed by a server that is down or too busy to&lt;br /&gt;
accept connections.&lt;br /&gt;
&amp;quot;Store and forward&amp;quot; gives the SMTP server the ability&lt;br /&gt;
to retry delivery without making the SMTP client wait for completion.&lt;br /&gt;
 &lt;br /&gt;
A server might try to deliver a message for as long as a week or more.&lt;br /&gt;
This, of course, makes it impractical for a client to wait for delivery&lt;br /&gt;
confirmation, so the SMTP protocol does not provide such information.&lt;br /&gt;
A &amp;quot;success&amp;quot; response from an SMTP server indicates&lt;br /&gt;
only that the server has accepted the request and will&lt;br /&gt;
attempt to deliver the mail to the recipients.&lt;br /&gt;
 &lt;br /&gt;
Most SMTP servers will at least confirm that&lt;br /&gt;
any domain names in the recipient list are valid, but they cannot confirm that an&lt;br /&gt;
actual recipient name is valid.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;div id=&amp;quot;jport&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
You must define a Janus &amp;lt;var&amp;gt;[[JANUS CLSOCK|CLSOCK]]&amp;lt;/var&amp;gt; port to use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
If you supply the IP address&lt;br /&gt;
of the server and the port number in the port definition, SMTP&lt;br /&gt;
applications need only know the Janus port name to communicate with the server.&lt;br /&gt;
The following example defines a client socket port for use by SMTP applications.&lt;br /&gt;
For more detailed information about defining&lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; client socket ports, see &amp;lt;var&amp;gt;[[JANUS DEFINE]]&amp;lt;/var&amp;gt; and &amp;lt;var&amp;gt;[[JANUS CLSOCK]]&amp;lt;/var&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;JANUS DEFINE MYSMTP * CLSOCK 5 REMOTE 198.242.244.100 25&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039;&lt;br /&gt;
To use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects under versions of Model 204 earlier than 7.5, you must have licensed &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/var&amp;gt;, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus Sockets]]&amp;lt;/var&amp;gt;, &#039;&#039;&#039;and&#039;&#039;&#039; &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus SOAP]]&amp;lt;/var&amp;gt;. Under version 7.5 and later,&lt;br /&gt;
you do not require &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt;. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information about using SOUL objects, see [[Object oriented programming in SOUL]] and&lt;br /&gt;
[[Getting started with OOP for User Language programmers]].&lt;br /&gt;
&lt;br /&gt;
==Email class summary==&lt;br /&gt;
The following capabilities are provided by the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Creating general purpose e-mail for SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Sending general purpose e-mail via SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Setting e-mail content using &amp;lt;var&amp;gt;[[Longstrings]]&amp;lt;/var&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Sending MIME content (attachments and alternative content)&lt;br /&gt;
&amp;lt;li&amp;gt;Sending to multiple recipients&lt;br /&gt;
&amp;lt;li&amp;gt;Access to status (error or confirmation messages)&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; object to generate SMTP messages&lt;br /&gt;
(e-mail) to send to an SMTP server.&lt;br /&gt;
To construct a request, you use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to set and inspect&lt;br /&gt;
header information, content, and attachments.&lt;br /&gt;
To send e-mail, you use the &amp;lt;var&amp;gt;[[Mail (Email function)|Mail]]&amp;lt;/var&amp;gt; method.&lt;br /&gt;
 &lt;br /&gt;
[[List of Email methods]] contains a list of all the methods in the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
==Dummy SMTP Server example==&lt;br /&gt;
This is an example of very basic SMTP Service which simple excepts &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects from a SMTP client and response back to the client.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Dummy SMTP Server example===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;emclass&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* encoding enumerations.                                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
enumeration encoding&lt;br /&gt;
   public&lt;br /&gt;
   value base64&lt;br /&gt;
   value none&lt;br /&gt;
   end  public&lt;br /&gt;
end enumeration&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* emailPart class.                                                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class emailPart&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
   variable headers is object stringlist&lt;br /&gt;
   variable body is object stringlist&lt;br /&gt;
   function type is string len 255&lt;br /&gt;
   function encoding is string len 255&lt;br /&gt;
   function name is string len 255&lt;br /&gt;
   function contentlist is object stringlist&lt;br /&gt;
   function content is longstring&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return complete contentlist from an emailPart                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function contentlist is object stringlist&lt;br /&gt;
 &lt;br /&gt;
return %this:body&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Decode and return content from an emailPart                         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function content is longstring&lt;br /&gt;
 &lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 128&lt;br /&gt;
%encoding is string len 128&lt;br /&gt;
%lf   is string len 1&lt;br /&gt;
%i    is float&lt;br /&gt;
%j    is float&lt;br /&gt;
%content is longstring&lt;br /&gt;
%concat  is boolean initial(True)&lt;br /&gt;
%temp    is longstring&lt;br /&gt;
 &lt;br /&gt;
if %this:body eq null then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%lf = &#039;0A&#039;:x&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:body:count&lt;br /&gt;
   if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
      %content = %content with %this:body(%i)&lt;br /&gt;
   elseif %this:encoding eq &#039;quoted-printable&#039; then&lt;br /&gt;
      %temp = %this:body(%i):Unspace(Leading=False, Trailing=True, -&lt;br /&gt;
         Compress=False)&lt;br /&gt;
      if %concat = False then&lt;br /&gt;
         %content = %content %lf&lt;br /&gt;
      end if&lt;br /&gt;
      for %j from 1 to %temp:Length - 2&lt;br /&gt;
         if %temp:Substring(%j, 1) = &#039;=&#039; then&lt;br /&gt;
            %content = %content %temp:Substring(%j + 1, 2): -&lt;br /&gt;
            HexToString:AsciiToEbcdic(characterEncode=true)&lt;br /&gt;
            %j = %j + 2&lt;br /&gt;
         else&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end if&lt;br /&gt;
      end for&lt;br /&gt;
      if %j &amp;lt;= %temp:Length then&lt;br /&gt;
         for %j from %j to %temp:Length&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end for&lt;br /&gt;
      end if&lt;br /&gt;
      if %content:Right(1) = &#039;=&#039; then&lt;br /&gt;
         %concat = True&lt;br /&gt;
         %content = %content:TrimRight(1)&lt;br /&gt;
      else&lt;br /&gt;
         %concat = False&lt;br /&gt;
      end if&lt;br /&gt;
   else&lt;br /&gt;
      %content = %content %this:body(%i) with %lf&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
   %content = %content:base64ToString&lt;br /&gt;
   if %this:type:left(5) = &#039;text/&#039; then&lt;br /&gt;
      %content = %content:AsciiToEbcdic(CharacterEncode=true)&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %content&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the name (if present) of an emailPart                        *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function name is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%name is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Disposition:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; filename=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; name=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%name = %name:word(2, spaces=&#039; =&#039;)&lt;br /&gt;
if %name:left(1) = &#039;&amp;quot;&#039; then %name = %name:trimLeft(1); end if&lt;br /&gt;
if %name:right(1) = &#039;&amp;quot;&#039; then %name = %name:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
return %name&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the encoding (if present) of an emailPart                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function encoding is string len 255&lt;br /&gt;
 &lt;br /&gt;
%enc  is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
   %enc = %temp:word(2)&lt;br /&gt;
   if %enc:left(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimLeft(1); end if&lt;br /&gt;
   if %enc:right(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimRight(1); end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
if %enc = &#039;&#039; then %enc = &#039;7bit&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %enc&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the content type of an emailPart                             *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function type is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%type = %temp:word(2)&lt;br /&gt;
if %type:left(1) = &#039;&amp;quot;&#039; then %type = %type:trimLeft(1); end if&lt;br /&gt;
if %type:right(1) = &#039;&amp;quot;&#039; then %type = %type:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
if %type = &#039;&#039; then %type = &#039;text/plain&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %type&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* receivedEmail class.                                                *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class receivedEmail&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
  variable headers is object stringlist&lt;br /&gt;
  variable body is object stringlist&lt;br /&gt;
  variable rcptList is object stringlist&lt;br /&gt;
  variable fromHost is string len 128&lt;br /&gt;
  variable from     is string len 128&lt;br /&gt;
 &lt;br /&gt;
  function header -&lt;br /&gt;
    (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
     is string len 255&lt;br /&gt;
  function contentList (%x is float) is object stringlist&lt;br /&gt;
  function part (%number is float) is object emailPart&lt;br /&gt;
  function parts is float&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a header from the email message                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function header -&lt;br /&gt;
   (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
   is string len 255&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 255&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %toke  = %this:headers(%i):stringTokenizer&lt;br /&gt;
   %token = %toke:nextToken:toUpper&lt;br /&gt;
   %toke:discard&lt;br /&gt;
   if %name:toUpper eq %token then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %i &amp;gt; %this:headers:count then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%token = %this:headers(%i)&lt;br /&gt;
if %this:headers(%i):right(1) ne &#039;;&#039; then return %token; end if&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:headers:count&lt;br /&gt;
   %token = %token %this:headers(%i)&lt;br /&gt;
   if %this:headers(%i):right(1) ne &#039;;&#039; then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %token&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a &amp;quot;part&amp;quot; of an email message as an emailPart object.         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function part (%number is float) is object emailPart&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 72&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%encoding is string len 255&lt;br /&gt;
%partNumber is float&lt;br /&gt;
%cont is boolean initial(false)&lt;br /&gt;
%mime is boolean initial(false)&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
 &lt;br /&gt;
%part = new&lt;br /&gt;
%part:headers = new&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%part:headers = new&lt;br /&gt;
%part:body = new&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i) then&lt;br /&gt;
         %partNumber = %partNumber + 1&lt;br /&gt;
         if %partNumber = %number then loop end; end if&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %this:body(%i) eq &#039;&#039; then loop end; end if&lt;br /&gt;
      %part:headers:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i):substring(1, %bound:length) then&lt;br /&gt;
         loop end;&lt;br /&gt;
      end if&lt;br /&gt;
      %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
else&lt;br /&gt;
   assert %number eq 1&lt;br /&gt;
   for %i from 1 to %this:headers:count&lt;br /&gt;
      %temp = %this:headers(%i)&lt;br /&gt;
      if &#039;Content-&#039;:toUpper eq %temp:word(1):left(8):toUpper then&lt;br /&gt;
         %part:headers:add(%temp)&lt;br /&gt;
         for %i from %i + 1 to %this:headers:count&lt;br /&gt;
            if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
            %part:headers:add(%this:headers(%i))&lt;br /&gt;
         end for&lt;br /&gt;
         %i = %i - 1&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
     %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %part&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return number of &amp;quot;parts&amp;quot; of an email message.                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function parts is float&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 128&lt;br /&gt;
%parts is float&lt;br /&gt;
%temp  is longstring&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
else&lt;br /&gt;
   return 1&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%parts = 0&lt;br /&gt;
for %i from 1 to %this:body:count&lt;br /&gt;
   if %bound = %this:body(%i) then&lt;br /&gt;
      %parts = %parts + 1&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %parts&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* smtpDriver class.                                                   *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class smtpDriver&lt;br /&gt;
    public shared&lt;br /&gt;
       subroutine -&lt;br /&gt;
       run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
    end public shared&lt;br /&gt;
 &lt;br /&gt;
   subroutine run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
 &lt;br /&gt;
      %receivedEmail is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * SMTP server program.                                          *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * Static values used by the server.                             *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      %serverId         is string len 80 initial -&lt;br /&gt;
            (&amp;quot;host.sirius-software.com running Model 204 SMTP server&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * End of static values used by the server.                      *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      local subroutine (stringList):audit&lt;br /&gt;
      %i  is float&lt;br /&gt;
      for %i from 1 to %this:count&lt;br /&gt;
         auditText {%i}: {%this(%i)}&lt;br /&gt;
      end for&lt;br /&gt;
      end subroutine&lt;br /&gt;
 &lt;br /&gt;
      %remail                 is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      %msg                    is string len 128&lt;br /&gt;
      %client                 is string len 128&lt;br /&gt;
      %command                is string len 16&lt;br /&gt;
      %email                  is object receivedEmail&lt;br /&gt;
      %esmtp                  is boolean initial(false)&lt;br /&gt;
      %from                   is string len 128&lt;br /&gt;
      %by                     is string len 128&lt;br /&gt;
      %received               is string len 255&lt;br /&gt;
      %dateTime               is string len 128&lt;br /&gt;
      %inputLength            is float&lt;br /&gt;
      %inputLine              is longstring&lt;br /&gt;
      %sock                   is object socket&lt;br /&gt;
      %toke                   is object stringTokenizer&lt;br /&gt;
      %token                  is string len 128&lt;br /&gt;
 &lt;br /&gt;
      %sock = serverSocket&lt;br /&gt;
 &lt;br /&gt;
      %sock:set(&#039;CHAR&#039;, &#039;CHAR&#039;)&lt;br /&gt;
      %sock:set(&#039;LINEND&#039;, &#039;0D0A&#039;)&lt;br /&gt;
      %sock:set(&#039;PRSTOK&#039;, &#039;0D0A&#039;)&lt;br /&gt;
 &lt;br /&gt;
      %dateTime = -&lt;br /&gt;
         %(system):currentTimeString(&#039;DD Mon YYYY HH:MI:SS&#039;)&lt;br /&gt;
      %sock:sendWithLineEnd( -&lt;br /&gt;
         &amp;quot;220 &amp;quot; with %serverId with &amp;quot; on &amp;quot; with %dateTime)&lt;br /&gt;
 &lt;br /&gt;
      %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
 &lt;br /&gt;
      %toke = %inputLine:stringTokenizer&lt;br /&gt;
 &lt;br /&gt;
      %command = %toke:nextToken:toUpper&lt;br /&gt;
      if %command eq &#039;EHLO&#039; then&lt;br /&gt;
         %esmtp = true&lt;br /&gt;
      elseIf %command ne &#039;HELO&#039; then&lt;br /&gt;
         auditText *** Incorrect hello message received, -&lt;br /&gt;
            command={%command}, closing connection&lt;br /&gt;
         %sock:close&lt;br /&gt;
         stop&lt;br /&gt;
      end if&lt;br /&gt;
 &lt;br /&gt;
      %client = %toke:nextToken&lt;br /&gt;
      %msg = &amp;quot;250 Hello &amp;quot; with %client with -&lt;br /&gt;
         &amp;quot; I&#039;m delighted to meet you&amp;quot;&lt;br /&gt;
      %sock:sendWithLineEnd(%msg)&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Entering main SMTP loop for {%client}&lt;br /&gt;
      repeat forever&lt;br /&gt;
         %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
         %toke = %inputLine:stringTokenizer&lt;br /&gt;
         %command = %toke:nextToken:toUpper&lt;br /&gt;
         if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
         if %command ne &#039;MAIL&#039; then&lt;br /&gt;
            auditText **** Unexpected command {%command} received, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %token = %toke:nextToken&lt;br /&gt;
         if %token:left(5):toUpper ne &#039;FROM:&#039; then&lt;br /&gt;
            auditText **** MAIL followed by {%token} not -&lt;br /&gt;
               FROM:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %from = %token:substring(6)&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email = new&lt;br /&gt;
         %email:rcptList = new&lt;br /&gt;
 &lt;br /&gt;
         %toke = %sock:info(&#039;REMOTE&#039;):stringTokenizer&lt;br /&gt;
         %email:fromHost = %toke:nextToken&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            %toke = %inputLine:stringTokenizer&lt;br /&gt;
            %command = %toke:nextToken:toUpper&lt;br /&gt;
            if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
            if %command ne &#039;RCPT&#039; then loop end; end if&lt;br /&gt;
            %token = %toke:nextToken&lt;br /&gt;
            if %token:left(3):toUpper ne &#039;TO:&#039; then&lt;br /&gt;
               auditText **** RCPT followed by {%token} not -&lt;br /&gt;
                  TO:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
               jump to close&lt;br /&gt;
            end if&lt;br /&gt;
            %email:rcptList:add(%token:substring(4))&lt;br /&gt;
            %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         if %email:rcptList:count eq 0 then&lt;br /&gt;
            auditText **** No RCPT TO:s received after a -&lt;br /&gt;
               MAIL FROM:, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
 &lt;br /&gt;
         if %command ne &#039;DATA&#039; then&lt;br /&gt;
            auditText **** No DATA received after a RCPT TO:, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;354 End data with a single &#039;.&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email:headers = new&lt;br /&gt;
         setText %received = Received: from {%email:fromHost} by -&lt;br /&gt;
            {%serverid} ; -&lt;br /&gt;
            {%(system):currentTimeString(&#039;Wkd, DD Mon YYYY HH:MI:SS&#039;)}&lt;br /&gt;
         %email:headers:add(%received)&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine = &#039;&#039; then loop end; end if&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:headers:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %email:body = new&lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:body:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 E-mail received&amp;quot;)&lt;br /&gt;
      end repeat&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
      quit:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** QUIT received&lt;br /&gt;
      %sock:sendWithLineEnd(&amp;quot;221 Bye&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      close:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Terminating SMTP connection&lt;br /&gt;
      %sock:close&lt;br /&gt;
 &lt;br /&gt;
      %email:%processEmail&lt;br /&gt;
 &lt;br /&gt;
    end subroutine&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;driver.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UTABLE LNTBL 128&lt;br /&gt;
b&lt;br /&gt;
 &lt;br /&gt;
i emclass.ul&lt;br /&gt;
 &lt;br /&gt;
local subroutine (receivedEmail):process&lt;br /&gt;
 &lt;br /&gt;
%i     is float&lt;br /&gt;
%j     is float&lt;br /&gt;
%x     is float&lt;br /&gt;
%ls    is longstring&lt;br /&gt;
%op    is string len 8&lt;br /&gt;
%temp  is string len 255&lt;br /&gt;
%ename is string len 255&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%tp    is float&lt;br /&gt;
 &lt;br /&gt;
%tp = 0&lt;br /&gt;
setText %ename = CSURF_EMAIL_{$sir_date(&#039;YYMMDDHHMISS&#039;)}&lt;br /&gt;
%x = $bldproc(%tp, %ename, &#039;OPEN&#039;)&lt;br /&gt;
assert %x eq 0&lt;br /&gt;
*&lt;br /&gt;
* Get attachments and copy content to output procedure&lt;br /&gt;
*&lt;br /&gt;
%op = &#039;APPEND&#039;&lt;br /&gt;
for %i from 1 to %this:parts&lt;br /&gt;
   %part = %this:part(%i)&lt;br /&gt;
   for %j from 1 to %part:headers:count&lt;br /&gt;
      %temp = %part:headers(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
   for %j from 1 to %part:body:count&lt;br /&gt;
      %temp = %part:body(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
end subroutine&lt;br /&gt;
 &lt;br /&gt;
%(smtpDriver):run(process)&lt;br /&gt;
 &lt;br /&gt;
end&lt;br /&gt;
USE Fred&lt;br /&gt;
DISPLAY PROCEDURE 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
==SMTP examples==&lt;br /&gt;
Examples follow in which &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects are used to create and send a request to an SMTP server.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Basic e-mail example===&lt;br /&gt;
This example uses most of the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to send a simple message to three recipients.&lt;br /&gt;
The local &amp;lt;var&amp;gt;CLSOCK&amp;lt;/var&amp;gt; port used is named &amp;lt;code&amp;gt;SPAM&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
 &lt;br /&gt;
%letter object Email&lt;br /&gt;
%h      longstring&lt;br /&gt;
%t      longstring&lt;br /&gt;
%name   longstring&lt;br /&gt;
%nick   string len 64&lt;br /&gt;
 &lt;br /&gt;
%letter = new&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;C_Coolidge@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;SilentCal&#039;&lt;br /&gt;
%letter:AddRecipient(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;D_Eisenhower@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;Ike&#039;&lt;br /&gt;
%letter:AddCc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = L_Johnson@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;LBJ&#039;&lt;br /&gt;
%letter:AddBcc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%letter:Sender(&#039;a_huckster@bankandtrustme.com&#039;)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Subject:&#039;&lt;br /&gt;
%t = &#039;Lower Mortgage Rates&#039;&lt;br /&gt;
%letter:AddHeader(%h, %t)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Great deal of debt for you!&#039;&lt;br /&gt;
%letter:SetBody(%h)&lt;br /&gt;
 &lt;br /&gt;
%letter:mail(&#039;SPAM&#039;, 0)&lt;br /&gt;
 &lt;br /&gt;
print %letter:GetReplyCode with &#039; - &#039; with -&lt;br /&gt;
      %letter:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%letter:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===E-mail with attachment===&lt;br /&gt;
In the following example, an image is attached to a short e-mail message.&lt;br /&gt;
The attachment is produced from a member of a local &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; procedure file&lt;br /&gt;
using &amp;lt;var&amp;gt;Stringlist&amp;lt;/var&amp;gt; class methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
%rolex is object Email&lt;br /&gt;
%sl   is object Stringlist&lt;br /&gt;
%procdata   is object Stringlist&lt;br /&gt;
%jpg longstring&lt;br /&gt;
%t longstring&lt;br /&gt;
%temp string len 255&lt;br /&gt;
%procfile string len 10&lt;br /&gt;
%procname string len 63&lt;br /&gt;
%q float&lt;br /&gt;
%rc float&lt;br /&gt;
 &lt;br /&gt;
%rolex = new&lt;br /&gt;
%sl   = new&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;jbgood@netscape.net&#039;&lt;br /&gt;
%rolex:AddRecipient(%t, &#039;JB&#039;)&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;cberry@ucantbee-sirius.com&#039;&lt;br /&gt;
%rolex:Sender(%t)&lt;br /&gt;
%rolex:AddHeader(&#039;Subject:&#039;, &#039;watch this...&#039;)&lt;br /&gt;
 &lt;br /&gt;
text to %sl&lt;br /&gt;
 I want an authentic imitation Rolex watch. Something like&lt;br /&gt;
 the one shown in this image. Know anyone who&#039;s got one?&lt;br /&gt;
end text&lt;br /&gt;
%rolex:SetBody(%sl, encoding=&#039;none&#039;, type=&#039;text/plain&#039;)&lt;br /&gt;
 &lt;br /&gt;
%procfile = &#039;MYPROC&#039;&lt;br /&gt;
%procname = &#039;FAKE5.JPG&#039;&lt;br /&gt;
%rc = $procopn(%procname, %procfile)&lt;br /&gt;
if %rc ne 0 then&lt;br /&gt;
   print &#039;Can&#039;&#039;t open procedure &#039; with %procname    -&lt;br /&gt;
    with &#039; in file &#039; with %procfile with &#039;, rc = &#039;  -&lt;br /&gt;
    with %rc&lt;br /&gt;
   stop&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%procdata = new&lt;br /&gt;
%procdata:appendOpenProcedure&lt;br /&gt;
%jpg = %procData:binaryProcedureDecode&lt;br /&gt;
%rolex:AddPart(%jpg, type=&#039;image/jpg&#039;, name=&#039;Rolex1.jpg&#039;)&lt;br /&gt;
 &lt;br /&gt;
print %rolex:mail(&#039;MYSMTP&#039;, 0) &#039; is return from Mail method&#039;&lt;br /&gt;
print %rolex:GetReplyCode &#039; is return from GetReplyCode&#039;&lt;br /&gt;
print %rolex:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%rolex:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
If the request is successful, results like the following display at the terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;0 is return from Mail method&lt;br /&gt;
221 is return from GetReplyCode&lt;br /&gt;
ucantbee-sirius.com running IBM VM SMTP Level 320&lt;br /&gt;
   closing connection&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==List of Email methods==&lt;br /&gt;
The [[List of Email methods|&amp;quot;List of Email methods&amp;quot;]] shows all the class methods.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets User Language coding considerations]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Sample Janus Sockets programs]]&lt;br /&gt;
&amp;lt;li&amp;gt;Socket-level interfaces:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets $functions|$functions]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Socket class]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Higher-level interfaces: &lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Email class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[HTTP Helper|HTTP Helper classes]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[LDAP class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus FTP Server]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Telnet Server]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Janus Sockets]] &lt;br /&gt;
[[Category:System classes]]&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68082</id>
		<title>Email class</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Email_class&amp;diff=68082"/>
		<updated>2014-03-20T18:01:37Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class is a high level,&lt;br /&gt;
object oriented interface to client sockets that lets you write a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; SMTP&lt;br /&gt;
(Simple Mail Transfer Protocol) request without knowledge of socket level programming&lt;br /&gt;
or the format of SMTP requests and responses.&lt;br /&gt;
 &lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods let a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; program act as an SMTP client.&lt;br /&gt;
SMTP clients send mail requests&lt;br /&gt;
to an SMTP server, not directly to other SMTP clients.&lt;br /&gt;
The &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class methods only support communication with SMTP servers.&lt;br /&gt;
 &lt;br /&gt;
An SMTP server will &amp;quot;store and forward&amp;quot; mail it receives.&lt;br /&gt;
This means that all&lt;br /&gt;
messages are first received in entirety on the SMTP server,&lt;br /&gt;
then the server attempts to deliver it to the recipients.&lt;br /&gt;
Mail delivery can be delayed by a server that is down or too busy to&lt;br /&gt;
accept connections.&lt;br /&gt;
&amp;quot;Store and forward&amp;quot; gives the SMTP server the ability&lt;br /&gt;
to retry delivery without making the SMTP client wait for completion.&lt;br /&gt;
 &lt;br /&gt;
A server might try to deliver a message for as long as a week or more.&lt;br /&gt;
This, of course, makes it impractical for a client to wait for delivery&lt;br /&gt;
confirmation, so the SMTP protocol does not provide such information.&lt;br /&gt;
A &amp;quot;success&amp;quot; response from an SMTP server indicates&lt;br /&gt;
only that the server has accepted the request and will&lt;br /&gt;
attempt to deliver the mail to the recipients.&lt;br /&gt;
 &lt;br /&gt;
Most SMTP servers will at least confirm that&lt;br /&gt;
any domain names in the recipient list are valid, but they cannot confirm that an&lt;br /&gt;
actual recipient name is valid.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;div id=&amp;quot;jport&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
You must define a Janus &amp;lt;var&amp;gt;[[JANUS CLSOCK|CLSOCK]]&amp;lt;/var&amp;gt; port to use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
If you supply the IP address&lt;br /&gt;
of the server and the port number in the port definition, SMTP&lt;br /&gt;
applications need only know the Janus port name to communicate with the server.&lt;br /&gt;
The following example defines a client socket port for use by SMTP applications.&lt;br /&gt;
For more detailed information about defining&lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; client socket ports, see &amp;lt;var&amp;gt;[[JANUS DEFINE]]&amp;lt;/var&amp;gt; and &amp;lt;var&amp;gt;[[JANUS CLSOCK]]&amp;lt;/var&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;JANUS DEFINE MYSMTP * CLSOCK 5 REMOTE 198.242.244.100 25&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;&#039;&#039;&#039;Note:&#039;&#039;&#039;&lt;br /&gt;
To use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects under versions of Model 204 earlier than 7.5, you must have licensed &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/var&amp;gt;, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus Sockets]]&amp;lt;/var&amp;gt;, &#039;&#039;&#039;and&#039;&#039;&#039; &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Janus SOAP]]&amp;lt;/var&amp;gt;. Under version 7.5 and later,&lt;br /&gt;
you do not require &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt;. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For information about using SOUL objects, see [[Object oriented programming in SOUL]] and&lt;br /&gt;
[[Getting started with OOP for User Language programmers]].&lt;br /&gt;
&lt;br /&gt;
==Email class summary==&lt;br /&gt;
The following capabilities are provided by the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Creating general purpose e-mail for SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Sending general purpose e-mail via SMTP&lt;br /&gt;
&amp;lt;li&amp;gt;Setting e-mail content using &amp;lt;var&amp;gt;[[Longstrings]]&amp;lt;/var&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Sending MIME content (attachments and alternative content)&lt;br /&gt;
&amp;lt;li&amp;gt;Sending to multiple recipients&lt;br /&gt;
&amp;lt;li&amp;gt;Access to status (error or confirmation messages)&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You use the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; object to generate SMTP messages&lt;br /&gt;
(e-mail) to send to an SMTP server.&lt;br /&gt;
To construct a request, you use &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to set and inspect&lt;br /&gt;
header information, content, and attachments.&lt;br /&gt;
To send e-mail, you use the &amp;lt;var&amp;gt;[[Mail (Email function)|Mail]]&amp;lt;/var&amp;gt; method.&lt;br /&gt;
 &lt;br /&gt;
[[List of Email methods]] contains a list of all the methods in the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
==Dummy SMTP Server example==&lt;br /&gt;
This is an example of very basic SMTP Service which simple excepts &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects from a SMTP client and response back to the client.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Dummy SMTP Server example===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;emclass&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* encoding enumerations.                                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
enumeration encoding&lt;br /&gt;
   public&lt;br /&gt;
   value base64&lt;br /&gt;
   value none&lt;br /&gt;
   end  public&lt;br /&gt;
end enumeration&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* emailPart class.                                                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class emailPart&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
   variable headers is object stringlist&lt;br /&gt;
   variable body is object stringlist&lt;br /&gt;
   function type is string len 255&lt;br /&gt;
   function encoding is string len 255&lt;br /&gt;
   function name is string len 255&lt;br /&gt;
   function contentlist is object stringlist&lt;br /&gt;
   function content is longstring&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return complete contentlist from an emailPart                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function contentlist is object stringlist&lt;br /&gt;
 &lt;br /&gt;
return %this:body&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Decode and return content from an emailPart                         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function content is longstring&lt;br /&gt;
 &lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 128&lt;br /&gt;
%encoding is string len 128&lt;br /&gt;
%lf   is string len 1&lt;br /&gt;
%i    is float&lt;br /&gt;
%j    is float&lt;br /&gt;
%content is longstring&lt;br /&gt;
%concat  is boolean initial(True)&lt;br /&gt;
%temp    is longstring&lt;br /&gt;
 &lt;br /&gt;
if %this:body eq null then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%lf = &#039;0A&#039;:x&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:body:count&lt;br /&gt;
   if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
      %content = %content with %this:body(%i)&lt;br /&gt;
   elseif %this:encoding eq &#039;quoted-printable&#039; then&lt;br /&gt;
      %temp = %this:body(%i):Unspace(Leading=False, Trailing=True, -&lt;br /&gt;
         Compress=False)&lt;br /&gt;
      if %concat = False then&lt;br /&gt;
         %content = %content %lf&lt;br /&gt;
      end if&lt;br /&gt;
      for %j from 1 to %temp:Length - 2&lt;br /&gt;
         if %temp:Substring(%j, 1) = &#039;=&#039; then&lt;br /&gt;
            %content = %content %temp:Substring(%j + 1, 2): -&lt;br /&gt;
            HexToString:AsciiToEbcdic(characterEncode=true)&lt;br /&gt;
            %j = %j + 2&lt;br /&gt;
         else&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end if&lt;br /&gt;
      end for&lt;br /&gt;
      if %j &amp;lt;= %temp:Length then&lt;br /&gt;
         for %j from %j to %temp:Length&lt;br /&gt;
            %content = %content %temp:Substring(%j, 1)&lt;br /&gt;
         end for&lt;br /&gt;
      end if&lt;br /&gt;
      if %content:Right(1) = &#039;=&#039; then&lt;br /&gt;
         %concat = True&lt;br /&gt;
         %content = %content:TrimRight(1)&lt;br /&gt;
      else&lt;br /&gt;
         %concat = False&lt;br /&gt;
      end if&lt;br /&gt;
   else&lt;br /&gt;
      %content = %content %this:body(%i) with %lf&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %this:encoding eq &#039;base64&#039; then&lt;br /&gt;
   %content = %content:base64ToString&lt;br /&gt;
   if %this:type:left(5) = &#039;text/&#039; then&lt;br /&gt;
      %content = %content:AsciiToEbcdic(CharacterEncode=true)&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %content&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the name (if present) of an emailPart                        *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function name is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%name is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Disposition:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; filename=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      %n = %temp:positionOf(&#039; name=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %name = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%name = %name:word(2, spaces=&#039; =&#039;)&lt;br /&gt;
if %name:left(1) = &#039;&amp;quot;&#039; then %name = %name:trimLeft(1); end if&lt;br /&gt;
if %name:right(1) = &#039;&amp;quot;&#039; then %name = %name:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
return %name&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the encoding (if present) of an emailPart                    *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function encoding is string len 255&lt;br /&gt;
 &lt;br /&gt;
%enc  is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if &#039;Content-Transfer-Encoding:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
   %enc = %temp:word(2)&lt;br /&gt;
   if %enc:left(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimLeft(1); end if&lt;br /&gt;
   if %enc:right(1) = &#039;&amp;quot;&#039; then %enc = %enc:trimRight(1); end if&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
if %enc = &#039;&#039; then %enc = &#039;7bit&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %enc&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return the content type of an emailPart                             *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function type is string len 255&lt;br /&gt;
 &lt;br /&gt;
%type is string len 255&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
%i    is float&lt;br /&gt;
%n    is float&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %temp:word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %i = %i - 1&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%type = %temp:word(2)&lt;br /&gt;
if %type:left(1) = &#039;&amp;quot;&#039; then %type = %type:trimLeft(1); end if&lt;br /&gt;
if %type:right(1) = &#039;&amp;quot;&#039; then %type = %type:trimRight(1); end if&lt;br /&gt;
 &lt;br /&gt;
if %type = &#039;&#039; then %type = &#039;text/plain&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
return %type&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* receivedEmail class.                                                *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class receivedEmail&lt;br /&gt;
 &lt;br /&gt;
public&lt;br /&gt;
  variable headers is object stringlist&lt;br /&gt;
  variable body is object stringlist&lt;br /&gt;
  variable rcptList is object stringlist&lt;br /&gt;
  variable fromHost is string len 128&lt;br /&gt;
  variable from     is string len 128&lt;br /&gt;
 &lt;br /&gt;
  function header -&lt;br /&gt;
    (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
     is string len 255&lt;br /&gt;
  function contentList (%x is float) is object stringlist&lt;br /&gt;
  function part (%number is float) is object emailPart&lt;br /&gt;
  function parts is float&lt;br /&gt;
end public&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a header from the email message                              *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function header -&lt;br /&gt;
   (%name is string len 255, %occur is float default(1)) -&lt;br /&gt;
   is string len 255&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%toke is object stringTokenizer&lt;br /&gt;
%token is string len 255&lt;br /&gt;
 &lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %toke  = %this:headers(%i):stringTokenizer&lt;br /&gt;
   %token = %toke:nextToken:toUpper&lt;br /&gt;
   %toke:discard&lt;br /&gt;
   if %name:toUpper eq %token then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %i &amp;gt; %this:headers:count then return &#039;&#039;; end if&lt;br /&gt;
 &lt;br /&gt;
%token = %this:headers(%i)&lt;br /&gt;
if %this:headers(%i):right(1) ne &#039;;&#039; then return %token; end if&lt;br /&gt;
 &lt;br /&gt;
for %i from %i + 1 to %this:headers:count&lt;br /&gt;
   %token = %token %this:headers(%i)&lt;br /&gt;
   if %this:headers(%i):right(1) ne &#039;;&#039; then loop end; end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %token&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return a &amp;quot;part&amp;quot; of an email message as an emailPart object.         *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function part (%number is float) is object emailPart&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 72&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%encoding is string len 255&lt;br /&gt;
%partNumber is float&lt;br /&gt;
%cont is boolean initial(false)&lt;br /&gt;
%mime is boolean initial(false)&lt;br /&gt;
%temp is string len 255&lt;br /&gt;
 &lt;br /&gt;
%part = new&lt;br /&gt;
%part:headers = new&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
%part:headers = new&lt;br /&gt;
%part:body = new&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i) then&lt;br /&gt;
         %partNumber = %partNumber + 1&lt;br /&gt;
         if %partNumber = %number then loop end; end if&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %this:body(%i) eq &#039;&#039; then loop end; end if&lt;br /&gt;
      %part:headers:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from %i + 1 to %this:body:count&lt;br /&gt;
      if %bound = %this:body(%i):substring(1, %bound:length) then&lt;br /&gt;
         loop end;&lt;br /&gt;
      end if&lt;br /&gt;
      %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
else&lt;br /&gt;
   assert %number eq 1&lt;br /&gt;
   for %i from 1 to %this:headers:count&lt;br /&gt;
      %temp = %this:headers(%i)&lt;br /&gt;
      if &#039;Content-&#039;:toUpper eq %temp:word(1):left(8):toUpper then&lt;br /&gt;
         %part:headers:add(%temp)&lt;br /&gt;
         for %i from %i + 1 to %this:headers:count&lt;br /&gt;
            if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
            %part:headers:add(%this:headers(%i))&lt;br /&gt;
         end for&lt;br /&gt;
         %i = %i - 1&lt;br /&gt;
      end if&lt;br /&gt;
   end for&lt;br /&gt;
   for %i from 1 to %this:body:count&lt;br /&gt;
     %part:body:add(%this:body(%i))&lt;br /&gt;
   end for&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
return %part&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* Return number of &amp;quot;parts&amp;quot; of an email message.                       *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
function parts is float&lt;br /&gt;
 &lt;br /&gt;
%i is float&lt;br /&gt;
%n is float&lt;br /&gt;
%bound is string len 128&lt;br /&gt;
%parts is float&lt;br /&gt;
%temp  is longstring&lt;br /&gt;
 &lt;br /&gt;
* Scan global headers for boundary&lt;br /&gt;
for %i from 1 to %this:headers:count&lt;br /&gt;
   %temp = %this:headers(%i)&lt;br /&gt;
   if &#039;Content-Type:&#039;:toUpper eq %temp:word(1):toUpper then&lt;br /&gt;
      for %i from %i + 1 to %this:headers:count&lt;br /&gt;
         if %this:headers(%i):word(1):right(1) eq &#039;:&#039; then loop end; end if&lt;br /&gt;
         %temp = %temp %this:headers(%i)&lt;br /&gt;
      end for&lt;br /&gt;
      %n = %temp:positionOf(&#039;boundary=&#039;)&lt;br /&gt;
      if %n gt 0 then&lt;br /&gt;
         %bound = %temp:subString(%n)&lt;br /&gt;
      end if&lt;br /&gt;
      loop end;&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
if %bound ne &#039;&#039; then&lt;br /&gt;
   %bound = %bound:substring(10)&lt;br /&gt;
   if %bound:left(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimLeft(1); end if&lt;br /&gt;
   if %bound:right(1) = &#039;&amp;quot;&#039; then %bound = %bound:trimRight(1); end if&lt;br /&gt;
   %bound = &#039;--&#039; %bound;&lt;br /&gt;
else&lt;br /&gt;
   return 1&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%parts = 0&lt;br /&gt;
for %i from 1 to %this:body:count&lt;br /&gt;
   if %bound = %this:body(%i) then&lt;br /&gt;
      %parts = %parts + 1&lt;br /&gt;
   end if&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
return %parts&lt;br /&gt;
 &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
***********************************************************************&lt;br /&gt;
*                                                                     *&lt;br /&gt;
* smtpDriver class.                                                   *&lt;br /&gt;
*                                                                     *&lt;br /&gt;
***********************************************************************&lt;br /&gt;
class smtpDriver&lt;br /&gt;
    public shared&lt;br /&gt;
       subroutine -&lt;br /&gt;
       run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
    end public shared&lt;br /&gt;
 &lt;br /&gt;
   subroutine run(%processEmail is subroutine (receivedEmail):whatever)&lt;br /&gt;
 &lt;br /&gt;
      %receivedEmail is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * SMTP server program.                                          *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * Static values used by the server.                             *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      %serverId         is string len 80 initial -&lt;br /&gt;
            (&amp;quot;host.sirius-software.com running Model 204 SMTP server&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      *****************************************************************&lt;br /&gt;
      * End of static values used by the server.                      *&lt;br /&gt;
      *****************************************************************&lt;br /&gt;
 &lt;br /&gt;
      local subroutine (stringList):audit&lt;br /&gt;
      %i  is float&lt;br /&gt;
      for %i from 1 to %this:count&lt;br /&gt;
         auditText {%i}: {%this(%i)}&lt;br /&gt;
      end for&lt;br /&gt;
      end subroutine&lt;br /&gt;
 &lt;br /&gt;
      %remail                 is object receivedEmail&lt;br /&gt;
 &lt;br /&gt;
      %msg                    is string len 128&lt;br /&gt;
      %client                 is string len 128&lt;br /&gt;
      %command                is string len 16&lt;br /&gt;
      %email                  is object receivedEmail&lt;br /&gt;
      %esmtp                  is boolean initial(false)&lt;br /&gt;
      %from                   is string len 128&lt;br /&gt;
      %by                     is string len 128&lt;br /&gt;
      %received               is string len 255&lt;br /&gt;
      %dateTime               is string len 128&lt;br /&gt;
      %inputLength            is float&lt;br /&gt;
      %inputLine              is longstring&lt;br /&gt;
      %sock                   is object socket&lt;br /&gt;
      %toke                   is object stringTokenizer&lt;br /&gt;
      %token                  is string len 128&lt;br /&gt;
 &lt;br /&gt;
      %sock = serverSocket&lt;br /&gt;
 &lt;br /&gt;
      %sock:set(&#039;CHAR&#039;, &#039;CHAR&#039;)&lt;br /&gt;
      %sock:set(&#039;LINEND&#039;, &#039;0D0A&#039;)&lt;br /&gt;
      %sock:set(&#039;PRSTOK&#039;, &#039;0D0A&#039;)&lt;br /&gt;
 &lt;br /&gt;
      %dateTime = -&lt;br /&gt;
         %(system):currentTimeString(&#039;DD Mon YYYY HH:MI:SS&#039;)&lt;br /&gt;
      %sock:sendWithLineEnd( -&lt;br /&gt;
         &amp;quot;220 &amp;quot; with %serverId with &amp;quot; on &amp;quot; with %dateTime)&lt;br /&gt;
 &lt;br /&gt;
      %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
 &lt;br /&gt;
      %toke = %inputLine:stringTokenizer&lt;br /&gt;
 &lt;br /&gt;
      %command = %toke:nextToken:toUpper&lt;br /&gt;
      if %command eq &#039;EHLO&#039; then&lt;br /&gt;
         %esmtp = true&lt;br /&gt;
      elseIf %command ne &#039;HELO&#039; then&lt;br /&gt;
         auditText *** Incorrect hello message received, -&lt;br /&gt;
            command={%command}, closing connection&lt;br /&gt;
         %sock:close&lt;br /&gt;
         stop&lt;br /&gt;
      end if&lt;br /&gt;
 &lt;br /&gt;
      %client = %toke:nextToken&lt;br /&gt;
      %msg = &amp;quot;250 Hello &amp;quot; with %client with -&lt;br /&gt;
         &amp;quot; I&#039;m delighted to meet you&amp;quot;&lt;br /&gt;
      %sock:sendWithLineEnd(%msg)&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Entering main SMTP loop for {%client}&lt;br /&gt;
      repeat forever&lt;br /&gt;
         %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
         %toke = %inputLine:stringTokenizer&lt;br /&gt;
         %command = %toke:nextToken:toUpper&lt;br /&gt;
         if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
         if %command ne &#039;MAIL&#039; then&lt;br /&gt;
            auditText **** Unexpected command {%command} received, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %token = %toke:nextToken&lt;br /&gt;
         if %token:left(5):toUpper ne &#039;FROM:&#039; then&lt;br /&gt;
            auditText **** MAIL followed by {%token} not -&lt;br /&gt;
               FROM:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %from = %token:substring(6)&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email = new&lt;br /&gt;
         %email:rcptList = new&lt;br /&gt;
 &lt;br /&gt;
         %toke = %sock:info(&#039;REMOTE&#039;):stringTokenizer&lt;br /&gt;
         %email:fromHost = %toke:nextToken&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            %toke = %inputLine:stringTokenizer&lt;br /&gt;
            %command = %toke:nextToken:toUpper&lt;br /&gt;
            if %command eq &#039;QUIT&#039; then jump to quit; end if&lt;br /&gt;
            if %command ne &#039;RCPT&#039; then loop end; end if&lt;br /&gt;
            %token = %toke:nextToken&lt;br /&gt;
            if %token:left(3):toUpper ne &#039;TO:&#039; then&lt;br /&gt;
               auditText **** RCPT followed by {%token} not -&lt;br /&gt;
                  TO:&amp;lt;email-address&amp;gt;, terminating connection&lt;br /&gt;
               jump to close&lt;br /&gt;
            end if&lt;br /&gt;
            %email:rcptList:add(%token:substring(4))&lt;br /&gt;
            %sock:sendWithLineEnd(&amp;quot;250 Ok&amp;quot;)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         if %email:rcptList:count eq 0 then&lt;br /&gt;
            auditText **** No RCPT TO:s received after a -&lt;br /&gt;
               MAIL FROM:, terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
 &lt;br /&gt;
         if %command ne &#039;DATA&#039; then&lt;br /&gt;
            auditText **** No DATA received after a RCPT TO:, -&lt;br /&gt;
               terminating connection&lt;br /&gt;
            jump to close&lt;br /&gt;
         end if&lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;354 End data with a single &#039;.&#039;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
         %email:headers = new&lt;br /&gt;
         setText %received = Received: from {%email:fromHost} by -&lt;br /&gt;
            {%serverid} ; -&lt;br /&gt;
            {%(system):currentTimeString(&#039;Wkd, DD Mon YYYY HH:MI:SS&#039;)}&lt;br /&gt;
         %email:headers:add(%received)&lt;br /&gt;
 &lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine = &#039;&#039; then loop end; end if&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:headers:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %email:body = new&lt;br /&gt;
         repeat forever&lt;br /&gt;
            %inputLength = %sock:receiveAndParse(%inputLine)&lt;br /&gt;
            if %inputLine eq &#039;.&#039; then loop end; end if&lt;br /&gt;
            if %inputLine:left(2) eq &#039;..&#039; then&lt;br /&gt;
               %inputLine = %inputLine:substring(2);&lt;br /&gt;
            end if&lt;br /&gt;
            %email:body:add(%inputLine)&lt;br /&gt;
         end repeat&lt;br /&gt;
 &lt;br /&gt;
         %sock:sendWithLineEnd(&amp;quot;250 E-mail received&amp;quot;)&lt;br /&gt;
      end repeat&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
      quit:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** QUIT received&lt;br /&gt;
      %sock:sendWithLineEnd(&amp;quot;221 Bye&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
      close:&lt;br /&gt;
 &lt;br /&gt;
      auditText **** Terminating SMTP connection&lt;br /&gt;
      %sock:close&lt;br /&gt;
 &lt;br /&gt;
      %email:%processEmail&lt;br /&gt;
 &lt;br /&gt;
    end subroutine&lt;br /&gt;
 &lt;br /&gt;
end class&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;u&amp;gt;driver.ul&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
UTABLE LNTBL 128&lt;br /&gt;
b&lt;br /&gt;
 &lt;br /&gt;
i emclass.ul&lt;br /&gt;
 &lt;br /&gt;
local subroutine (receivedEmail):process&lt;br /&gt;
 &lt;br /&gt;
%i     is float&lt;br /&gt;
%j     is float&lt;br /&gt;
%x     is float&lt;br /&gt;
%ls    is longstring&lt;br /&gt;
%op    is string len 8&lt;br /&gt;
%temp  is string len 255&lt;br /&gt;
%ename is string len 255&lt;br /&gt;
%part  is object emailPart&lt;br /&gt;
%tp    is float&lt;br /&gt;
 &lt;br /&gt;
%tp = 0&lt;br /&gt;
setText %ename = CSURF_EMAIL_{$sir_date(&#039;YYMMDDHHMISS&#039;)}&lt;br /&gt;
%x = $bldproc(%tp, %ename, &#039;OPEN&#039;)&lt;br /&gt;
assert %x eq 0&lt;br /&gt;
*&lt;br /&gt;
* Get attachments and copy content to output procedure&lt;br /&gt;
*&lt;br /&gt;
%op = &#039;APPEND&#039;&lt;br /&gt;
for %i from 1 to %this:parts&lt;br /&gt;
   %part = %this:part(%i)&lt;br /&gt;
   for %j from 1 to %part:headers:count&lt;br /&gt;
      %temp = %part:headers(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
   for %j from 1 to %part:body:count&lt;br /&gt;
      %temp = %part:body(%j):left(255)&lt;br /&gt;
      %x = $bldproc(%tp, %temp, %op)&lt;br /&gt;
      assert %x eq 0&lt;br /&gt;
   end for&lt;br /&gt;
end for&lt;br /&gt;
 &lt;br /&gt;
end subroutine&lt;br /&gt;
 &lt;br /&gt;
%(smtpDriver):run(process)&lt;br /&gt;
 &lt;br /&gt;
end&lt;br /&gt;
USE Fred&lt;br /&gt;
DISPLAY PROCEDURE 0&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
==SMTP examples==&lt;br /&gt;
Examples follow in which &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; objects are used to create and send a request to an SMTP server.&lt;br /&gt;
No &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; port definitions are shown.&lt;br /&gt;
For comments about defining &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus&amp;lt;/var&amp;gt; ports for the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; class, see&lt;br /&gt;
the [[#jport|earlier]] remarks.&lt;br /&gt;
&lt;br /&gt;
===Basic e-mail example===&lt;br /&gt;
This example uses most of the &amp;lt;var&amp;gt;Email&amp;lt;/var&amp;gt; methods to send a simple message to three recipients.&lt;br /&gt;
The local &amp;lt;var&amp;gt;CLSOCK&amp;lt;/var&amp;gt; port used is named &amp;lt;code&amp;gt;SPAM&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
 &lt;br /&gt;
%letter object Email&lt;br /&gt;
%h      longstring&lt;br /&gt;
%t      longstring&lt;br /&gt;
%name   longstring&lt;br /&gt;
%nick   string len 64&lt;br /&gt;
 &lt;br /&gt;
%letter = new&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;C_Coolidge@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;SilentCal&#039;&lt;br /&gt;
%letter:AddRecipient(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = &#039;D_Eisenhower@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;Ike&#039;&lt;br /&gt;
%letter:AddCc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%name = L_Johnson@presidents.usa&#039;&lt;br /&gt;
%nick = &#039;LBJ&#039;&lt;br /&gt;
%letter:AddBcc(%name, %nick)&lt;br /&gt;
 &lt;br /&gt;
%letter:Sender(&#039;a_huckster@bankandtrustme.com&#039;)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Subject:&#039;&lt;br /&gt;
%t = &#039;Lower Mortgage Rates&#039;&lt;br /&gt;
%letter:AddHeader(%h, %t)&lt;br /&gt;
 &lt;br /&gt;
%h = &#039;Great deal of debt for you!&#039;&lt;br /&gt;
%letter:SetBody(%h)&lt;br /&gt;
 &lt;br /&gt;
%letter:mail(&#039;SPAM&#039;, 0)&lt;br /&gt;
 &lt;br /&gt;
print %letter:GetReplyCode with &#039; - &#039; with -&lt;br /&gt;
      %letter:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%letter:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===E-mail with attachment===&lt;br /&gt;
In the following example, an image is attached to a short e-mail message.&lt;br /&gt;
The attachment is produced from a member of a local &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; procedure file&lt;br /&gt;
using &amp;lt;var&amp;gt;Stringlist&amp;lt;/var&amp;gt; class methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;b&lt;br /&gt;
%rolex is object Email&lt;br /&gt;
%sl   is object Stringlist&lt;br /&gt;
%procdata   is object Stringlist&lt;br /&gt;
%jpg longstring&lt;br /&gt;
%t longstring&lt;br /&gt;
%temp string len 255&lt;br /&gt;
%procfile string len 10&lt;br /&gt;
%procname string len 63&lt;br /&gt;
%q float&lt;br /&gt;
%rc float&lt;br /&gt;
 &lt;br /&gt;
%rolex = new&lt;br /&gt;
%sl   = new&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;jbgood@netscape.net&#039;&lt;br /&gt;
%rolex:AddRecipient(%t, &#039;JB&#039;)&lt;br /&gt;
 &lt;br /&gt;
%t = &#039;cberry@ucantbee-sirius.com&#039;&lt;br /&gt;
%rolex:Sender(%t)&lt;br /&gt;
%rolex:AddHeader(&#039;Subject:&#039;, &#039;watch this...&#039;)&lt;br /&gt;
 &lt;br /&gt;
text to %sl&lt;br /&gt;
 I want an authentic imitation Rolex watch. Something like&lt;br /&gt;
 the one shown in this image. Know anyone who&#039;s got one?&lt;br /&gt;
end text&lt;br /&gt;
%rolex:SetBody(%sl, encoding=&#039;none&#039;, type=&#039;text/plain&#039;)&lt;br /&gt;
 &lt;br /&gt;
%procfile = &#039;MYPROC&#039;&lt;br /&gt;
%procname = &#039;FAKE5.JPG&#039;&lt;br /&gt;
%rc = $procopn(%procname, %procfile)&lt;br /&gt;
if %rc ne 0 then&lt;br /&gt;
   print &#039;Can&#039;&#039;t open procedure &#039; with %procname    -&lt;br /&gt;
    with &#039; in file &#039; with %procfile with &#039;, rc = &#039;  -&lt;br /&gt;
    with %rc&lt;br /&gt;
   stop&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
%procdata = new&lt;br /&gt;
%procdata:appendOpenProcedure&lt;br /&gt;
%jpg = %procData:binaryProcedureDecode&lt;br /&gt;
%rolex:AddPart(%jpg, type=&#039;image/jpg&#039;, name=&#039;Rolex1.jpg&#039;)&lt;br /&gt;
 &lt;br /&gt;
print %rolex:mail(&#039;MYSMTP&#039;, 0) &#039; is return from Mail method&#039;&lt;br /&gt;
print %rolex:GetReplyCode &#039; is return from GetReplyCode&#039;&lt;br /&gt;
print %rolex:GetReplyText&lt;br /&gt;
 &lt;br /&gt;
%rolex:discard&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
If the request is successful, results like the following display at the terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;code&amp;quot;&amp;gt;0 is return from Mail method&lt;br /&gt;
221 is return from GetReplyCode&lt;br /&gt;
ucantbee-sirius.com running IBM VM SMTP Level 320&lt;br /&gt;
   closing connection&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==List of Email methods==&lt;br /&gt;
The [[List of Email methods|&amp;quot;List of Email methods&amp;quot;]] shows all the class methods.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets User Language coding considerations]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Sample Janus Sockets programs]]&lt;br /&gt;
&amp;lt;li&amp;gt;Socket-level interfaces:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Sockets $functions|$functions]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Socket class]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Higher-level interfaces: &lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[Email class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[HTTP Helper|HTTP Helper classes]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[LDAP class]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus FTP Server]]&lt;br /&gt;
&amp;lt;li&amp;gt;[[Janus Telnet Server]]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category: Janus Sockets]] &lt;br /&gt;
[[Category:System classes]]&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Sirius_Software_product_list&amp;diff=67948</id>
		<title>Sirius Software product list</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Sirius_Software_product_list&amp;diff=67948"/>
		<updated>2014-03-11T15:32:32Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rocket Software, formerly &#039;&#039;&#039;[[Sirius Software]]&#039;&#039;&#039;, provides a wide variety of products to enhance and extend the &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;[[Model 204]]&amp;lt;/var&amp;gt; DBMS. Those products, shown in the table below, are now available through Rocket Software. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;3&amp;quot; width=&amp;quot;35%&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;tr class=&amp;quot;head&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;th align=&amp;quot;center&amp;quot; bgcolor=&amp;quot;#ffffd3&amp;quot;&amp;gt;&lt;br /&gt;
       Software product list&lt;br /&gt;
   &amp;lt;/th&amp;gt;&lt;br /&gt;
 &amp;lt;/tr&amp;gt;&lt;br /&gt;
 &amp;lt;tr&amp;gt;&lt;br /&gt;
   &amp;lt;td align=&amp;quot;left&amp;quot; valign=&amp;quot;top&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fast products:&lt;br /&gt;
 &amp;lt;ul class=&amp;quot;nobul&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/1/12/FastbackNew.pdf Fast/Backup]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/9/95/FrelrNew.pdf Fast/Reload]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[Fast/Unload User Language Interface]]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/0/0b/CramrNew.pdf Fast/Cram]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[[Fast/Unload]] &amp;lt;!--http://www.sirius-software.com/maint/download/funr.pdf --&amp;gt;&lt;br /&gt;
 &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;hr width=&amp;quot;85%&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;janus&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
Janus middleware products:&lt;br /&gt;
 &amp;lt;ul class=&amp;quot;nobul&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/d/de/JansslrNew.pdf Janus Network Security]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/1/17/JosrvrNew.pdf Janus Open Server]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/4/4a/JoclrNew.pdf Janus Open Client]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[[Janus SOAP]]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[[Janus Sockets]]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/e/e4/JsdsrNew.pdf Janus Specialty Data Store]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[Janus Web Server]]&amp;lt;/li&amp;gt; &lt;br /&gt;
 &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;hr width=&amp;quot;85%&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[ULSPF | UL/SPF]]:&lt;br /&gt;
 &amp;lt;ul class=&amp;quot;nobul&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirDBA]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirFile]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirLib]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirMon]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirPro]]&amp;lt;/li&amp;gt; &lt;br /&gt;
  &amp;lt;li&amp;gt;[[SirScan]]&amp;lt;/li&amp;gt; &lt;br /&gt;
 &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;hr width=&amp;quot;85%&amp;quot;&amp;gt;&lt;br /&gt;
[[Debugger | The Janus and Sirius Debuggers]] &lt;br /&gt;
&amp;lt;hr width=&amp;quot;85%&amp;quot;&amp;gt;&lt;br /&gt;
[[Japanese Functions]] &lt;br /&gt;
&amp;lt;hr width=&amp;quot;85%&amp;quot;&amp;gt;&lt;br /&gt;
Other products:&lt;br /&gt;
 &amp;lt;ul class=&amp;quot;nobul&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/f/fb/FactrNew.pdf SirFact] &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/4/4d/SafrNew.pdf SirSafe] &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[[SirTune]] &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/4/4b/SirfieldNew.pdf Sir2000 Field Migration Facility] &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/d/d6/Ul2krNew.pdf Sir2000 User Language Tools] &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/f/fc/AudrNew.pdf SirAud]&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li&amp;gt;[http://m204wiki.rocketsoftware.com/images/d/d4/SirzaprNew.pdf SirZap]&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt; &amp;lt;/td&amp;gt;&lt;br /&gt;
 &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can determine which products your site is authorized for by issuing the &amp;lt;var&amp;gt;[[SIRIUS command|SIRIUS]]&amp;lt;/var&amp;gt; command in an Online running a load module that includes the &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Sirius Mods&amp;lt;/var&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===See also===&lt;br /&gt;
&lt;br /&gt;
[http://www.rocketsoftware.com/products?brand=156&amp;amp;category=616 The Rocket M204 products web page]&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=What%27s_new&amp;diff=67947</id>
		<title>What&#039;s new</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=What%27s_new&amp;diff=67947"/>
		<updated>2014-03-11T15:29:30Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
This page contains recent and forthcoming additions of note to Model 204 documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; data-expandtext=&amp;quot;▼&amp;quot; data-collapsetext=&amp;quot;▲&amp;quot;&amp;gt;&lt;br /&gt;
==Model 204 Version 7.5==&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Version 7.5, the next release of Model 204, follows the recent acquisition of Sirius Software product line and integrates the Sirius and Janus software products into the Model 204 nucleus. One of the more exciting results of the integration is Simple Objective User Language, or SOUL. SOUL adds object-oriented programming to, and replaces the name of, User Language. It comes with no additional cost, and it is backward compatible with existing User Language applications.&lt;br /&gt;
&lt;br /&gt;
===Release notes===&lt;br /&gt;
The main features in this release of Model 204 are summarized on this page and described in greater detail in the [[Release notes for Model 204 version 7.5 (DRAFT)|version 7.5 release notes]].&lt;br /&gt;
&lt;br /&gt;
===SOUL===&lt;br /&gt;
Here are some of the new SOUL features:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Mixed case User Language support&lt;br /&gt;
&amp;lt;li&amp;gt;Generic User Language sorting, searching, and subsetting facilities&lt;br /&gt;
&amp;lt;li&amp;gt;Improved syntax for setting/retrieving large object (LOB) values (directly to/from longstrings)&lt;br /&gt;
&amp;lt;li&amp;gt;Enhanced printing and auditing statements&lt;br /&gt;
&amp;lt;li&amp;gt;Implicit concatenation&lt;br /&gt;
&amp;lt;li&amp;gt;The Assert and Loop Next statements &lt;br /&gt;
&amp;lt;li&amp;gt;A macro language&lt;br /&gt;
&amp;lt;li&amp;gt;Data types:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Longstring (including image string items &amp;gt; 255 bytes)&lt;br /&gt;
&amp;lt;li&amp;gt;Unicode &lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Full OO programming capabilities including:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Class and object definitions, methods, public/private class variables, inheritance, polymorphism, etc.&lt;br /&gt;
&amp;lt;li&amp;gt;Support for exceptions such as Try, Catch, and Throw statements&lt;br /&gt;
&amp;lt;li&amp;gt;Support for named parameters&lt;br /&gt;
&amp;lt;li&amp;gt;Support for method variables, that is, variables that can be used to dynamically invoke functions or subroutines&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Shorthand right-side assignment operators:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;%a = @ + 1&lt;br /&gt;
&amp;lt;li&amp;gt;%a = @ * 1&lt;br /&gt;
&amp;lt;li&amp;gt;%a = @ / 1&lt;br /&gt;
&amp;lt;li&amp;gt;%a = @ :div(1)&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===64-bit enablement of the Model 204 infrastructure===&lt;br /&gt;
Model 204 moves “Above the Bar” to increase scalability, performance, and growth potential. With this release of Model 204, 64-bit addressing becomes the de-facto standard for all subsequent versions. This may bring new challenges to customers who have written assembly language functions for use within Model 204, and Rocket Software has prepared a new set of service offerings to help accommodate upgrade and conversion needs.&lt;br /&gt;
&lt;br /&gt;
===Physical field groups===&lt;br /&gt;
Model 204 supports non-relational, denormalized data structures, and its efficient processing of multiply-occurring fields provides significant cost and performance benefits. This processing is enhanced by the availability of physical field groups, which let you view and process groups of fields as logical entities.&lt;br /&gt;
&lt;br /&gt;
===Range searching by Ordered Index (OI) chunk===&lt;br /&gt;
The new CHUNK attribute of the DEFINE FIELD command offers significantly more efficient searching on Ordered Index numeric (ORDERED NUMERIC) field ranges. The storage for the file&#039;s values of these fields is automatically maintained, divided into ordered sub-ranges (&amp;quot;OI chunks&amp;quot;) whose interval-size is part of the CHUNK definition. Finds of value ranges of these fields search by OI chunk rather than by individual value, so they entail fewer scans of the Ordered Index entries.&lt;br /&gt;
&lt;br /&gt;
===Expanded file-record limit===&lt;br /&gt;
In version 7.5 of Model 204, the record limit per file increases from sixteen million records to forty-eight million records.&lt;br /&gt;
&lt;br /&gt;
===New debugging tools===&lt;br /&gt;
Developing web and screen applications that use Model 204 is made easier by newly acquired debuggers: &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus Debugger&amp;lt;/var&amp;gt;, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;TN3270 Debugger&amp;lt;/var&amp;gt;, and &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SoftSpy&amp;lt;/var&amp;gt;.&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible mw-collapsed&amp;quot; data-expandtext=&amp;quot;▼&amp;quot; data-collapsetext=&amp;quot;▲&amp;quot;&amp;gt;&lt;br /&gt;
==The status of Janus SOAP==&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt; was an important of the Sirius Software product set that is still referenced frequently in the M204wiki pages. Significantly, Janus SOAP included &lt;br /&gt;
the Janus SOAP User Language Interface, also known as the Janus SOAP ULI. The Janus SOAP ULI was a collection of extensions to &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;User Language&amp;lt;/var&amp;gt; originally intended to simplify the coding of&lt;br /&gt;
applications that used the &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt; product. In version 7.5 of Model 204, the &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP ULI&amp;lt;/var&amp;gt; features were incorporated into Model 204. They are the new SOUL features [[#SOUL|highlighted above]]. &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP&amp;lt;/var&amp;gt; continues as a separate product providing support for [[Janus SOAP|XML processing]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote class=&amp;quot;note&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Note: &amp;lt;/b&amp;gt;The &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP ULI&amp;lt;/var&amp;gt; extensions did not alter the behavior of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;User Language&amp;lt;/var&amp;gt;. This is important on two counts:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;When the extensions formerly known as the &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Janus SOAP ULI&amp;lt;/var&amp;gt; are used, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL&amp;lt;/var&amp;gt; applications continue to work as they always have.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;All documentation concerning &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;SOUL/User Language&amp;lt;/var&amp;gt; remains valid. &lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=SOUL&amp;diff=67946</id>
		<title>SOUL</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=SOUL&amp;diff=67946"/>
		<updated>2014-03-11T15:23:51Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The SOUL programming language is used to write systems and applications in [[Model 204]]. The name of the language, SOUL, may be thought of as an acronym for Simple Objective User Language, which alludes to some of the language&#039;s essential features: Most significantly, it offers all of the benefits and features of the object oriented programming model, it provides a natural fit for programmers accustomed to other contemporary object oriented languages, and it provides syntax and semantics that are carefully tailored for the manipulation of Model 204 databases, seamlessly integrated in the language.&lt;br /&gt;
&lt;br /&gt;
Prior to version 7.5 of Model 204, the language used for systems and applications in Model 204 was named User Language, and a number of [[User Language#User Language becomes SOUL|Sirius Software extensions]] to it were available, including but not limited to object oriented features. Under Rocket Software, all the former Sirius products, including these extensions, were merged into the base Model 204 product or provided as separately licensed products.&lt;br /&gt;
&lt;br /&gt;
Starting with version 7.5 of Model 204, SOUL is available to all Model 204 customers. It is an evolving language, frequently enhanced. It contains all of the features formerly provided in User Language, together with the object oriented features provided by Rocket Software (including some, but not all, of the Sirius system classes).&lt;br /&gt;
&lt;br /&gt;
Since the former User Language and Rocket Software documentation is in the process of being combined to describe the single language, SOUL, the current documentation may contain references to &amp;quot;User Language&amp;quot; or to the &amp;quot;Janus SOAP User Language Interface&amp;quot; instead of simply to &amp;quot;SOUL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
==Getting started==&lt;br /&gt;
In the set of pages that document SOUL, it is recommended that:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For someone new to the language, begin with [[Introduction to User Language]].&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;For someone familiar with &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;User Language&amp;lt;/var&amp;gt; but not&lt;br /&gt;
the Sirius Software extensions, begin with [[Release_notes_for_Model_204_version_7.5_(DRAFT)#SOUL_.28User_Language.29_enhancements|Sirius enhancements added to V7.5 of Model 204]].&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;For an entry point to object-oriented SOUL, see [[Object oriented programming in SOUL]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;For an alphabetical list of links to all SOUL topics, refer to [[:Category:SOUL]].&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204_documentation&amp;diff=61819</id>
		<title>Model 204 documentation</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204_documentation&amp;diff=61819"/>
		<updated>2013-08-08T19:11:38Z</updated>

		<summary type="html">&lt;p&gt;SNelson: /* Model 204 core documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rocket Model 204 documentation is being converted from individual manuals in PDF format to a set of cross-linked HTML articles in this integrated wiki, M204wiki. Although it is the goal to move all Model 204 and Sirius PDF documents to M204wiki, many documents remain in PDF. The sections below specify which manuals have been converted and which manuals remain in PDF format. &lt;br /&gt;
&lt;br /&gt;
==Model 204 core documentation==&lt;br /&gt;
The following manuals have been converted to M204wiki:&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Manual&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;M204wiki starting page&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 User Language Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[:Category:SOUL|SOUL/User Language]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 File Manager&#039;s Guide&amp;lt;/var&amp;gt;&amp;lt;td&amp;gt;[[File Management Overview]]&amp;lt;br&amp;gt;[[File Architecture Overview]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 Parameter and Command Reference&amp;lt;/var&amp;gt;&amp;lt;td&amp;gt;[[List of Model 204 commands|Model 204 and Sirius commands]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[List of Model 204 parameters|Model 204 and Sirius parameters]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 Release Notes&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Model 204 version 7.5]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All other core Model 204 manuals remain in PDF: see [http://docs.rocketsoftware.com/nxt/gateway.dll?f=templates$fn=default.htm  Model 204 PDF Documentation]&lt;br /&gt;
&lt;br /&gt;
==Sirius documentation==&lt;br /&gt;
This section is the primary home page for Sirius documentation. A significant amount of the Sirius documentation now resides in M204wiki.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
The following manuals have been completely converted to M204wiki:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr class=&amp;quot;head&amp;quot;&amp;gt;&amp;lt;th&amp;gt;Manual&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;M204wiki starting page&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus SOAP Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus SOAP]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus Web Server Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus Web Server]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Mods Command and Parameter Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[List of Model 204 commands]]&amp;lt;br&amp;gt;[[List of Model 204 parameters]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus TCP/IP Base Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus Sockets Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus Sockets]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Functions Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[List of $functions]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Messages Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[:Category:Messages]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V8.1&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V8.1]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V8.0&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V8.0]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V7.9&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V7.9]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V7.8&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V7.8]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;UL/SPF Installation and Maintenance Guide&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[UL/SPF installation guide]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For products not in the list above, the PDFs remain the principal resource. &lt;br /&gt;
A complete list of PDF manuals is available at the [http://www.sirius-software.com/maint/manlist PDF Documentation] page on the Sirius Software web site.&lt;br /&gt;
The primary product manuals that are still in PDF format are:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;i&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/fastback.pdf Fast/Backup User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/cramr.pdf Fast/CRAM Installation Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/tlogr.pdf Fast/CRAM Trusted Login Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/frelr.pdf Fast/Reload Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/funr.pdf  Fast/Unload Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jansslr.pdf Janus Network Security Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/joclr.pdf Janus Open Client Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/josrvr.pdf Janus Open Server Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jsdsr.pdf Janus Specialty Data Store Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jansoldr.pdf Janus SOAP Reference Manual (6.4)]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jdebugr.pdf Janus/Sirius Debugger User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/siri.pdf Sirius Mods Installation Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/perfr.pdf Sirius Performance Enhancements Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/audr.pdf SirAud Installation and Reference Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/dbar.pdf SirDBA User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/factr.pdf SirFact Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/filr.pdf SirFile User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/libr.pdf SirLib User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/monr.pdf SirMon User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/pror.pdf SirPro User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/safr.pdf SirSafe Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/scanr.pdf SirScan User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/tunr.pdf SirTune Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/sirzapr.pdf SirZAP User&#039;s Guide and Reference]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/sirfield.pdf Sir2000 Field Migration Facility Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/ul2kr.pdf Sir2000 User Language Tools Reference Manual]&lt;br /&gt;
&amp;lt;/i&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204_documentation&amp;diff=61818</id>
		<title>Model 204 documentation</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204_documentation&amp;diff=61818"/>
		<updated>2013-08-08T19:10:12Z</updated>

		<summary type="html">&lt;p&gt;SNelson: /* Model 204 core documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Rocket Model 204 documentation is being converted from individual manuals in PDF format to a set of cross-linked HTML articles in this integrated wiki, M204wiki. Although it is the goal to move all Model 204 and Sirius PDF documents to M204wiki, many documents remain in PDF. The sections below specify which manuals have been converted and which manuals remain in PDF format. &lt;br /&gt;
&lt;br /&gt;
==Model 204 core documentation==&lt;br /&gt;
The following manuals have been converted to M204wiki:&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Manual&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;M204wiki starting page&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 User Language Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[:Category:SOUL|SOUL/User Language]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 File Manager&#039;s Guide&amp;lt;/var&amp;gt;&amp;lt;td&amp;gt;[[File Management Overview]]&amp;lt;br&amp;gt;[[File Architecture Overview]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 Parameter and Command Reference&amp;lt;/var&amp;gt;&amp;lt;td&amp;gt;[[List of Model 204 commands|Model 204 and Sirius commands]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[List of Model 204 parameters|Model 204 and Sirius parameters]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Rocket Model 204 Release Notes&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Model 204 version 7.5]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All other core Model 204 manuals remain in PDF: see [http://docs.rocketsoftware.com/nxt/gateway.dll?f=templates$fn=default.htm]&lt;br /&gt;
&lt;br /&gt;
==Sirius documentation==&lt;br /&gt;
This section is the primary home page for Sirius documentation. A significant amount of the Sirius documentation now resides in M204wiki.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
The following manuals have been completely converted to M204wiki:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
&amp;lt;tr class=&amp;quot;head&amp;quot;&amp;gt;&amp;lt;th&amp;gt;Manual&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;M204wiki starting page&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus SOAP Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus SOAP]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus Web Server Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus Web Server]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Mods Command and Parameter Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[List of Model 204 commands]]&amp;lt;br&amp;gt;[[List of Model 204 parameters]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus TCP/IP Base Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus TCP/IP Base]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Janus Sockets Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Janus Sockets]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Functions Reference Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[List of $functions]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Sirius Messages Manual&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[:Category:Messages]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V8.1&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V8.1]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V8.0&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V8.0]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V7.9&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V7.9]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;Release notes for Sirius Mods V7.8&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[Release notes for Sirius Mods V7.8]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;var class=&amp;quot;book&amp;quot;&amp;gt;UL/SPF Installation and Maintenance Guide&amp;lt;/var&amp;gt;&amp;lt;/td&amp;gt; &lt;br /&gt;
&amp;lt;td&amp;gt;[[UL/SPF installation guide]]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For products not in the list above, the PDFs remain the principal resource. &lt;br /&gt;
A complete list of PDF manuals is available at the [http://www.sirius-software.com/maint/manlist PDF Documentation] page on the Sirius Software web site.&lt;br /&gt;
The primary product manuals that are still in PDF format are:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;i&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/fastback.pdf Fast/Backup User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/cramr.pdf Fast/CRAM Installation Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/tlogr.pdf Fast/CRAM Trusted Login Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/frelr.pdf Fast/Reload Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/funr.pdf  Fast/Unload Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jansslr.pdf Janus Network Security Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/joclr.pdf Janus Open Client Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/josrvr.pdf Janus Open Server Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jsdsr.pdf Janus Specialty Data Store Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jansoldr.pdf Janus SOAP Reference Manual (6.4)]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/jdebugr.pdf Janus/Sirius Debugger User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/siri.pdf Sirius Mods Installation Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/perfr.pdf Sirius Performance Enhancements Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/audr.pdf SirAud Installation and Reference Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/dbar.pdf SirDBA User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/factr.pdf SirFact Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/filr.pdf SirFile User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/libr.pdf SirLib User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/monr.pdf SirMon User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/pror.pdf SirPro User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/safr.pdf SirSafe Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/scanr.pdf SirScan User&#039;s Guide]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/tunr.pdf SirTune Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/sirzapr.pdf SirZAP User&#039;s Guide and Reference]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/sirfield.pdf Sir2000 Field Migration Facility Reference Manual]&lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com/maint/download/ul2kr.pdf Sir2000 User Language Tools Reference Manual]&lt;br /&gt;
&amp;lt;/i&amp;gt;&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60517</id>
		<title>Model 204</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60517"/>
		<updated>2013-06-24T01:05:27Z</updated>

		<summary type="html">&lt;p&gt;SNelson: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Model 204&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt; is a DBMS for IBM and compatible mainframes, which was first deployed as a product in 1972.  Formerly owned by Computer Corporation of America (CCA), &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; was purchased in 2010 by Rocket Software, of Newton, Massachusetts.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is a database management system (DBMS) that provides facilities for the creation, control, query and maintenance of database files.  Access to the data is provided by an internal language known as &#039;&#039;&#039;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;User Language&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt;&#039;&#039;&#039;, by a variety of Host Language Interfaces (for example, you can embed queries to &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; data in COBOL, Assembler, Fortran, etc.) and via SQL using Horizon and CRAM interfaces.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; contains an embedded TP monitor that provides for user sessions directly in the DBMS address space.  Note that this makes &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; unique in the DBMS world:  Rather than users viewing the data from an external application, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; users typically hold full-screen sessions directly inside &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is highly parameterized and can be configured for environments that are quite compact and also for environments spanning the largest IBM and IBM-compatible multiprocessor machines.  &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;&#039;s strengths lie in its ability to handle very large volumes of data accessed by very large numbers of users, processing very high volumes of transactions.  In addition, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is characterized by its high level of integration and the ease and variety of programming approaches for application development.&lt;br /&gt;
 &lt;br /&gt;
The internal structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database files is based on a set of tables which hold file parameters, data records, indexes, procedures and binary large objects.  The sizing of the tables is based on expected use of the file.  Typically, procedures are held in separate files from data, but this is more of a standard practice and is not enforced by &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
While a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database can be fully &#039;&#039;Normalized&#039;&#039;, this too is not enforced by the structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  In fact, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; records can be completely free-form, with varying lengths of records and varying numbers of occurrences of same-named fields.  Because records, and the fields that are populated on records, do not require or use any pre-allocated space, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; lends itself to applications where record sizes vary greatly and where the largest records or greatest number of occurrences of any field or set of fields, is unpredictable.  Family records, for instance, are well-suited to Model 204 databases, as the average family might have 2 or 3 children, but many will have none, and a few will have dozens, or even hundreds.  In a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; file, the smallest &amp;quot;Family&amp;quot; record takes up only the space that it requires, and lives happily alongside other &amp;quot;Family&amp;quot; records&lt;br /&gt;
that are many times larger.&lt;br /&gt;
 &lt;br /&gt;
==Relationship to other vendors==&lt;br /&gt;
 &lt;br /&gt;
[[Sirius Software]] develops add-on software for &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;, including the Janus family of connectivity products and a wide variety of performance, tuning and functional enhancements.&lt;br /&gt;
 &lt;br /&gt;
Allscripts Corporation owns and develops a hospital system using &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; as the database engine.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[M204wiki main page#Model 204|Model 204 documentation on M204wiki]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/model204/documentation Model 204 PDF documentation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204 Rocket Software (M204)]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com Sirius Software, Inc.]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.allscripts.com/ Allscripts Corporation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60456</id>
		<title>Model 204</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60456"/>
		<updated>2013-06-20T15:23:44Z</updated>

		<summary type="html">&lt;p&gt;SNelson: /* Documentation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Model 204&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt; is a DBMS for IBM and compatible mainframes, which was first deployed as a product in 1972.  Formerly owned by Computer Corporation of America (CCA), &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; was purchased in 2010 by Rocket Software, of Newton, Massachusetts.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is a database management system (DBMS) that provides facilities for the creation, control, query and maintenance of database files.  Access to the data is provided by an internal language known as &#039;&#039;&#039;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;User Language&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt;&#039;&#039;&#039;, by a variety of Host Language Interfaces (for example, you can embed queries to &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; data in COBOL, Assembler, Fortran, etc.) and via SQL using Horizon and CRAM interfaces.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; contains an embedded TP monitor that provides for user sessions directly in the DBMS address space.  Note that this makes &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; unique in the DBMS world:  Rather than users viewing the data from an external application, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; users typically hold full-screen sessions directly inside &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is highly parameterized and can be configured for environments that are quite compact and also for environments spanning the largest IBM and IBM-compatible multiprocessor machines.  &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;&#039;s strengths lie in its ability to handle very large volumes of data accessed by very large numbers of users, processing very high volumes of transactions.  In addition, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is characterized by its high level of integration and the ease and variety of programming approaches for application development.&lt;br /&gt;
 &lt;br /&gt;
The internal structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database files is based on a set of tables which hold file parameters, data records, indexes, procedures and binary large objects.  The sizing of the tables is based on expected use of the file.  Typically, procedures are held in separate files from data, but this is more of a standard practice and is not enforced by &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
While a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database can be fully &#039;&#039;Normalized&#039;&#039;, this too is not enforced by the structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  In fact, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; records can be completely free-form, with varying lengths of records and varying numbers of occurrences of same-named fields.  Because records, and the fields that are populated on records, do not require or use any pre-allocated space, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; lends itself to applications where record sizes vary greatly and where the largest records or greatest number of occurrences of any field or set of fields, is unpredictable.  Family records, for instance, are well-suited to Model 204 databases, as the average family might have 2 or 3 children, but many will have none, and a few will have dozens, or even hundreds.  In a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; file, the smallest &amp;quot;Family&amp;quot; record takes up only the space that it requires, and lives happily alongside other &amp;quot;Family&amp;quot; records&lt;br /&gt;
that are many times larger.&lt;br /&gt;
 &lt;br /&gt;
==Relationship to other vendors==&lt;br /&gt;
 &lt;br /&gt;
[[Sirius Software]] develops add-on software for &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;, including the Janus family of connectivity products and a wide variety of performance, tuning and functional enhancements.&lt;br /&gt;
 &lt;br /&gt;
Allscripts Corporation owns and develops a hospital system using &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; as the database engine.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[M204wiki main page#Model 204|Model 204 documentation on M204wiki]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/model204/documentation Model 204 PDF documentation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/model204/documentation Rocket Software (M204)]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com Sirius Software, Inc.]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.allscripts.com/ Allscripts Corporation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60455</id>
		<title>Model 204</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60455"/>
		<updated>2013-06-20T15:08:24Z</updated>

		<summary type="html">&lt;p&gt;SNelson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Model 204&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt; is a DBMS for IBM and compatible mainframes, which was first deployed as a product in 1972.  Formerly owned by Computer Corporation of America (CCA), &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; was purchased in 2010 by Rocket Software, of Newton, Massachusetts.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is a database management system (DBMS) that provides facilities for the creation, control, query and maintenance of database files.  Access to the data is provided by an internal language known as &#039;&#039;&#039;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;User Language&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt;&#039;&#039;&#039;, by a variety of Host Language Interfaces (for example, you can embed queries to &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; data in COBOL, Assembler, Fortran, etc.) and via SQL using Horizon and CRAM interfaces.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; contains an embedded TP monitor that provides for user sessions directly in the DBMS address space.  Note that this makes &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; unique in the DBMS world:  Rather than users viewing the data from an external application, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; users typically hold full-screen sessions directly inside &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is highly parameterized and can be configured for environments that are quite compact and also for environments spanning the largest IBM and IBM-compatible multiprocessor machines.  &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;&#039;s strengths lie in its ability to handle very large volumes of data accessed by very large numbers of users, processing very high volumes of transactions.  In addition, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is characterized by its high level of integration and the ease and variety of programming approaches for application development.&lt;br /&gt;
 &lt;br /&gt;
The internal structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database files is based on a set of tables which hold file parameters, data records, indexes, procedures and binary large objects.  The sizing of the tables is based on expected use of the file.  Typically, procedures are held in separate files from data, but this is more of a standard practice and is not enforced by &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
While a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database can be fully &#039;&#039;Normalized&#039;&#039;, this too is not enforced by the structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  In fact, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; records can be completely free-form, with varying lengths of records and varying numbers of occurrences of same-named fields.  Because records, and the fields that are populated on records, do not require or use any pre-allocated space, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; lends itself to applications where record sizes vary greatly and where the largest records or greatest number of occurrences of any field or set of fields, is unpredictable.  Family records, for instance, are well-suited to Model 204 databases, as the average family might have 2 or 3 children, but many will have none, and a few will have dozens, or even hundreds.  In a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; file, the smallest &amp;quot;Family&amp;quot; record takes up only the space that it requires, and lives happily alongside other &amp;quot;Family&amp;quot; records&lt;br /&gt;
that are many times larger.&lt;br /&gt;
 &lt;br /&gt;
==Relationship to other vendors==&lt;br /&gt;
 &lt;br /&gt;
[[Sirius Software]] develops add-on software for &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;, including the Janus family of connectivity products and a wide variety of performance, tuning and functional enhancements.&lt;br /&gt;
 &lt;br /&gt;
Allscripts Corporation owns and develops a hospital system using &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; as the database engine.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[M204wiki main page#Model 204|Model 204 documentation on M204wiki]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/index/documentation Model 204 PDF documentation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/model204/documentation Rocket Software (M204)]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com Sirius Software, Inc.]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.allscripts.com/ Allscripts Corporation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
	<entry>
		<id>https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60454</id>
		<title>Model 204</title>
		<link rel="alternate" type="text/html" href="https://m204wiki.rocketsoftware.com/index.php?title=Model_204&amp;diff=60454"/>
		<updated>2013-06-20T15:06:04Z</updated>

		<summary type="html">&lt;p&gt;SNelson: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Model 204&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt; is a DBMS for IBM and compatible mainframes, which was first deployed as a product in 1972.  Formerly owned by Computer Corporation of America (CCA), &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; was purchased in 2010 by Rocket Software, of Newton, Massachusetts.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is a database management system (DBMS) that provides facilities for the creation, control, query and maintenance of database files.  Access to the data is provided by an internal language known as &#039;&#039;&#039;&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;&amp;lt;b&amp;gt;User Language&amp;lt;/b&amp;gt;&amp;lt;/var&amp;gt;&#039;&#039;&#039;, by a variety of Host Language Interfaces (for example, you can embed queries to &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; data in COBOL, Assembler, Fortran, etc.) and via SQL using Horizon and CRAM interfaces.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; contains an embedded TP monitor that provides for user sessions directly in the DBMS address space.  Note that this makes &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; unique in the DBMS world:  Rather than users viewing the data from an external application, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; users typically hold full-screen sessions directly inside &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is highly parameterized and can be configured for environments that are quite compact and also for environments spanning the largest IBM and IBM-compatible multiprocessor machines.  &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;&#039;s strengths lie in its ability to handle very large volumes of data accessed by very large numbers of users, processing very high volumes of transactions.  In addition, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; is characterized by its high level of integration and the ease and variety of programming approaches for application development.&lt;br /&gt;
 &lt;br /&gt;
The internal structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database files is based on a set of tables which hold file parameters, data records, indexes, procedures and binary large objects.  The sizing of the tables is based on expected use of the file.  Typically, procedures are held in separate files from data, but this is more of a standard practice and is not enforced by &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
While a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; database can be fully &#039;&#039;Normalized&#039;&#039;, this too is not enforced by the structure of &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;.  In fact, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; records can be completely free-form, with varying lengths of records and varying numbers of occurrences of same-named fields.  Because records, and the fields that are populated on records, do not require or use any pre-allocated space, &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; lends itself to applications where record sizes vary greatly and where the largest records or greatest number of occurrences of any field or set of fields, is unpredictable.  Family records, for instance, are well-suited to Model 204 databases, as the average family might have 2 or 3 children, but many will have none, and a few will have dozens, or even hundreds.  In a &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; file, the smallest &amp;quot;Family&amp;quot; record takes up only the space that it requires, and lives happily alongside other &amp;quot;Family&amp;quot; records&lt;br /&gt;
that are many times larger.&lt;br /&gt;
 &lt;br /&gt;
==Relationship to other vendors==&lt;br /&gt;
 &lt;br /&gt;
[[Sirius Software]] develops add-on software for &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt;, including the Janus family of connectivity products and a wide variety of performance, tuning and functional enhancements.&lt;br /&gt;
 &lt;br /&gt;
Eclipsys Corporation owns and develops a hospital system using &amp;lt;var class=&amp;quot;product&amp;quot;&amp;gt;Model 204&amp;lt;/var&amp;gt; as the database engine.&lt;br /&gt;
&lt;br /&gt;
==Documentation==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[[M204wiki main page#Model 204|Model 204 documentation on M204wiki]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/index/documentation Model 204 PDF documentation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.rocketsoftware.com/m204/products/model204/documentation Rocket Software (M204)]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://sirius-software.com Sirius Software, Inc.]&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.eclipsys.com/ Eclipsys Corporation]&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>SNelson</name></author>
	</entry>
</feed>