-- email_factura.4gl IMPORT os IMPORT JAVA java.lang.System IMPORT JAVA java.io.ByteArrayOutputStream IMPORT JAVA java.io.PrintStream IMPORT JAVA java.util.Properties IMPORT JAVA javax.mail.Session IMPORT JAVA javax.mail.Message IMPORT JAVA javax.mail.Transport IMPORT JAVA javax.mail.internet.InternetAddress IMPORT JAVA javax.mail.internet.MimeMessage IMPORT JAVA javax.mail.internet.MimeMultipart IMPORT JAVA javax.mail.internet.MimeBodyPart IMPORT JAVA com.sun.mail.smtp.SMTPTransport IMPORT security CONSTANT debug_level = 1 DEFINE logtext STRING DEFINE out_stream ByteArrayOutputStream DEFINE xpassword STRING TYPE cnf_t RECORD hostname STRING, smtphost STRING, smtpport INTEGER, senderemail STRING, smtpauth SMALLINT, username STRING, password STRING, use_ssl SMALLINT, use_tls SMALLINT, cnxtimeout INTEGER END RECORD DEFINE cnf cnf_t FUNCTION enviaFilesCliente(rncempresa,ptipo_cliente,psec_cliente,rnc,ncf,porden,pconduce,pbodega) DEFINE email, cuerpo_correo, xusername, xsmtphost, xsmtpport, xpassword STRING DEFINE subject, attachment, nombre_cliente STRING DEFINE filefirmado, ruta_firmados,ncf STRING, ptipo_cliente,psec_cliente,i,porden,pconduce,pbodega INT, rnc,rncempresa VARCHAR(11), verdad BOOLEAN, rutas DYNAMIC ARRAY OF STRING DEFINE attachments DYNAMIC ARRAY OF STRING DEFINE ruta_doc, nombre_doc,selec,temp_dir STRING DEFINE bin_doc BYTE DEFINE temp_file STRING LET email = NULL LET nombre_cliente = NULL SELECT a.patente,a.nombre INTO email,nombre_cliente FROM vetb00004 a WHERE a.tipo_cliente = ptipo_cliente AND a.sec_cliente = psec_cliente IF email IS NULL OR email = "" THEN LET email = "apereyra@marmotech.com.do" ELSE LET email = email CLIPPED,",apereyra@marmotech.com.do" END IF IF nombre_cliente IS NULL OR nombre_cliente = "" THEN LET nombre_cliente = "Cliente" END IF DISPLAY BY NAME email LET temp_dir = "E:\\MARMOTECH\\temp\\" LET i = 1 -- 1. XML siempre primero LET rutas[1] = "E:\\MARMOTECH\\BIN320\\filesxml\\firmados\\" LET rutas[2] = "E:\\MARMOTECHC\\BIN320\\filesxml\\firmados\\" FOR i = 1 TO rutas.getLength() LET filefirmado = rutas[i] CLIPPED, rncempresa CLIPPED, ncf CLIPPED, ".xml" IF os.Path.exists(filefirmado) THEN LET attachments[i] = filefirmado EXIT FOR END IF END FOR LET selec = "SELECT a.nombre_file, a.documento FROM marmotech.dbo.prtb00029 a WHERE a.num_oc =? AND a.num_doc = ? AND a.bodega = ? AND a.tipo_file = 'CO' " PREPARE comando FROM selec DECLARE c_docs CURSOR FOR comando OPEN c_docs USING porden,pconduce,pbodega LET i = attachments.getLength() + 1 LOCATE bin_Doc IN MEMORY FETCH c_docs INTO nombre_doc, bin_doc WHILE STATUS = 0 IF nombre_doc IS NULL OR nombre_doc = "" THEN LET nombre_doc = SFMT("doc_%1.pdf", i) END IF LET temp_file = SFMT("%1%2", temp_dir, nombre_doc) CALL save_binary_to_file(temp_file, bin_doc) IF os.Path.exists(temp_file) THEN LET attachments[i] = temp_file LET i = i + 1 END IF FETCH c_docs INTO nombre_doc, bin_doc END WHILE CLOSE c_docs DISPLAY "Attachments:" FOR i = 1 TO attachments.getLength() DISPLAY attachments[i] END FOR LET subject = SFMT("XML Facturacion Electronica - NCF %1", ncf) LET xusername = "notificacion@marmotech.com.do" LET xsmtphost = "smtp.office365.com" LET xsmtpport = "587" LET xpassword = "Lmmjvsd2020" LET cuerpo_correo = build_html_factura(nombre_cliente, ncf, rnc) CALL enviaemail2( email, subject, cuerpo_correo, attachments, xusername, xsmtphost, xsmtpport, xpassword ) RETURNING verdad RETURN verdad END FUNCTION FUNCTION build_html_factura(nombre_cliente, ncf, rnc) DEFINE nombre_cliente, ncf, rnc STRING DEFINE html STRING LET html = "" || "" || "" || "" || "" || "" || "" || "
" || "
" || "
Factura Electronica
" || "
" || "Estimado(a) " || nombre_cliente CLIPPED || ",

