767 lines
25 KiB
Plaintext
767 lines
25 KiB
Plaintext
IMPORT os
|
|
IMPORT util
|
|
|
|
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
|
|
|
|
|
|
TYPE cnf_t RECORD
|
|
hostname STRING,
|
|
smtphost STRING,
|
|
smtpport INTEGER,
|
|
senderemail STRING,
|
|
clave STRING,
|
|
cnxtimeout INTEGER
|
|
END RECORD
|
|
DEFINE cnf cnf_t
|
|
|
|
FUNCTION mailer()
|
|
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,
|
|
hostname STRING,
|
|
smtphost STRING,
|
|
smtpport INTEGER,
|
|
senderemail STRING,
|
|
clave STRING,
|
|
cnxtimeout INTEGER
|
|
|
|
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
|
|
|
|
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 FUNCTION
|
|
|
|
# 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, "STARTTLS \r") RETURNING smtpStatus, smtpMessage
|
|
IF smtpStatus >= 400 THEN
|
|
CALL smtpError(mc, smtpMessage)
|
|
RETURN FALSE
|
|
END IF
|
|
|
|
CALL smtpSend(mc, cnf.senderemail CLIPPED ||" "|| cnf.clave CLIPPED) 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
|
|
DISPLAY "llegue aqui "
|
|
|
|
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, "STARTTLS \r") RETURNING smtpStatus, smtpMessage
|
|
IF smtpStatus >= 400 THEN
|
|
CALL smtpError(mc, smtpMessage)
|
|
RETURN
|
|
END IF
|
|
CALL smtpSend(mc, cnf.senderemail CLIPPED || " "||cnf.clave CLIPPED) 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 showTZ()
|
|
DEFINE mailer42m STRING
|
|
|
|
LET mailer42m = os.Path.join(fgl_getenv("FGLDIR"), "demo")
|
|
LET mailer42m = os.Path.join(mailer42m, "MultipleDialogs")
|
|
LET mailer42m = os.Path.join(mailer42m, "Mailer.42m")
|
|
RUN SFMT("fglrun %1 DTSHOW", mailer42m)
|
|
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
|
|
DEFINE mailer42m STRING
|
|
|
|
LET mailer42m = os.Path.join(fgl_getenv("FGLDIR"), "demo")
|
|
LET mailer42m = os.Path.join(mailer42m, "MultipleDialogs")
|
|
LET mailer42m = os.Path.join(mailer42m, "Mailer.42m")
|
|
IF NOT os.Path.exists(mailer42m) THEN
|
|
RETURN ""
|
|
END IF
|
|
|
|
LET ch = base.Channel.create()
|
|
CALL ch.openPipe(SFMT("fglrun %1 TZLOCAL", mailer42m), "r")
|
|
LET rv=ch.read(dnow)
|
|
CALL ch.close()
|
|
|
|
CALL ch.openPipe(SFMT("fglrun %1 TZGMT", mailer42m), "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
|
|
|
|
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
|