Files

763 lines
25 KiB
Plaintext

# Property of Four Js*
# (c) Copyright Four Js 1995, 2019. All Rights Reserved.
# * Trademark of Four Js Development Tools Europe Ltd
# in the United States and elsewhere
#
# Four Js and its suppliers do not warrant or guarantee that these
# samples are accurate and suitable for your purposes. Their inclusion is
# purely for information purposes only.
IMPORT os
IMPORT util
IMPORT FGL MsgBox
DEFINE charset STRING
DEFINE boundary STRING
DEFINE rv INTEGER
DEFINE smtplog base.StringBuffer
DEFINE logtext STRING
DEFINE tz STRING
DEFINE ext2mime DYNAMIC ARRAY OF RECORD
ext STRING,
mime STRING,
encoding STRING
END RECORD
&define EXT2MIME(a, b, c) \
LET ext2mime[nmime].ext = a \
LET ext2mime[nmime].mime = b \
LET ext2mime[nmime].encoding = c \
LET nmime = nmime + 1
TYPE cnf_t RECORD
hostname STRING,
smtphost STRING,
smtpport INTEGER,
senderemail STRING,
cnxtimeout INTEGER
END RECORD
DEFINE cnf cnf_t
MAIN
DEFINE subject STRING
DEFINE recipients DYNAMIC ARRAY OF RECORD mode STRING, recipient STRING END RECORD
DEFINE mailtext STRING
DEFINE mailbody DYNAMIC ARRAY OF STRING
DEFINE attachments DYNAMIC ARRAY OF RECORD fname, sname STRING END RECORD
DEFINE rcpt DYNAMIC ARRAY OF STRING
DEFINE nmime INTEGER
DEFINE filename STRING
OPTIONS INPUT WRAP
# TZ checks
IF NUM_ARGS() == 1 THEN
IF ARG_VAL(1) == "TZGMT" THEN
CALL fgl_setenv("TZ", "GMT")
CALL showTZ()
END IF
IF ARG_VAL(1) == "TZLOCAL" THEN
CALL showTZ()
END IF
IF ARG_VAL(1) == "DTSHOW" THEN
DISPLAY CURRENT YEAR TO MINUTE
END IF
EXIT PROGRAM 0
END IF
OPEN FORM maildemo FROM "Mailer"
DISPLAY FORM maildemo
LET charset = getCharset()
# Mime types initialization - should be left configurable by the client
LET nmime = 1
EXT2MIME("bin", "application/octet-stream", "base64")
EXT2MIME("pdf", "application/x-pdf", "base64")
EXT2MIME("gz", "application/x-gzip", "base64")
EXT2MIME("tgz", "application/x-compressed-tar", "base64")
EXT2MIME("gif", "image/gif", "base64")
EXT2MIME("jpg", "image/jpg", "base64")
EXT2MIME("png", "image/png", "base64")
EXT2MIME("txt", "text/plain", "7bit")
EXT2MIME("per", "text/plain", "7bit")
EXT2MIME("4gl", "text/plain", "7bit")
EXT2MIME("42m", "application/octet-stream", "base64")
CALL load_maildemo_cnf()
LET tz = detect_timezone()
LET boundary='--------------' || util.Math.rand(1000) || util.Math.rand(1000) || util.Math.rand(1000) || util.Math.rand(1000)
# Mail composition dialog
DIALOG ATTRIBUTE(UNBUFFERED)
INPUT BY NAME cnf.* ATTRIBUTES(WITHOUT DEFAULTS)
END INPUT
INPUT ARRAY recipients FROM srrecipients.* ATTRIBUTES(WITHOUT DEFAULTS)
BEFORE INSERT
LET recipients[dialog.getCurrentRow("srrecipients")].mode = "To"
AFTER ROW
IF LENGTH(recipients[dialog.getCurrentRow("srrecipients")].recipient) == 0 THEN
CALL recipients.deleteElement(dialog.getCurrentRow("srrecipients"))
END IF
END INPUT
INPUT BY NAME subject, mailtext
END INPUT
DISPLAY ARRAY attachments TO srattachments.*
END DISPLAY
INPUT BY NAME logtext
END INPUT
BEFORE DIALOG
IF LENGTH(cnf.hostname) == 0 OR LENGTH(cnf.smtpHost) == 0 OR LENGTH(cnf.senderEmail) == 0 THEN
NEXT FIELD hostname
END IF
NEXT FIELD recipient
ON ACTION attachfile
CALL ui.Interface.frontCall("standard", "openfile", ["C:\\", "*", "", "Attach file"], [filename])
IF filename IS NOT NULL THEN
LET attachments[attachments.getLength()+1].fname = filename
LET attachments[attachments.getLength()].sname = "attachment" || (attachments.getLength() USING "<<<<<<<")
END IF
ON ACTION delattachment
CALL attachments.deleteElement(dialog.getCurrentRow("srattachments"))
ON ACTION viewattachment
CALL mbox_ok("View attachment", "View : " || attachments[dialog.getCurrentRow("srattachments")].sname, "information")
ON ACTION close
EXIT DIALOG
ON ACTION send
IF INFIELD(recipient) THEN
# We are currently editing the recipient column
IF LENGTH(recipients[dialog.getCurrentRow("srrecipients")].recipient) == 0 THEN
# Empty, remove it
# AFTER FIELD has not been executed, do it here
CALL recipients.deleteElement(dialog.getCurrentRow("srrecipients"))
END IF
END IF
IF recipients.getLength() == 0 THEN
CALL mbox_ok("Error", "The recipient list is empty.", "stop")
CONTINUE DIALOG
END IF
IF LENGTH(subject) == 0 THEN
# Note: click on the X button returns NULL or "", I would expect the default specified, i.e. "No" here.
IF NOT mbox_yn("Warning", "The subject line is empty.\nDo you really want to send this mail ?", "exclamation") THEN
NEXT FIELD subject
END IF
END IF
IF NOT retrieve_attachments(attachments) THEN
CONTINUE DIALOG
END IF
CALL genmail(cnf.senderemail, recipients, subject, mailtext, attachments, mailbody, rcpt)
IF sendmail(rcpt, mailbody) THEN
CALL clear_attachments(attachments)
CALL mbox_ok("Send mail", "Mail successfully sent.", "information")
CALL rcpt.clear()
CALL recipients.clear()
CALL attachments.clear()
CALL mailbody.clear()
LET subject = ""
LET mailtext = ""
NEXT FIELD recipient
END IF
CALL clear_attachments(attachments)
ON ACTION savecnf
CALL save_maildemo_cnf()
ON ACTION chkcnf
CALL check_maildemo_cnf()
END DIALOG
END MAIN
# Retrieve the current charset
FUNCTION getCharset()
DEFINE l STRING
DEFINE c base.Channel
LET c = base.Channel.create()
CALL c.openPipe("fglrun -i mbcs 2>&1", "r")
LET l = c.readLine()
WHILE l IS NOT NULL
IF l MATCHES "Charmap : *" THEN
RETURN l.subString(16,length(l))
EXIT WHILE
END IF
LET l = c.readLine()
END WHILE
END FUNCTION
&define MB(array, idx, line) \
LET array[idx] = line \
LET idx = idx + 1
# Generate the mail content
FUNCTION genmail(senderemail, recipients, subject, mailtext, attachments, mailbody, rcpt)
DEFINE senderemail STRING
DEFINE subject STRING
DEFINE recipients DYNAMIC ARRAY OF RECORD mode STRING, recipient STRING END RECORD
DEFINE mailtext STRING
DEFINE sbmt base.StringBuffer
DEFINE i, found INTEGER
DEFINE rcpt DYNAMIC ARRAY OF STRING
DEFINE attachments DYNAMIC ARRAY OF RECORD fname, sname STRING END RECORD
DEFINE nl INTEGER
DEFINE nrcpt INTEGER
DEFINE nr INTEGER
DEFINE extension STRING
DEFINE mimeid INTEGER
DEFINE mailbody DYNAMIC ARRAY OF STRING
LET nl = 1
LET nr = 1
LET nrcpt = 0
# Add mail date
MB(mailbody, nl, SFMT("Date: %1 %2 %3\r", TODAY USING "ddd, dd mmm yyyy", TIME(CURRENT), tz))
# First add headers
MB(mailbody, nl, SFMT("From: %1\r", senderemail))
# Add user agent
MB(mailbody, nl, "User-Agent: maildemo sample program.\r")
# Add MIME version
MB(mailbody, nl, "MIME-Version: 1.0\r")
# Add To: recipients
LET found = 0
FOR i = 1 TO recipients.getLength()
IF recipients[i].mode == "To" THEN
IF found THEN
LET mailbody[nl] = mailbody[nl].append(SFMT(", %1", recipients[i].recipient))
ELSE
LET mailbody[nl]=SFMT("To: %1", recipients[i].recipient)
LET found = 1
END IF
MB(rcpt, nr, SFMT("RCPT TO: %1", extract_email(recipients[i].recipient)))
END IF
END FOR
IF found == 1 THEN
LET mailbody[nl] = mailbody[nl].append("\r")
LET nl = nl + 1
END IF
# Add CC: recipients
LET found = 0
FOR i = 1 TO recipients.getLength()
IF recipients[i].mode == "CC" THEN
IF found THEN
LET mailbody[nl] = mailbody[nl].append(SFMT(", %1", recipients[i].recipient))
ELSE
LET mailbody[nl]=SFMT("CC: %1", recipients[i].recipient)
LET found = 1
END IF
MB(rcpt, nr, SFMT("RCPT TO: %1", extract_email(recipients[i].recipient)))
END IF
END FOR
IF found == 1 THEN
LET mailbody[nl] = mailbody[nl].append("\r")
LET nl = nl + 1
END IF
# Add CC: recipients
LET found = 0
FOR i = 1 TO recipients.getLength()
IF recipients[i].mode == "BCC" THEN
IF found THEN
LET mailbody[nl] = mailbody[nl].append(SFMT(", %1", recipients[i].recipient))
ELSE
LET mailbody[nl]=SFMT("BCC: %1", recipients[i].recipient)
LET found = 1
END IF
MB(rcpt, nr, SFMT("RCPT TO: %1", extract_email(recipients[i].recipient)))
END IF
END FOR
IF found == 1 THEN
LET mailbody[nl] = mailbody[nl].append("\r")
LET nl = nl + 1
END IF
MB(mailbody, nl, SFMT("Subject: %1\r", subject))
# Now add the message content
# Multipart message not handled
# Should check the body is really 7bit and not line starts with ., ...
# To be conformant with 7bit encoding. See RFC for details.
# \n.\n is the DATA section end mark.
# Should be replaced by \n..\n
LET sbmt = base.StringBuffer.create()
CALL sbmt.append(mailtext)
# Need to do it twice to properly handle following case: \n.\n.\n.\n.\n.\n
CALL sbmt.replace("\n.\n", "\n..\n", 0)
CALL sbmt.replace("\n.\n", "\n..\n", 0)
LET mailtext=sbmt.toString()
IF attachments.getLength() == 0 THEN
MB(mailbody, nl, SFMT("Content-Type: text/plain; charset=%1\r", "ISO-8859-1"))
MB(mailbody, nl, SFMT("Content-Transfer-Encoding: %1\r", "7bit"))
MB(mailbody, nl, "\r")
MB(mailbody, nl, mailtext)
MB(mailbody, nl, "\r")
ELSE
MB(mailbody, nl, "Content-Type: multipart/mixed;\r")
MB(mailbody, nl, ' boundary="' || boundary || '"\r')
MB(mailbody, nl, "\r")
MB(mailbody, nl, "This is a multi-part message in MIME format.\r")
# Add message text
MB(mailbody, nl, "--" || boundary || "\r")
MB(mailbody, nl, SFMT("Content-Type: text/plain; charset=%1; format=flowed\r", "ISO-8859-1"))
MB(mailbody, nl, SFMT("Content-Transfer-Encoding: %1\r", "7bit"))
MB(mailbody, nl, "\r")
MB(mailbody, nl, mailtext)
MB(mailbody, nl, '\r')
FOR i = 1 TO attachments.getLength()
MB(mailbody, nl, "--" || boundary || "\r")
LET extension = os.Path.extension(attachments[i].fname)
LET mimeid = getmime(extension)
IF mimeid == -1 THEN
# Unknown extension.
# Default to application/octet-stream, base64 encoded
LET mimeid = 1
END IF
CASE ext2mime[mimeid].encoding
WHEN "base64"
MB(mailbody, nl, SFMT("Content-Type: %1;\r", ext2mime[mimeid].mime))
MB(mailbody, nl, ' name="'|| attachments[i].fname || '"\r')
MB(mailbody, nl, 'Content-Transfer-Encoding: base64\r')
MB(mailbody, nl, 'Content-Disposition: inline;\r')
MB(mailbody, nl, ' filename="'|| os.Path.basename(attachments[i].fname) || '"\r')
MB(mailbody, nl, '\r')
LET nl = file_to_base64(attachments[i].sname, mailbody, nl)
WHEN "7bit"
MB(mailbody, nl, SFMT("Content-Type: %1;\r", ext2mime[mimeid].mime))
MB(mailbody, nl, ' name="'|| attachments[i].fname || '"\r')
MB(mailbody, nl, 'Content-Transfer-Encoding: 7bit\r')
MB(mailbody, nl, 'Content-Disposition: inline;\r')
MB(mailbody, nl, ' filename="'|| os.Path.basename(attachments[i].fname) || '"\r')
MB(mailbody, nl, '\r')
LET nl = file_to_7bit(attachments[i].sname, mailbody, nl)
OTHERWISE
CALL mbox_ok("Attachment encoding", SFMT("Unsupported encoding %1.", ext2mime[mimeid].encoding), "stop")
EXIT PROGRAM 1
END CASE
END FOR
MB(mailbody, nl, "--" || boundary || "--\r")
END IF
# Add end of message marker
MB(mailbody, nl, ".\r")
END FUNCTION
FUNCTION smtpSend(ch, command)
DEFINE ch base.Channel
DEFINE command STRING
DEFINE smtpStatus INTEGER
DEFINE smtpMessage STRING
CALL clientWrite(ch, command)
CALL readSmtpAnswer(ch) RETURNING smtpStatus, smtpMessage
RETURN smtpStatus, smtpMessage
END FUNCTION
FUNCTION readSmtpAnswer(ch)
DEFINE ch base.Channel
DEFINE line STRING
DEFINE smtpStatus INTEGER
DEFINE smtpMessage STRING
LET smtpMessage = ""
WHILE 1
LET line = serverRead(ch)
IF line IS NULL THEN
RETURN -1, "COULD NOT READ SMTP ANSWER"
END IF
IF line MATCHES "[0-9][0-9][0-9] *" THEN
IF smtpMessage.getLength() != 0 THEN
LET smtpMessage=smtpMessage || "\n"
END IF
LET smtpMessage=smtpMessage.append(line.subString(4, line.getLength()))
LET smtpStatus = line.subString(1,3)
RETURN smtpStatus, smtpMessage
END IF
IF line MATCHES "[0-9][0-9][0-9]-*" THEN
IF smtpMessage.getLength() != 0 THEN
LET smtpMessage=smtpMessage || "\n"
END IF
LET smtpMessage=smtpMessage.append(line.subString(4, line.getLength()))
END IF
END WHILE
END FUNCTION
FUNCTION sendmail(rcpt, mailbody)
DEFINE mailbody DYNAMIC ARRAY OF STRING
DEFINE rcpt DYNAMIC ARRAY OF STRING
DEFINE smtpStatus INTEGER
DEFINE smtpMessage STRING
DEFINE mc base.Channel
DEFINE i INTEGER
LET smtplog = base.StringBuffer.create()
LET mc = base.Channel.create()
TRY
CALL mc.openClientSocket(cnf.smtphost, cnf.smtpport, "ub", cnf.cnxtimeout)
CATCH
CALL mbox_ok("Socket error", "The connection to the SMTP Server failed.\n", "stop")
RETURN FALSE
END TRY
CALL readSmtpAnswer(mc) RETURNING smtpStatus, smtpMessage
CALL smtpSend(mc, "HELO " || cnf.hostname || "\r") RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
CALL smtpSend(mc, SFMT("MAIL FROM: %1\r", extract_email(cnf.senderemail))) RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
FOR i = 1 TO rcpt.getLength()
CALL smtpSend(mc, rcpt[i]) RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
END FOR
CALL smtpSend(mc, "DATA\r") RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
FOR i = 1 TO mailbody.getLength()
CALL clientWrite(mc, mailbody[i])
END FOR
CALL readSmtpAnswer(mc) RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
CALL smtpSend(mc, "QUIT\r") RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN FALSE
END IF
CALL mc.close()
RETURN TRUE
END FUNCTION
FUNCTION clientWrite(mc, line)
DEFINE mc base.Channel
DEFINE line STRING
CALL smtplog.append('<FONT COLOR="#339933"><B>C&gt; </B>')
CALL smtplog.append(line)
CALL smtplog.append("<BR></FONT>")
LET logtext=smtplog.toString()
CALL mc.writeLine(line)
END FUNCTION
FUNCTION serverRead(mc)
DEFINE line STRING
DEFINE mc base.Channel
LET line = mc.readLine()
CALL smtplog.append("<FONT COLOR=red><B>S&gt; </B>")
CALL smtplog.append(line)
CALL smtplog.append("<BR></FONT>")
LET logtext=smtplog.toString()
RETURN line
END FUNCTION
# Returns the mime entry index for the extension `ext'
# -1 if not entry matching the extension is found.
FUNCTION getmime(ext)
DEFINE ext STRING
DEFINE j INTEGER
FOR j = 1 TO ext2mime.getLength()
IF ext2mime[j].ext == ext THEN
RETURN j
END IF
END FOR
RETURN -1
END FUNCTION
# Save configuration
FUNCTION save_maildemo_cnf()
DEFINE pch base.Channel
DEFINE path STRING
LET path = os.Path.join(os.Path.homedir(), "maildemo.cnf")
IF os.Path.exists(path) THEN
IF NOT os.Path.writable(path) THEN
CALL mbox_ok("Write configuration", SFMT("The file %1 can not be written", path), "stop")
RETURN
END IF
END IF
TRY
LET pch=base.channel.create()
CALL pch.openFile(path, "w")
CALL pch.write([cnf.*])
CALL pch.close()
CATCH
CALL mbox_ok("Write configuration", SFMT("Failed to save the configuration in the file %1", path), "stop")
RETURN
END TRY
CALL mbox_ok("Save configuration", SFMT("The configuration was successfully saved in %1.", path), "information")
END FUNCTION
# Load configuration
FUNCTION load_maildemo_cnf()
DEFINE pch base.Channel
DEFINE path STRING
LET path = os.Path.join(os.Path.homedir(), "maildemo.cnf")
IF NOT os.Path.exists(path) THEN
CALL default_maildemo_cnf()
RETURN
END IF
IF NOT os.Path.readable(path) THEN
CALL default_maildemo_cnf()
RETURN
END IF
# Read save parameters
LET pch = base.channel.create()
CALL pch.openFile(path,"r")
LET rv = pch.read([cnf.*])
CALL pch.close()
IF rv THEN
RETURN
END IF
CALL default_maildemo_cnf()
END FUNCTION
FUNCTION default_maildemo_cnf()
LET cnf.smtpPort = 25
LET cnf.smtpHost = ""
LET cnf.senderEmail = ""
LET cnf.hostname = ""
LET cnf.cnxtimeout = 10
END FUNCTION
FUNCTION file_to_base64(fname, mailbody, nl)
DEFINE mailbody DYNAMIC ARRAY OF STRING
DEFINE fname STRING
DEFINE nl INTEGER
DEFINE l BYTE
DEFINE lfn STRING
DEFINE doc om.DomDocument
DEFINE node om.DomNode
DEFINE lnode om.NodeList
LET lfn = fname || ".xml"
LOCATE l IN FILE fname
CALL fgl_report_set_document_handler(om.XmlWriter.createFileWriter(lfn))
START REPORT gen_base64 TO FILE "dummy_report_file"
OUTPUT TO REPORT gen_base64(l)
FINISH REPORT gen_base64
# Load the generated XML file
LET doc = om.DomDocument.createFromXmlFile(lfn)
LET node = doc.getDocumentElement()
LET lnode = node.selectByTagName("Item")
LET node = lnode.item(1)
MB(mailbody, nl, node.getAttribute("value"))
IF NOT os.Path.delete(lfn) THEN
CALL mbox_ok("Warning", SFMT("The temporary file %1 could not be removed.", lfn), "stop")
END IF
RETURN nl
END FUNCTION
# Convert a file to a base64 string
REPORT gen_base64(l)
DEFINE l BYTE
OUTPUT
PAGE LENGTH 1
TOP MARGIN 0
BOTTOM MARGIN 0
LEFT MARGIN 0
FORMAT
ON EVERY ROW
PRINTX name=base64_l l
END REPORT
# Convert a file to 7bit encoding (fake)
FUNCTION file_to_7bit(fname, mailbody, nl)
DEFINE fname STRING
DEFINE mailbody DYNAMIC ARRAY OF STRING
DEFINE ac base.Channel
DEFINE line STRING
DEFINE nl INTEGER
LET ac = base.Channel.create()
CALL ac.openFile(fname, "rb")
WHILE NOT ac.isEof()
LET line = ac.readLine()
MB(mailbody, nl, line)
END WHILE
CALL ac.close()
RETURN nl
END FUNCTION
FUNCTION check_maildemo_cnf()
DEFINE smtpStatus INTEGER
DEFINE smtpMessage STRING
DEFINE mc base.Channel
LET smtplog = base.StringBuffer.create()
LET mc = base.Channel.create()
TRY
CALL mc.openClientSocket(cnf.smtphost, cnf.smtpport, "ub", cnf.cnxtimeout)
CATCH
CALL mbox_ok("Socket error", "The connection to the SMTP Server failed.\n", "stop")
RETURN
END TRY
CALL readSmtpAnswer(mc) RETURNING smtpStatus, smtpMessage
CALL smtpSend(mc, "HELO " || cnf.hostname || "\r") RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN
END IF
CALL smtpSend(mc, "QUIT\r") RETURNING smtpStatus, smtpMessage
IF smtpStatus >= 400 THEN
CALL smtpError(mc, smtpMessage)
RETURN
END IF
CALL mc.close()
CALL mbox_ok("SMTP Connection", "The SMTP parameters are correct", "information")
RETURN
END FUNCTION
FUNCTION smtpError(mc, msg)
DEFINE msg STRING
DEFINE mc base.Channel
DEFINE smtpStatus INTEGER
DEFINE smtpMessage STRING
CALL mbox_ok("SMTP Error", msg, "stop")
CALL smtpSend(mc, "QUIT\r") RETURNING smtpStatus, smtpMessage
CALL mc.close()
END FUNCTION
FUNCTION getProgramCmd()
DEFINE cmd STRING
LET cmd = os.Path.join(fgl_getenv("FGLDIR"), "demo")
LET cmd = os.Path.join(cmd, "MultipleDialogs")
LET cmd = os.Path.join(cmd, "Mailer.42m")
IF NOT os.Path.exists(cmd) THEN
LET cmd = os.Path.join(".", "Mailer.42m")
IF NOT os.Path.exists(cmd) THEN
DISPLAY "ERROR: Could not find Mailer.42m program file."
EXIT PROGRAM 1
END IF
END IF
IF fgl_getenv("WINDIR") THEN
LET cmd = "\"" || cmd || "\""
END IF
LET cmd = SFMT("fglrun %1 ", cmd)
RETURN cmd
END FUNCTION
FUNCTION showTZ()
CALL FGL_SETENV("FGLGUI","0")
RUN getProgramCmd() || "DTSHOW"
CALL FGL_SETENV("FGLGUI","1")
END FUNCTION
FUNCTION detect_timezone()
DEFINE ch base.Channel
DEFINE dnow, dgmt DATETIME YEAR TO MINUTE
DEFINE dh INTERVAL MINUTE(5) TO MINUTE
DEFINE sminutes STRING
DEFINE iminutes INTEGER
DEFINE ihours INTEGER
CALL FGL_SETENV("FGLGUI","0")
LET ch = base.Channel.create()
CALL ch.openPipe(getProgramCmd()||" TZLOCAL", "r")
LET rv=ch.read(dnow)
CALL ch.close()
CALL ch.openPipe(getProgramCmd()||" TZGMT", "r")
LET rv=ch.read(dgmt)
CALL ch.close()
LET dh = dnow - dgmt
LET sminutes = dh
LET iminutes = sminutes
IF iminutes MOD 2 == 1 THEN
LET iminutes = iminutes + 1
END IF
LET ihours = iminutes / 60
LET iminutes = iminutes - ihours * 60
CALL FGL_SETENV("FGLGUI","1")
RETURN SFMT("%1%2", ihours USING "+&&", iminutes USING "&&")
END FUNCTION
{
Retrieves attachments from the client.
If many attachments should be retrieved, maybe a progress bar could be displayed
}
FUNCTION retrieve_attachments(attachments)
DEFINE attachments DYNAMIC ARRAY OF RECORD fname, sname STRING END RECORD
DEFINE i, j INTEGER
FOR i = 1 TO attachments.getLength()
DISPLAY "Retrieving attachment : ", attachments[i].fname, " TO ", attachments[i].sname
TRY
CALL fgl_getfile(attachments[i].fname, attachments[i].sname)
CATCH
CALL mbox_ok("Attachment download", SFMT("Could not retrieve attachment %1", attachments[i].fname), "stop")
FOR j = 1 TO i
LET rv = os.Path.delete(attachments[j].sname)
END FOR
RETURN FALSE
END TRY
END FOR
RETURN TRUE
END FUNCTION
# Deletes temporary attachment files
FUNCTION clear_attachments(attachments)
DEFINE attachments DYNAMIC ARRAY OF RECORD fname, sname STRING END RECORD
DEFINE i INTEGER
FOR i = 1 TO attachments.getLength()
LET rv = os.Path.delete(attachments[i].sname)
END FOR
END FUNCTION
FUNCTION extract_email(email)
DEFINE email STRING
DEFINE s, e INTEGER
LET s = email.getIndexOf("<", 1)
LET e = email.getIndexOf(">", 1)
IF s == 0 OR e == 0 OR s >= e THEN
RETURN email
END IF
RETURN email.subString(s + 1, e - 1)
END FUNCTION