" || "Adjunto encontrara el archivo XML firmado correspondiente a su comprobante electronico emitido por MARMOTECH, S. A..
" || "
" || "NCF: " || ncf CLIPPED || "
" || "RNC Emisor: " || rnc CLIPPED || "
" || "Documento adjunto: XML firmado" || "
" || "
Este mensaje fue generado automaticamente por el sistema MBS." || "
" || "" || "
" || "
" || "" || "" RETURN html END FUNCTION -- enviaemail.4gl FUNCTION enviaemail2(rcpt_to, subject, body, attachments, xusername, xsmtphost, xsmtpport, xpassword) DEFINE rcpt_to, subject, body, xusername, xsmtphost, xsmtpport, xpassword STRING DEFINE attachments DYNAMIC ARRAY OF STRING DEFINE msg MimeMessage DEFINE body_part MimeBodyPart DEFINE attach_part MimeBodyPart DEFINE multipart MimeMultipart DEFINE sesion Session DEFINE plain_password, s_proto STRING DEFINE trans Transport DEFINE i INT LET cnf.smtphost = xsmtphost LET cnf.smtpport = xsmtpport LET cnf.username = xusername LET cnf.password = xpassword LET cnf.senderemail = xusername LET cnf.smtpauth = TRUE LET cnf.use_ssl = FALSE LET cnf.use_tls = TRUE LET cnf.cnxtimeout = 30 CALL create_cxion_session() RETURNING sesion, plain_password, s_proto LET msg = MimeMessage.create(sesion) CALL msg.setFrom(InternetAddress.create(xusername)) CALL msg.setSubject(subject,"UTF-8") CALL msg.addHeader("To", rcpt_to) CALL msg.addHeader("MIME-Version", "1.0") LET body_part = MimeBodyPart.create() CALL body_part.setContent(body, "text/html; charset=UTF-8") LET attach_part = MimeBodyPart.create() LET multipart = MimeMultipart.create() CALL multipart.addBodyPart(body_part) -- ? FALTABA FOR i = 1 TO attachments.getLength() IF attachments[i] IS NOT NULL AND os.Path.exists(attachments[i]) THEN LET attach_part = MimeBodyPart.create() CALL attach_part.attachFile(attachments[i]) CALL multipart.addBodyPart(attach_part) END IF END FOR CALL msg.setContent(multipart) CALL msg.saveChanges() LET trans = sesion.getTransport(s_proto) CALL trans.connect(xsmtphost, xusername, plain_password) CALL trans.sendMessage( msg, InternetAddress.parse(rcpt_to) ) CALL trans.close() RETURN TRUE END FUNCTION PRIVATE FUNCTION create_cxion_session() DEFINE s_proto, s_password STRING DEFINE x_timeout INTEGER DEFINE sess Session DEFINE props Properties DEFINE custom_ps PrintStream CALL show_debug_msg(1, "Preparing connection parameters ...") CALL string_to_base64(cnf.password) RETURNING cnf.password LET s_password = base64_to_string(cnf.password) IF cnf.cnxtimeout > 0 THEN LET x_timeout = cnf.cnxtimeout * 1000 ELSE LET x_timeout = 0 END IF LET cnf.use_tls = TRUE LET cnf.use_ssl = FALSE IF cnf.use_ssl THEN LET s_proto = "smtps" ELSE LET s_proto = "smtp" END IF LET props = System.getProperties() IF cnf.use_ssl THEN CALL setMailProperties(props, "smtp", "ssl.enable", "true") ELSE CALL setMailProperties(props, "smtp", "ssl.enable", "false") END IF IF cnf.smtpauth THEN CALL setMailProperties(props, s_proto, "auth", "true") ELSE CALL setMailProperties(props, s_proto, "auth", "false") END IF CALL setMailProperties(props, s_proto, "host", cnf.smtphost) CALL setMailProperties(props, s_proto, "port", cnf.smtpport) CALL setMailProperties(props, s_proto, "connectiontimeout", x_timeout) CALL setMailProperties(props, s_proto, "timeout", x_timeout) CALL setMailProperties(props, s_proto, "writetimeout", x_timeout) IF cnf.use_tls THEN CALL setMailProperties(props, s_proto, "starttls.enable", "true") CALL setMailProperties(props, s_proto, "ssl.checkserveridentity", "false") CALL setMailProperties(props, s_proto, "ssl.trust", "*") ELSE CALL setMailProperties(props, s_proto, "starttls.enable", "false") END IF LET sess = Session.getInstance(props) LET out_stream = ByteArrayOutputStream.create() LET custom_ps = PrintStream.create(out_stream) CALL sess.setDebugOut(custom_ps) CALL sess.setDebug(TRUE) RETURN sess, s_password, s_proto END FUNCTION FUNCTION base64_to_string(str_b64) DEFINE str_out, str_b64, str_aux STRING TRY CALL security.Base64.ToString(str_b64) RETURNING str_out CATCH LET str_aux = "Unable to convert the Base64 string into plain-text: ", STATUS CALL mbox_ok("Error", str_aux, "stop") LET str_out = NULL END TRY RETURN str_out END FUNCTION FUNCTION string_to_base64(str_ent) DEFINE str_ent, str_b64, str_aux STRING TRY CALL security.Base64.FromString(str_ent) RETURNING str_b64 CATCH LET str_aux = "Unable to convert the input string into Base64: ", STATUS CALL mbox_ok("Error", str_aux, "stop") LET str_b64 = NULL END TRY RETURN str_b64 END FUNCTION PRIVATE FUNCTION setMailProperties(props, prot, prop, val) DEFINE props Properties DEFINE auxi, prot, prop, val STRING LET auxi = SFMT("mail.%1.%2", prot, prop) CALL props.put(auxi, val) CALL show_debug_msg(1, SFMT("Property '%1' set to value '%2'", auxi, val)) END FUNCTION PRIVATE FUNCTION show_debug_msg(lev, msg) DEFINE lev SMALLINT DEFINE msg STRING IF lev >= debug_level THEN DISPLAY msg END IF END FUNCTION FUNCTION mbox_ok(t, m, i) DEFINE t, m, i STRING MENU t ATTRIBUTES(STYLE="dialog", COMMENT=m, IMAGE=i) COMMAND "Ok" EXIT MENU END MENU END FUNCTION FUNCTION save_binary_to_file(path, data) DEFINE path STRING DEFINE data BYTE DEFINE ch base.Channel DEFINE size INTEGER DISPLAY "path: ", path LET ch = base.Channel.create() CALL ch.openFile(path, "wb") LET size = LENGTH(data) IF size > 0 THEN #CALL ch.write(data) CALL data.writeFile(path) ELSE DISPLAY "ERROR: binary vacío" END IF CALL ch.close() END FUNCTION