// IfsMailUndeliv.bcpl -- "Return to sender: undeliverable"
// Copyright Xerox Corporation 1980, 1981
// Last modified September 18, 1983 1:44 PM by Taft
get "Ifs.decl"
get "IfsSystemInfo.decl"
get "IfsMail.decl"
external
[
// outgoing procedure
StartUndelivMsg; FinishUndelivMsg
// incoming procedures from other mail modules
StartMsg; WriteMNB; FinishMsg
MailStat; EnumerateMB; ReadMB; AppendRegistry
// incoming procedures - misc
LockCell; UnlockCell; VFileReadPage
StringCompare; ExtractSubstring; CopyString
PutTemplate; Wss; WRITEUDT; PrintIFSVersion
ReadBlock; SetFilePos; DiskToDisk
SysFree; FreePointer; MoveBlock
IFSError
// incoming statics
infoVMD
]
//----------------------------------------------------------------------------
let StartUndelivMsg(msg) be
//----------------------------------------------------------------------------
// Starts an undeliverable message msg to the sender of msg.
[
let uMsg = StartMsg(); if uMsg eq 0 return
// Sender of uMsg is Mailer.registry.
let sender = AppendRegistry("Mailer")
WriteMNB(uMsg, mbTypeSndr, sender)
// Recipient of uMsg is sender of msg.
SetFilePos(msg>>Msg.stream, lv msg>>Msg.posSndr)
let recip = ReadMB(msg); CopyString(recip, lv recip>>MNB.name)
if StringCompare(recip, sender) eq 0 then //Mailer sent msg.
[
let ms = VFileReadPage(infoVMD, msPage)
LockCell(lv ms)
let deadLtr, dot = lv ms>>MS.deadLtr, 0
test deadLtr>>String.length eq 0
ifso deadLtr = 0
ifnot
[
// Make sure deadLtr contains a registry.
for i = deadLtr>>String.length to 1 by -1 do
if deadLtr>>String.char↑i eq $. then [ dot = i; break ]
deadLtr = dot? ExtractSubstring(deadLtr), AppendRegistry(deadLtr)
]
UnlockCell(lv ms)
// Mailer sent msg so recipient should be deadLtr.
SysFree(recip); recip = deadLtr
EnumerateMB(msg, UndelivUndeliv, lv deadLtr)
if deadLtr eq 0 then //msg is undeliverable to deadLtr.
[ // Abondon uMsg, thereby discarding msg.
MailStat(msTypeDiscard)
FreePointer(lv recip, lv sender)
FinishMsg(uMsg, false)
return
]
]
WriteMNB(uMsg, mbTypeMlbx, recip)
// Generate the covering letter's header text.
let uStream = uMsg>>Msg.stream
PutTemplate(uStream, "To: $S", recip)
PutTemplate(uStream, "*NFrom: $S ($P mail job)",
sender, PrintIFSVersion, 0)
FreePointer(lv recip, lv sender)
Wss(uStream, "*NDate: "); WRITEUDT(uStream, 0, true)
Wss(uStream, "*NSubject: Undeliverable mail*N")
// Ready to generate the list of undeliverable recipients.
Wss(uStream, "*NUndeliverable to:")
msg>>Msg.uMsg = uMsg
]
//----------------------------------------------------------------------------
and UndelivUndeliv(mb, msg, lvDeadLtr) = valof
//----------------------------------------------------------------------------
// Called by EnumerateMB on behalf of StartUndelivMsg.
// Scans msg's recipients (which are by now exception blocks),
// looking for a recipient = deadLtr.
// If it finds one, then msg is undeliverable to deadLtr and
// a uMsg should not be created.
[
if mb>>MB.type ne mbTypeExcp % @lvDeadLtr eq 0 resultis false
if StringCompare(lv mb>>MNB.name, @lvDeadLtr) eq 0 then
[
mb>>MB.type = mbTypeFree
@lvDeadLtr = 0 //signal StartUndelivMsg to abandon uMsg
]
resultis mb>>MB.type eq mbTypeFree
]
//----------------------------------------------------------------------------
and FinishUndelivMsg(msg) be
//----------------------------------------------------------------------------
[
// copy the original message
SetFilePos(msg>>Msg.stream, lv msg>>Msg.posTxt)
let bytes = vec 1; MoveBlock(bytes, lv msg>>Msg.lenTxt, 2)
Wss(msg>>Msg.uMsg>>Msg.stream, "*N---------------------------*N")
DiskToDisk(msg>>Msg.uMsg>>Msg.stream, msg>>Msg.stream, bytes)
msg>>Msg.uMsg = FinishMsg(msg>>Msg.uMsg, true)
]