<<>> <> <> <> <> <<>> <> <<>> 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; <> <> 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] ~ { <> <> <> <> <> <> <> 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] = { <> 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]]; <> <> <> <> < 0 AND stripped.Fetch[i - 1] = ': AND Rope.EqualSubstrs[s1: stripped, start1: i, s2: thisOrganization, case: FALSE] THEN stripped _ stripped.Substr[len: i - 1]>> <> <> < 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; <> <> 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.