HeaderFromText:
PUBLIC
PROC
[text:
ROPE, includeTextAnnotation:
BOOL ¬
TRUE, plainText, formatting:
ROPE]
RETURNS [header: ROPE, errorCode: MailParse.ParseErrorCode ¬ none, index: INT ¬ 0, included: NameBodyPairList, notIncluded: NameBodyPairList] ~ {
Takes an "822" header as "text" and converts it into an encoded representation "header" that can be handed to MSSend as the header BodyPart. "text" may actually be a header followed by a message body; the two being delimited by the 822 standard "double-carriage-return".
If includeTextAnnotation=TRUE then any input fields that are unknow will be included in the TextAnnotation attribute in the resulting header.
errorCode indicates success or the particular problem encountered.
If errorCode indicates a problem then errorCode will point close to the point of problems.
If errorCode indicates success then index points just past the header. If "text" also included a message body then Rope.Substr[base: text, start: index] will be the portion of the message that should be sent as the message body.
included is a list of those fields that were successfully encoded into "header"
notIncluded is a list of those fields that were not successfully encoded into "header".
OPEN MailFormat;
Next:
PROC
RETURNS [c:
CHAR] ~ {
IF index < length
THEN {
c ¬ Rope.Fetch[text, index];
index ¬ index + 1;
}
ELSE c ¬ MailParse.endOfInput;
};
AddToIncludedList:
PROC [fieldName:
ROPE, fieldBody:
ROPE] ~ {
IF included =
NIL
THEN lastIncluded ¬ included ¬ LIST[[fieldName, fieldBody]]
ELSE lastIncluded ¬ lastIncluded.rest ¬ LIST[[fieldName, fieldBody]];
};
AddToNotIncludedList:
PROC [fieldName:
ROPE, fieldBody:
ROPE] ~ {
IF notIncluded =
NIL
THEN lastNotIncluded ¬ notIncluded ¬ LIST[[fieldName, fieldBody]]
ELSE lastNotIncluded ¬ lastNotIncluded.rest ¬ LIST[[fieldName, fieldBody]];
};
NameListFromRope:
PROC [names:
ROPE]
RETURNS [nameList: XNSCHItemOps.NameList] ~ {
LocalNext:
PROC
RETURNS [c:
CHAR] ~ {
IF localIndex < length
THEN {
c ¬ Rope.Fetch[names, localIndex];
localIndex ¬ localIndex + 1;
}
ELSE c ¬ IO.CR; -- this rope doesn't end with a CR so supply one
};
EachName:
PROC [rName: MailBasics.RName]
RETURNS [nameToWrite:
ROPE] ~ {
IF rName.name = NIL THEN RETURN[NIL];
SELECT rName.ns
FROM
$xns => AddNameToList[XNSCHName.NameFromRope[rName.name ! XNSCHName.FieldTooLong => RESUME]];
$file => AddPrivateDLToList[rName.name];
ENDCASE => NULL;
RETURN[NIL];
};
AddNameToList:
PROC [name: XNSCHName.Name] = {
IF nameList =
NIL
THEN lastName ¬ nameList ¬ LIST[name]
ELSE lastName ¬ lastName.rest ¬ LIST[name];
};
AddPrivateDLToList:
PROC [name:
ROPE] = {
xnsName: XNSCHName.Name;
xnsName.organization ¬ NIL;
xnsName.domain ¬ NIL;
xnsName.object ¬ name.Concat[":;"];
IF nameList =
NIL
THEN lastName ¬ nameList ¬ LIST[xnsName]
ELSE lastName ¬ lastName.rest ¬ LIST[xnsName];
};
lastName: XNSCHItemOps.NameList;
localIndex: INT ¬ 0;
length: INT ¬ Rope.Length[names];
localPH: MailParse.ParseHandle ¬ MailParse.InitializeParse[];
MailParse.NameList[localPH, $xns, LocalNext, EachName];
MailParse.FinalizeParse[localPH];
};
AddNameListAttribute:
PROC [list:
ROPE, value:
CARD32, fName:
ROPE, fBody:
ROPE] ~ {
nameList: XNSCHItemOps.NameList ¬ NameListFromRope[list];
tempPos: CARDINAL;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard32[value, pos, headerItem];
tempPos ¬ pos;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard16[card: 0, index: pos, item: headerItem];
[headerItem, pos] ¬ ItemFromNameListAsRNames[nameList, pos, headerItem];
[] ¬ XNSCHItemOps.Card16IntoItem[headerItem, pos-tempPos-1, tempPos];
attributeCount ¬ attributeCount + 1;
AddToIncludedList[fName, fBody];
};
AddNameAttribute:
PROC [name:
ROPE, value:
CARD32, fName:
ROPE, fBody:
ROPE] ~ {
tempPos: CARDINAL;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard32[value, pos, headerItem];
tempPos ¬ pos;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard16[card: 0, index: pos, item: headerItem];
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard16[0, pos, headerItem]; -- the tag: 0 = xns
[headerItem, pos] ¬ XNSCHItemOps.ItemFromName[XNSCHName.NameFromRope[name ! XNSCHName.FieldTooLong => RESUME], pos, headerItem];
[] ¬ XNSCHItemOps.Card16IntoItem[headerItem, pos-tempPos-1, tempPos];
attributeCount ¬ attributeCount + 1;
AddToIncludedList[fName, fBody];
};
AddRopeAttribute:
PROC [rope:
ROPE, value:
CARD32, fName:
ROPE, fBody:
ROPE] ~ {
tempPos: CARDINAL;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard32[value, pos, headerItem];
tempPos ¬ pos;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard16[card: 0, index: pos, item: headerItem];
[headerItem, pos] ¬ XNSCHItemOps.ItemFromRope[rope, pos, headerItem];
[] ¬ XNSCHItemOps.Card16IntoItem[headerItem, pos-tempPos-1, tempPos];
attributeCount ¬ attributeCount + 1;
IF fName # NIL THEN AddToIncludedList[fName, fBody];
};
lastIncluded: NameBodyPairList;
lastNotIncluded: NameBodyPairList;
textAnnotation: ROPE;
length: INT ¬ Rope.Length[text];
pH: MailParse.ParseHandle ¬ MailParse.InitializeParse[];
pos: CARDINAL ¬ 0;
attributeCount: CARDINAL ¬ 0;
headerItem: XNSCHItemOps.Item;
[headerItem, pos] ¬ XNSCHItemOps.ItemFromCard16[card: 0, index: 0, item: headerItem];
{
ENABLE MailParse.ParseError => { errorCode ¬ code; GOTO DoneWithError};
DO
fieldName: ROPE;
fieldBody: ROPE;
fieldName ¬ MailParse.GetFieldName[pH, Next];
IF fieldName = NIL THEN EXIT;
fieldBody ¬ MailParse.GetFieldBody[pH, Next];
SELECT
TRUE
FROM
Rope.Equal[s1: fieldName, s2: "Subject", case:
FALSE] => {
AddRopeAttribute[Rope.Substr[fieldBody, 0, 256], subject, fieldName, fieldBody];
};
Rope.Equal[s1: fieldName, s2: "Sender", case:
FALSE] => {
AddNameAttribute[fieldBody, originator, fieldName, fieldBody];
};
Rope.Equal[s1: fieldName, s2: "From", case:
FALSE] => {
AddNameListAttribute[fieldBody, authorizingUsers, fieldName, fieldBody];
};
Rope.Equal[s1: fieldName, s2: "To", case:
FALSE] => {
AddNameListAttribute[fieldBody, primaryRecipients, fieldName, fieldBody];
};
Rope.Equal[s1: fieldName, s2: "cc", case:
FALSE] => {
AddNameListAttribute[fieldBody, copyRecipients, fieldName, fieldBody];
};
Rope.Equal[s1: fieldName, s2: "Reply-To", case:
FALSE] => {
AddNameListAttribute[fieldBody, replyToUsers, fieldName, fieldBody];
};
ENDCASE => {
maxTextAnnotation: INT ¬ 2000;
additionalTextAnnotation: ROPE ¬ Rope.Cat[fieldName, ": ", fieldBody, "\r"];
IF includeTextAnnotation
AND (Rope.Length[textAnnotation] + Rope.Length[additionalTextAnnotation] <= maxTextAnnotation)
THEN textAnnotation ¬ Rope.Concat[textAnnotation, additionalTextAnnotation]
ELSE AddToNotIncludedList[fieldName, fieldBody];
};
ENDLOOP;
EXITS DoneWithError => NULL;
};
MailParse.FinalizeParse[pH];
IF includeTextAnnotation
AND textAnnotation #
NIL
THEN
AddRopeAttribute[textAnnotation, MailFormat.textAnnotation, "Text-Annotation", textAnnotation];
IF ( plainText #
NIL )
THEN {
AddRopeAttribute[plainText, MailFormatExtraTypes.tiogaPlainText, NIL, NIL];
AddRopeAttribute[formatting, MailFormatExtraTypes.tiogaFormatting, NIL, NIL];
};
[] ¬ XNSCHItemOps.Card16IntoItem[headerItem, attributeCount, 0];
header ¬ ItemToRope[headerItem];
};
ItemFromNameListAsRNames:
PROC [names: XNSCHItemOps.NameList, index:
CARDINAL ¬ 0, item: XNSCHItemOps.Item ¬
NIL]
RETURNS [newItem: XNSCHItemOps.Item, nextPos:
CARDINAL] ~ {
countIndex: CARDINAL ¬ index;
count: CARDINAL ¬ 0;
[item, index] ¬ XNSCHItemOps.ItemFromCard16[0, index, item]; -- place holder for count
FOR thisName: XNSCHItemOps.NameList ¬ names, thisName.rest
WHILE thisName #
NIL
DO
[item, index] ¬ XNSCHItemOps.ItemFromCard16[0, index, item]; -- the tag: 0 = xns
[item, index] ¬ XNSCHItemOps.ItemFromName[thisName.first, index, item];
count ¬ count + 1;
ENDLOOP;
[] ¬ XNSCHItemOps.Card16IntoItem[item, count, countIndex];
RETURN[item, index];
};
StrippedName:
PUBLIC
PROC[name, domain, organization:
ROPE]
RETURNS[stripped:
ROPE] = {
i: INT;
chName: XNSCHName.Name ¬ XNSCHName.NameFromRope[name, domain, organization ! XNSCHName.FieldTooLong => RESUME];
IF thisOrganization = NIL THEN InitNames[];
IF thisOrganization.Equal[chName.organization,
FALSE]
THEN {
IF thisDomain.Equal[chName.domain, FALSE] THEN RETURN[chName.object]
ELSE RETURN[Rope.Cat[chName.object, ":", chName.domain]];
};
RETURN[XNSCHName.RopeFromName[chName ! XNSCHName.FieldTooLong => RESUME]];
name ← XNSCHName.RopeFromName[XNSCHName.NameFromRope[name, domain, organization]];
IF thisOrganization = NIL THEN InitNames[];
i ← name.Length[] - thisOrganization.Length[];
stripped ← name;
IF i > 0 AND stripped.Fetch[i - 1] = ':
AND Rope.EqualSubstrs[s1: stripped, start1: i, s2: thisOrganization, case: FALSE] THEN stripped ← stripped.Substr[len: i - 1]
ELSE RETURN;
i ← stripped.Length[] - thisDomain.Length[];
IF i > 0 AND stripped.Fetch[i - 1] = ':
AND Rope.EqualSubstrs[s1: stripped, start1: i, s2: thisDomain, case: FALSE] THEN stripped ← stripped.Substr[len: i - 1];
};