Commit inicial: fuentes MBS ERP (Genero 6) + .gitignore + docs/SETUP_PC_MBS.md
This commit is contained in:
@@ -0,0 +1,762 @@
|
||||
# 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> </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> </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
|
||||
Reference in New Issue
Block a user