MSUtilsImpl.mesa
Copyright Ó 1988, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Wes Irish, December 22, 1988 6:25:48 pm PST
Willie-sue, January 28, 1993 6:17 pm PST
Utilities for manipulating MS stuff...
DIRECTORY
Basics,
BasicTime,
CrRPC,
EnvelopeContentsP0V0,
EnvelopeFormatP1517V1,
IO,
MailBasics,
MailFormatExtraTypes,
MailFormatP1516V3,
MailTransportP17V5,
MSBasics,
MailParse,
MSUtils,
RefText,
Rope,
SystemSite USING [Get, Names],
XNSCHItemOps,
XNSCHName;
MSUtilsImpl: CEDAR PROGRAM
IMPORTS BasicTime, CrRPC, EnvelopeContentsP0V0, IO, MailParse, RefText, Rope, SystemSite, XNSCHItemOps, XNSCHName
EXPORTS MSUtils
~ BEGIN
OPEN
EnvelopeContents: EnvelopeContentsP0V0,
EnvelopeFormat: EnvelopeFormatP1517V1,
MailFormat: MailFormatP1516V3,
MailTransport: MailTransportP17V5;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
NameBodyPairList: TYPE = MSUtils.NameBodyPairList;
NameBodyPair: TYPE = MSUtils.NameBodyPair;
Headers
In MS land a header is a BodyPart (specifically, bodyPart 0) and is encoded data. The MailUser interface also treats a header as a BodyPart but it is "text" in "822" format.
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];
};
maxRefTextLen: NAT ¬ LAST[RefText.TextBound] - 1;
ItemToRope: PUBLIC PROC [item: XNSCHItemOps.Item, length: CARDINAL ¬ LAST[CARDINAL]] RETURNS [rope: ROPE] ~ {
buf: Basics.Word16;
lenToDo: CARD16;
start: CARD16 ¬ 0;
text: REF TEXT;
IF item = NIL THEN RETURN[NIL];
lenToDo ¬ MIN[item.length, length];
text ¬ RefText.ObtainScratch[MIN[maxRefTextLen, lenToDo]];
DO
thisLen: CARD16 ¬ MIN[lenToDo, maxRefTextLen/2];
FOR i: CARDINAL IN [start..start+thisLen) DO
buf.card ¬ item.body[i];
text ¬ RefText.AppendChar[text, LOOPHOLE[buf.hi]];
text ¬ RefText.AppendChar[text, LOOPHOLE[buf.lo]];
ENDLOOP;
rope ¬ Rope.Concat[rope, Rope.FromRefText[text]];
IF ( lenToDo ¬ lenToDo - thisLen ) = 0 THEN EXIT;
start ¬ start+thisLen;
text.length ¬ 0;  -- reset text
ENDLOOP;
RefText.ReleaseScratch[text];
};
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];
};
XNSRNameFromRope: PUBLIC PROC [name: ROPE] RETURNS [rName: MSBasics.RName] ~ {
xnsRName: MSBasics.CHRName;
xnsRName ¬ NEW[MailTransport.RNameObject.xns ¬ [xns[]]];
xnsRName.xns ¬ XNSCHName.NameFromRope[name
! XNSCHName.FieldTooLong => RESUME];
RETURN[xnsRName];
};
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];
};
thisDomain, thisOrganization: ROPE;
Envelopes
Note: there are some items in the MailTransport.Envelope that do not exist in MSBasics.Envelope. MSBasics.Envelope contains only the envelope items that appear to be useful to clients. Someday this may need to extended if clients are interested in additional items...
ParseEnvelope: PUBLIC PROC [envelope: MailTransport.Envelope] RETURNS [parsed: MSBasics.Envelope] ~ {
h: CrRPC.Handle ¬ CrRPC.CreateClientHandle[$Loopback, NIL];
FOR i: CARDINAL IN [0..envelope.length) DO
item: MailTransport.EnvelopeItem ¬ envelope.body[i];
SELECT item.type FROM
-- Required Envelope Items:
EnvelopeFormat.postmark =>
parsed.postmark ¬ EnvelopeContents.PostmarkFromItem[h, item.value].value;
EnvelopeFormat.messageID =>
parsed.msgID ¬ EnvelopeContents.MessageIDFromItem[h, item.value].value;
EnvelopeFormat.contentsType =>
parsed.ctype ¬ EnvelopeContents.ContentsTypeFromItem[h, item.value].value;
EnvelopeFormat.tableOfContents =>
parsed.toc ¬ EnvelopeContents.TableOfContentsFromItem[h, item.value].value;
EnvelopeFormat.contentsSize =>
parsed.size ¬ EnvelopeContents.ContentsSizeFromItem[h, item.value].value;
EnvelopeFormat.originator =>
parsed.originator ¬ EnvelopeContents.OriginatorFromItem[h, item.value].value;
-- Other Envelope Items (may or may not exist):
EnvelopeFormat.authenticationLevelOfSender => {
parsed.authenticationLevel ¬ EnvelopeContents.AuthenticationLevelOfSenderFromItem[h, item.value].value;
parsed.authenticationLevelPresent ¬ TRUE;
};
EnvelopeFormat.report => {
parsed.report ¬ EnvelopeContents.ReportFromItem[h, item.value].value;
parsed.reportPresent ¬ TRUE;
};
EnvelopeFormat.gatewayPostmark => {
parsed.gatewayPostmark ¬ EnvelopeContents.GatewayPostmarkFromItem[h, item.value].value;
parsed.gatewayPostmarkPresent ¬ TRUE;
};
EnvelopeFormat.priority => {
parsed.priority ¬ EnvelopeContents.PriorityFromItem[h, item.value].value;
parsed.priorityPresent ¬ TRUE;
};
EnvelopeFormat.converted => {
parsed.converted ¬ EnvelopeContents.ConvertedFromItem[h, item.value].value;
parsed.convertedPresent ¬ TRUE;
};
ENDCASE => NULL;
ENDLOOP;
};
SystemMessageFromEnvelope: PUBLIC PROC [envelope: MSBasics.Envelope] RETURNS [msg: ROPE] ~ {
IF NOT envelope.reportPresent THEN RETURN[NIL];
msg ¬ IO.PutFR1["%g\r------------------\r",
[rope[RopeFromReport[envelope.report, TRUE]]]];
};
RopeFromEnvelope: PUBLIC PROC [envelope: MSBasics.Envelope, newLines: BOOL ¬ TRUE, indentation: ROPE ¬ NIL] RETURNS [ROPE] ~ {
out: STREAM ¬ IO.ROS[];
IF NOT newLines THEN indentation ¬ NIL;
IO.PutF[out, "%gPostmark: %g", [rope[indentation]], IO.rope[RopeFromPostmark[envelope.postmark]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gSender: %g", [rope[indentation]], IO.rope[RopeFromMSRName[envelope.originator]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gMessage-ID: %g", [rope[indentation]], [rope[RopeFromMessageID[envelope.msgID]]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gContents-type: %g", [rope[indentation]], IO.rope[RopeFromContentsType[envelope.ctype]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gMessage-Size: %g", [rope[indentation]], IO.int[envelope.size]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gTable-Of-Contents: %g", [rope[indentation]], IO.rope[RopeFromTOC[envelope.toc]]];
IF envelope.authenticationLevelPresent THEN {
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gAuthentication-Level-Of-Sender: %g", [rope[indentation]], IO.rope[RopeFromAuthenticationLevel[envelope.authenticationLevel]]];
};
IF envelope.gatewayPostmarkPresent THEN {
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gGateway: %g", [rope[indentation]], [rope[RopeFromPostmark[envelope.gatewayPostmark]]]];
};
IF envelope.priorityPresent THEN {
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gPriority: %g", [rope[indentation]], [rope[RopeFromPriority[envelope.priority]]]];
};
IF envelope.reportPresent THEN {
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gReport: %g", [rope[indentation]], [rope[RopeFromReport[envelope.report, FALSE]]]];
};
IF envelope.convertedPresent THEN {
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF[out, "%gConverted: %g", [rope[indentation]], [rope[RopeFromConverted[envelope.converted]]]];
};
IF newLines THEN IO.PutChar[out, '\r];
RETURN[IO.RopeFromROS[out]];
};
RopeFromMSRName: PUBLIC PROC [name: MSBasics.RName] RETURNS [rope: ROPE] ~ {
WITH name SELECT FROM
it: MSBasics.CHRName => {
rope ¬ XNSCHName.RopeFromName[it.xns] };
it: MSBasics.X400RName => { -- don't know how to print these yet!
rope ¬ "Some X.400 O/R name" };
ENDCASE => ERROR
};
RopeFromPostmark: PUBLIC PROC [postmark: MSBasics.Postmark] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFR["\"%g\" @ %g",
[rope[RopeFromMSRName[postmark.postedAt]]],
[time[BasicTime.FromNSTime[postmark.time]]]];
};
RopeFromContentsType: PUBLIC PROC [contentsType: MSBasics.ContentsType] RETURNS [rope: ROPE] ~ {
OPEN MSBasics;
rope ¬ SELECT contentsType FROM
ctStandardMessage => "InterpersonalMessage",
ctReport => "Delivery/NonDelivery-Report",
ctNull => "No Content",
ENDCASE => IO.PutFR1["contentsType(%g)", [cardinal[contentsType]]];
};
RopeFromPriority: PUBLIC PROC [priority: MSBasics.Priority] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT priority FROM
nonUrgent => "Non-Urgent",
normal => "Normal",
urgent => "Urgent",
unspecified => "Unspecified",
ENDCASE => IO.PutFR1["priority(%g)", [cardinal[ORD[priority]]]];
};
RopeFromMessageID: PUBLIC PROC [msgID: MSBasics.MessageID] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFLR["%g#%g#%g#%g#%g", LIST[IO.card[msgID[0]], IO.card[msgID[1]], IO.card[msgID[2]], IO.card[msgID[3]], IO.card[msgID[4]]] ];
};
RopeFromAuthenticationLevel: PUBLIC PROC [authLevel: MSBasics.AuthenticationLevelOfSender] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT authLevel FROM
strong => "Strong",
simple => "Simple",
foreign => "Foreign",
ENDCASE => IO.PutFR1["authLevel(%g)", [cardinal[ORD[authLevel]]]];
};
RopeFromBodyPartType: PUBLIC PROC [bodyPartType: MailTransport.BodyPartType] RETURNS [rope: ROPE] ~ {
OPEN MailFormat;
rope ¬ SELECT bodyPartType FROM
headingBodyPart => "header",
vpFolder => "vpFolder",
nsTextFile => "nsTextFile",
vpDocument => "vpDocument",
otherNSFile => "otherNSFile",
multinationalNote => "multinationalNote",
ia5Note => "ia5Note",
pilotFile => "pilotFile",
g3Fax => "g3Fax",
teletex => "teletex",
telex => "telex",
iso6937Note => "iso6937Note",
interpress => "interpress",
ENDCASE => IO.PutFR1["bodyPart(%g)", [cardinal[bodyPartType]]];
};
RopeFromTOC: PUBLIC PROC [toc: MSBasics.TableOfContents] RETURNS [rope: ROPE] ~ {
IF toc.length = 0 THEN RETURN["Empty"];
FOR i: CARDINAL IN [0..toc.length) DO
IF i > 0 THEN rope ¬ Rope.Concat[rope, ", "];
rope ¬ Rope.Concat[rope, IO.PutFR["(type: %g, size: %g)", [rope[RopeFromBodyPartType[toc[i].type]]], [integer[toc[i].sizeInBytes]]]];
ENDLOOP;
};
RopeFromConvertedItem: PUBLIC PROC [item: EnvelopeFormat.ConvertedItem] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT item FROM
ia5TextToTeletex => "ia5TextToTeletex",
teletexToTelex => "teletexToTelex",
teletexToIA5Text => "teletexToIA5Text",
telexToTeletex => "telexToTeletex",
ENDCASE => ERROR;
};
RopeFromReason: PUBLIC PROC [reason: EnvelopeFormat.Reason] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT reason FROM
noSuchRecipient => "noSuchRecipient",
noMailboxForRecipient => "noMailboxForRecipient",
illegalName => "illegalName",
timeout => "timeout",
reportNotAllowed => "reportNotAllowed",
messageTooLong => "messageTooLong",
ambiguousRName => "ambiguousRName",
illegalCharacters => "illegalCharacters",
unsupportedBodyparts => "unsupportedBodyparts",
unsupportedContentsType => "unsupportedContentsType",
transientProblem => "transientProblem",
contentSyntaxError => "contentSyntaxError",
tooManyRecipients => "tooManyRecipients",
protocolViolation => "protocolViolation",
x400PragmaticConstraintViolation => "x400PragmaticConstraintViolation",
x400NoBilateralAgreement => "x400NoBilateralAgreement",
accessRightsInsufficientForDL => "accessRightsInsufficientForDL",
other => "other",
ENDCASE => ERROR;
};
RopeFromDelType: PUBLIC PROC [delType: EnvelopeFormat.DelType] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT delType FROM
contentsTruncated => "contentsTruncated",
noProblem => "noProblem",
ENDCASE => ERROR;
};
RopeFromNonDelType: PUBLIC PROC [nonDelType: EnvelopeFormat.NonDelType] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFR["(reason: %g, reportCreationPostmark: %g)", [rope[RopeFromReason[nonDelType.reason]]], [rope[RopeFromPostmark[nonDelType.reportCreationPostmark]]]];
};
RopeFromFate: PUBLIC PROC [fate: EnvelopeFormat.Fate] RETURNS [rope: ROPE] ~ {
WITH fate SELECT FROM
delivered: REF delivered EnvelopeFormat.FateObject => rope ¬ IO.PutFR1["Delivered: %g", [rope[RopeFromDelType[delivered.delivered]]]];
notDelivered: REF notDelivered EnvelopeFormat.FateObject => rope ¬ IO.PutFR1["Not Delivered: %g", [rope[RopeFromNonDelType[notDelivered.notDelivered]]]];
ENDCASE => ERROR;
};
RopeFromReportType: PUBLIC PROC [reportType: MailTransport.ReportType] RETURNS [rope: ROPE] ~ {
rope ¬ SELECT reportType FROM
none => "none",
nonDeliveryOnly => "nonDeliveryOnly",
all => "all",
unknown => "unknown",
ENDCASE => IO.PutFR1["reportType(%g)", [cardinal[ORD[reportType]]]];
};
RopeFromRecipient: PUBLIC PROC [recipient: MSBasics.Recipient] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFR["(name: %g, id: %g, reportType: %g)", [rope[RopeFromMSRName[recipient.name]]], [cardinal[recipient.recipientID]], [rope[RopeFromReportType[recipient.report]]]];
};
RopeFromNonDeliveredRecipient: PUBLIC PROC [recipient: EnvelopeFormat.NonDeliveredRecipient] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFR["(recipient: %g, reason: %g)", [rope[RopeFromRecipient[recipient.recipient]]], [rope[RopeFromReason[recipient.reason]]]];
};
RopeFromDeliveredRecipient: PUBLIC PROC [recipient: EnvelopeFormat.DeliveredRecipient] RETURNS [rope: ROPE] ~ {
rope ¬ IO.PutFR["(recipient: %g, when: %g)", [rope[RopeFromRecipient[recipient.recipient]]], [time[BasicTime.FromNSTime[recipient.when]]]];
};
RopeFromInvalidRecipients: PUBLIC PROC [recipients: EnvelopeFormat.InvalRecip] RETURNS [rope: ROPE] ~ {
IF recipients.length = 0 THEN RETURN["No recipients"];
FOR i: CARDINAL IN [0..recipients.length) DO
IF i > 0 THEN rope ¬ Rope.Concat[rope, ", "];
rope ¬ Rope.Concat[rope, RopeFromNonDeliveredRecipient[recipients[i]]];
ENDLOOP;
};
RopeFromSucList: PUBLIC PROC [succeeded: EnvelopeFormat.SucList] RETURNS [rope: ROPE] ~ {
IF succeeded.length = 0 THEN RETURN["Empty"];
FOR i: CARDINAL IN [0..succeeded.length) DO
IF i > 0 THEN rope ¬ Rope.Concat[rope, ", "];
rope ¬ Rope.Concat[rope, RopeFromDeliveredRecipient[succeeded[i]]];
ENDLOOP;
};
RopeFromFailList: PUBLIC PROC [failed: EnvelopeFormat.FailList] RETURNS [rope: ROPE] ~ {
IF failed.length = 0 THEN RETURN["Empty"];
FOR i: CARDINAL IN [0..failed.length) DO
IF i > 0 THEN rope ¬ Rope.Concat[rope, ", "];
rope ¬ Rope.Concat[rope, RopeFromNonDeliveredRecipient[failed[i]]];
ENDLOOP;
};
RopeFromRepType: PUBLIC PROC [repType: EnvelopeFormat.RepType] RETURNS [rope: ROPE] ~ {
WITH repType SELECT FROM
dlMember: REF dlMember EnvelopeFormat.RepTypeObject => rope ¬ IO.PutFR["DL name: %g: %g", [rope[RopeFromMSRName[dlMember.dlMember.dlName]]], [rope[RopeFromInvalidRecipients[dlMember.dlMember.invalidDLRecipients]]]];
other: REF other EnvelopeFormat.RepTypeObject => rope ¬ IO.PutFR["Succeeded: %g, Failed: %g", [rope[RopeFromSucList[other.other.succeeded]]], [rope[RopeFromFailList[other.other.failed]]]];
ENDCASE => ERROR;
};
RopeFromConverted: PUBLIC PROC [converted: MSBasics.Converted] RETURNS [rope: ROPE] ~ {
IF converted.length = 0 THEN RETURN["No conversion"];
FOR i: CARDINAL IN [0..converted.length) DO
IF i > 0 THEN rope ¬ Rope.Concat[rope, ", "];
rope ¬ Rope.Concat[rope, RopeFromConvertedItem[converted[i]]];
ENDLOOP;
};
RopeFromReport: PUBLIC PROC [report: MSBasics.Report, newLines: BOOL ¬ TRUE] RETURNS [rope: ROPE] ~ {
out: STREAM ¬ IO.ROS[];
IO.PutF[out, "Original-Envelope:%g%g%g",
[rope[IF newLines THEN "\r" ELSE " {"]],
[rope[RopeFromEnvelope[ParseEnvelope[report.originalEnvelope], newLines, " "]]],
[rope[IF newLines THEN NIL ELSE "}"]]];
IO.PutRope[out, IF newLines THEN NIL ELSE ", "];
IO.PutF1[out, "Fate-Of-This-Report: %g", [rope[RopeFromFate[report.fateOfThisReport]]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE ", "];
IO.PutF1[out, "Report-Type: %g", [rope[RopeFromRepType[report.reportType]]]];
IO.PutRope[out, IF newLines THEN "\r" ELSE NIL];
RETURN[IO.RopeFromROS[out]];
};
InitNames: PROC = {
names: SystemSite.Names ¬ SystemSite.Get[];
thisDomain ¬ names.domain;
thisOrganization ¬ names.organization;
};
END.