ReadOneMessageX:
PUBLIC
PROC [handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender:
ROPE, stream:
IO.
STREAM ¬
NIL]
RETURNS [m, formatting:
ROPE ¬
NIL, bodyLength, formatLen, formatPos:
INT ¬ 0] ~ {
[m, formatting, bodyLength, formatLen, formatPos] ¬ DoReadOne[FALSE, handle, timeStamp, sender, stream]
};
ReadOneMessage:
PUBLIC
PROC [handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender:
ROPE, stream:
IO.
STREAM ¬
NIL]
RETURNS [m, formatting:
ROPE ¬
NIL, bodyLength, formatLen, formatPos:
INT ¬ 0] ~ {
[m, formatting, bodyLength, formatLen, formatPos] ¬ DoReadOne[TRUE, handle, timeStamp, sender, stream]
};
DoReadOne:
PROC [deleteLeadingCR:
BOOL, handle: MailRetrieve.Handle, timeStamp: MailBasics.Timestamp, sender:
ROPE, stream:
IO.
STREAM ¬
NIL]
RETURNS [m, formatting:
ROPE ¬
NIL, bodyLength, formatLen, formatPos:
INT ¬ 0] ~ {
ENABLE MailRetrieve.Failed => { GOTO failed };
header, plainText, formattedHeader, bodies: ROPE ¬ NIL;
sysMessage, attachments, unknowns: ROPE ¬ NIL;
buttonRope: ROPE ¬ NIL;
buttonType: MailBasics.ItemType;
MakeButton:
PROC[type: MailBasics.ItemType] ~ {
IF UserProfile.Boolean["MailUser.MakeButtonForSerializedFile",
FALSE]
THEN {
buttonRope ← MailRetrieve.GetItemAsRope[handle];
buttonType ← type
}
ELSE bodies ← bodies.Concat[MailRetrieve.GetItemAsRope[handle] ];
};
DO
item: MailBasics.ItemHeader ~ MailRetrieve.NextItem[handle];
SELECT item.type
FROM
MailBasicsItemTypes.envelope => {
NULL;
};
MailBasicsItemTypes.header => header ¬ MailRetrieve.GetItemAsRope[handle];
MailBasicsItemTypes.plainTextForFormatting => plainText ¬ MailRetrieve.GetItemAsRope[handle];
MailBasicsItemTypes.formattedHeader => formattedHeader ¬ MailRetrieve.GetItemAsRope[handle];
MailBasicsItemTypes.systemMessage =>
sysMessage ¬ sysMessage.Concat[MailRetrieve.GetItemAsRope[handle] ];
MailBasicsItemTypes.ia5Note,
MailBasicsItemTypes.text,
MailBasicsItemTypes.multinationalNote =>
bodies ¬ bodies.Concat[MailRetrieve.GetItemAsRope[handle] ];
MailBasicsMoreItemTypes.hasAttachment => MakeButton[item.type];
MailBasicsItemTypes.fullFormatting =>
formatting ¬ formatting.Concat[MailRetrieve.GetItemAsRope[handle] ];
MailBasicsItemTypes.tioga1 =>
formatting ¬ formatting.Concat[MailRetrieve.GetItemAsRope[handle] ];
MailBasicsItemTypes.gGW => { NULL };
MailBasicsItemTypes.pilotFile => { NULL };
MailBasicsItemTypes.tioga2 => { NULL };
MailBasicsItemTypes.walnutLog => { NULL };
MailBasicsItemTypes.capability => { NULL };
MailBasicsItemTypes.audio => { NULL }; -- we may use this someday
MailBasicsItemTypes.messageComposer => { NULL };
MailBasicsItemTypes.lastItem => {
EXIT
};
ENDCASE =>
unknowns ¬ unknowns.Concat[IO.PutFR["\r\r==>Discarded ItemType: %g (length %g bytes)<==\r",
[rope[MailUtils.RopeFromItemType[item.type]]],
[integer[item.length]]
] ];
ENDLOOP;
assemble the message from its parts
{
next: ROPE;
this is a hack so that formatting from SmallTalk will work
IF formatting # NIL THEN unknowns ¬ NIL;
SELECT
TRUE
FROM
attachments # NIL => { next ¬ attachments; attachments ¬ NIL };
unknowns # NIL => { next ¬ unknowns; unknowns ¬ NIL };
ENDCASE => { next ¬ bodies; bodies ¬ NIL };
SELECT
TRUE
FROM
sysMessage #
NIL => {
foo: ROPE ¬ IO.PutFR["Date: %g\rSender: %g\r", [time[MailUtils.GetTimeFromPostmark[timeStamp]]], [rope[sender]] ];
pos: INT ¬ sysMessage.Find["Report-Type: DL name:"];
dlOK: BOOL ¬ FALSE;
IF pos # -1
THEN {
pos2: INT ¬ sysMessage.Find[" (", pos];
IF pos2 # -1
THEN {
foo ¬ foo.Cat["Subject: Report for dl: ", sysMessage.Substr[pos, pos2-pos+1], "\r"];
dlOK ¬ TRUE;
};
};
IF NOT dlOK THEN
foo ¬ foo.Concat["Subject: Delivery / Non-Delivery Report information\r"];
foo ¬ foo.Cat[sysMessage, "\r"];
IF stream # NIL THEN stream.PutRope[foo]
ELSE m ¬ foo.Cat[sysMessage, "\r"];
bodyLength ¬ foo.Length[];
IF header # NIL THEN header ¬ IO.PutFR1["---------- Original-Header:\r%g\r----------\r", [rope[header]] ];
bodies ¬ header.Concat[bodies];
formatting ¬ NIL; -- won't be correct so toss
};
plainText #
NIL => {
-- don't want headers in this case
ch: CHAR ~ plainText.Fetch[0];
IF deleteLeadingCR THEN
IF ( ch = '\r ) OR ( ch = '\l ) THEN plainText ¬ plainText.Substr[1]; -- tioga stuff
IF stream # NIL THEN stream.PutRope[plainText] ELSE m ¬ plainText;
bodyLength ¬ plainText.Length[];
next ¬ NIL; -- kill multinationalnote part of message
};
ENDCASE => {
hL: INT = header.Length[];
numCRs: INT ¬ 0;
IF header #
NIL
THEN {
IF header.Fetch[hL-2] = '\r THEN numCRs ¬ numCRs + 1;
IF header.Fetch[hL-1] = '\r THEN numCRs ¬ numCRs + 1;
IF ( next # NIL ) AND ( next.Fetch[0] = '\r ) THEN numCRs ¬ numCRs + 1;
IF numCRs < 2 THEN header ¬ header.Concat["\r"];
IF stream # NIL THEN stream.PutRope[header]
ELSE m ¬ header;
bodyLength ¬ header.Length[];
};
};
IF stream # NIL THEN stream.PutRope[next] ELSE m ¬ m.Concat[next];
bodyLength ¬ bodyLength + next.Length[];
IF attachments #
NIL
THEN {
IF stream # NIL THEN stream.PutRope[attachments] ELSE m ¬ m.Concat[attachments];
bodyLength ¬ bodyLength + attachments.Length[];
};
IF unknowns #
NIL
THEN {
IF stream # NIL THEN stream.PutRope[unknowns] ELSE m ¬ m.Concat[unknowns];
bodyLength ¬ bodyLength + unknowns.Length[];
};
IF bodies #
NIL
THEN {
IF stream # NIL THEN stream.PutRope[bodies] ELSE m ¬ m.Concat[bodies];
bodyLength ¬ bodyLength + bodies.Length[];
};
};
IF buttonRope #
NIL
THEN {
props: IOTioga.PropList;
out: STREAM;
reader: TiogaAccess.Reader;
root: Tioga.Node;
posSlash, posAfter: INT;
fullRope: ROPE;
cr: ROPE ~ "\r";
pair: TiogaIO.Pair;
IF formatting # NIL THEN ERROR MailRetrieve.Failed[$malformedMsg, "a message has both a buttonRope and formatting"];
out ← IOTioga.CreateTiogaAccessStream[];
out.PutRope[m];
posSlash ← Rope.Find[buttonRope, "/"];
posAfter ← Rope.Find[buttonRope, "(", posSlash];
out.PutRope[buttonRope.Substr[0, posSlash]];
props ← IOTioga.PropPut[NIL, $Postfix, thePostfixValue];
props ← IOTioga.PropPut[props, $ButtonData, theButtonDataValue];
IOTioga.SetCharProps[out, props];
out.PutRope[Rope.Substr[buttonRope, posSlash, posAfter-posSlash-1]];
IOTioga.SetCharProps[out, NIL];
out.PutRope[Rope.Substr[buttonRope, posAfter-1]];
root ← TiogaAccess.WriteNode[IOTioga.WriterFromStream[out]];
TextEdit.PutProp[node: root, name: $NewlineDelimiter, value: cr];
pair ¬ TiogaIO.ToPair[root];
m ¬ pair.contents;
formatting ¬ pair.formatting;
};
IF stream #
NIL
THEN {
stream.PutRope[m];
bodyLength ¬ bodyLength + m.Length[];
};
IF ( formatting #
NIL )
AND ( stream #
NIL )
THEN {
formatPos ¬ stream.GetIndex[];
stream.PutRope[formatting];
formatLen ¬ formatting.Length[]
};
IF stream # NIL THEN stream.PutChar['\r];
RETURN;
EXITS
failed => RETURN[NIL, NIL, -1, -1, -1];
};