MailSplit

Command group Flag affected Reversible Execute on client Platform(s)
External commands YES NO NO All

Syntax

MailSplit (message,headerlist,body{Char|Bin|MIME-List}) Returns status

Description

Note: The flag is set according to whether Omnis was able to make a call to this external command.

This Web command is multi-threaded, allowing another thread to execute in the multi-threaded server while it runs. Note that the same socket cannot safely be used concurrently by more than one thread.

MAILSplit parses an Internet e-mail message. It can also decompose MIME content. It returns a Status value less than zero if an error occurs. Possible error codes are listed in the Web Command Error Codes Appendix.

Message is an Omnis Binary or Character field containing the complete text of an Internet e-mail message, including the header. Messages in this form are returned in the MailList argument of the POP3Recv command, and by the commands POP3RecvMessage and IMAPRecvMessage. You can also pass the headers returned by POP3RecvHeaders and IMAPRecvHeaders, in order to parse the headers.For correct results with many of the encodings supported by MAILSplit you must use a Binary field to receive the message.

Example message:

Received: by tigerlogic.com with SMTP; 12 Aug 1996 11:49:59 -0700
Received: (from someone@localhost) by netcom8.netcom.com (8.6.13/Netcom)
id LAA09789; Mon, 12 Aug 1996 11:46:45 -0700
Date: Mon, 12 Aug 1996 11:46:45 -0700
From: someone@somedomain.com (PersonalName here)
Message-Id: <199608121846.LAA09789@netcom8.netcom.com>
To: someoneelse@somedomain.com
Subject: This is an e-mail subject
Hello from TigerLogic Corporation

HeaderList is an Omnis list with two character columns. The list receives the information from the e-mail message header as attribute/value pairs. There is one row for each item in the header. For example, assuming the e-mail message above:

Attribute Value
Received by tigerlogic.com with SMTP; 12 Aug 1996 11:49:59 –0700
Received (from someone@localhost) by netcom8.netcom.com (8.6.13/Netcom)
id LAA09789; Mon, 12 Aug 1996 11:46:45 –0700
Date Mon, 12 Aug 1996 11:46:45 –0700
From someone@somedomain.com (PersonalName here)
Message-Id <199608121846.LAA09789@netcom8.netcom.com>
To someoneelse@somedomain.com
Subject This is an e-mail subject

Note: Two header lines may have the same attribute name. This is within the RFC822 message header specification. In this case, the HeaderList has two lines with the same Attribute name, as with Received in the above example. Long header lines that are split and continued in the message header are concatenated into one line in the list, as with the second Received attribute in the above example. The colon at the end of the attribute is stripped.

The Body parameter can be either an Omnis character field or an Omnis list.

If Body is an Omnis character field, MAILSplit returns the body of the e-mail message into this variable, minus the header. In the example: TigerLogic Corporation. Note, however, that if the body contains MIME content, the HeaderList only receives headers up to and excluding the MIME-Version header, and the body receives the rest of the message, starting with MIME-Version.

Alternatively, you can pass an Omnis list as the Body parameter. In this case, the HeaderList receives all of the headers, and the Body list receives either a single line containing the message body (if the message does not have MIME content), or a line for each MIME body part in the message body (if the message has MIME content). We discuss how MIME content is handled in this way below.

Header Values Containing International Characters

MAILSplit supports RFC 2047, for the UTF-8 and ISO8859-N character encodings. When it encounters text in header values that is encoded according to the RFC 2047 rules for the character encodings it supports, it converts the header value into its original value before storing it in the HeaderList.

MIME Content

MIME content can be thought of as a tree, which has a single root node, the message. Each node in the tree has a MIME type and a MIME subtype.

Non-leaf nodes have the type "multipart", and these contain other nodes, which themselves can be multipart. A non-leaf node does not contain data.

Leaf nodes have other types, such as "text" and "application", and these contain data. The type "message" can also be considered a container, but the MAILSplit (and SMTPSend) commands treat messages as leaf nodes. If you wish to decompose a message contained in MIME content, you need to call MAILSplit again for that message.

Each node in the tree is referred to as a body part.

The Body list receives a representation of the MIME content tree, with a line for each body part. Before calling MAILSplit, define a list with up to nine columns (the last three columns are optional):

Column Contains
Level A long integer which indicates the level of this node in the tree. The single root node has level zero. The next level down is one, and so on. This will become clearer in some examples below.
Content-type The type of this body part e.g. "text" or "multipart"
Content-subtype The sub-type of this body part e.g. "plain"
Filename The name of the file corresponding to this body-part. Used for leaf-nodes which are file attachments.
Character data If the content-type is "text" or "message", this column contains the data. Leaf nodes only.
Binary data If the content-type is not "text", "message" or "multipart", this column contains the data. Leaf nodes only.
Character-set The character set of the data. The commands only understand us-ascii and iso-8859-1. The latter is equivalent to the Ansi character set used on the Windows platforms. Character data in any other character set will not be handled correctly.
Content-Transfer-Encoding

How the data is encoded: "base64", "quoted-printable", "7bit" etc. The command handles decoding from base64 and quoted-printable, meaning that the data in the character and binary columns above has been decoded.

On the Macintosh, character data in the iso-8859-1 character set has been converted to the Macintosh character set.

On all platforms, the command replaces CRLFs with the Omnis newline character.

Content-disposition The content disposition of the body part. Either empty, "attachment" or "inline". This is a hint to the receiving application about how to handle the content. Inline body parts are intended to be displayed when the message is displayed, whereas attachments are considered separate from the main body of the mail message, and their display should not be automatic.

Some example lists:

A message sent by a mailer such as Outlook Express, containing both text and HTML versions of the message text:

Lev Content-type Content-subtype File Char Bin Char-set Encoding Disposition
0 multipart Alternative            
1 text Plain   From Bob   iso-8859-1 quoted-printable
1 text Html   <!DOCTYPE HTML…   iso-8859-1 quoted-printable

A message sent by a mailer such as Outlook Express, containing both text and HTML versions of the message text, and having a single file attachment:

Lev Content-type Content-subtype File Char Bin Char-set Encoding Disposition
0 multipart mixed            
1 multipart alternative            
2 text plain   From Bob   iso-8859-1 quoted-printable
2 text html   <!DOCTYPE HTML…   iso-8859-1 quoted-printable
1 application octet-stream App.h   This is my file data…   base64 attachment

Example

; Split and decompose pMessage as received from POP3Recv,POP3RecvHeaders,POP3RecvMessage,
; IMAPRecvHeaders or IMAPRecvMessage
; Return pDate, pFrom, pSubject and pBody (if message rather than headers) and save
; any attachments in pEnclosurePath
Do lHeaderList.$define(lAttribute,lValue)
Do lMimeList.$define(lLevel,lContentType,lContentSubType,lFileName,lCharData,lBinData,lCharSet,lEncoding)
MailSplit (pMessage,lHeaderList,lMimeList)
; extract header information
Do lHeaderList.$search(upp(lAttribute)='DATE'|upp(lAttribute)='FROM'|upp(lAttribute)='SUBJECT')
Do lHeaderList.$first(kTrue,kFalse) Returns lLineRef
While lLineRef
  Do lHeaderList.$loadcols()
  Switch upp(lAttribute)
    Case 'DATE'
      Calculate pDate as lValue
    Case 'FROM'
      Calculate pFrom as lValue
    Case 'SUBJECT'
      Calculate pSubject as lValue
  End Switch
  Do lHeaderList.$next(lLineRef,kTrue,kFalse)
End While
; decompose the MIME content from lMimeList
For lMimeList.$line from 1 to lMimeList.$linecount step 1
  Do lMimeList.$loadcols()
  If lContentType='text'&(lContentSubType='plain') ;; found body of e-mail in character format.
    Calculate pBody as lCharData
  End If
  If lFileName<>'' ;; found file attachment, write the file to the enclosures folder
    Calculate lFilePath as con(pEnclosurePath,lFileName)
    Do lFileOps.$createfile(lFilePath)
    Do lFileOps.$openfile(lFilePath)
    Do lFileOps.$writefile(lBinData) Returns lReturnFlag
    Do lFileOps.$closefile()
  End If
End For