lunes, 3 de febrero de 2025

Enviar correo electrónico (Email) SMTP desde Visual FoxPro

 

Hola a tod@s, he estado fuera desde hace mucho tiempo, pero ya  estoy volviendo, reconstruyéndome desde mis cenizas cual Ave Fenix.

Hace unos días un cliente que está llevando el procedimiento de cambiar de facturación tradicional (osea en papel) a facturación electrónica, solicitó el envío de correos desde una app de Visual Fox, caso que ya he cubierto antes, pero en esta ocasión el requerimiento fue un poco más específico, por alguna razón el cliente no desea ningún archivo adjunto, más bien lo que necesita es que los datos estén embebidos dentro del cuerpo del Email, además debe salir de un correo institucional con parámetros específicos y debe poder incluir imágenes como logotipo y dar formato de tabla tipo HTML.

En resumidas cuentas debería el destinatario del correo electrónico recibir algo como la siguiente imagen:




Luego de plantear dichos requerimientos, me dí cuenta que hay 3 problemas por resolver, los que detallo a continuación:

a)      Hacer la recolección de datos y preparar un cursor con los mismos para luego ir a la segunda parte.

b)      Poder enviar un correo desde una cuenta institucional, ya que la mayoría de ejemplos en la red son de cuentas gratuitas tipo Gmail, Hotmail, etc.

c)       Dar formato tipo HTML.

Luego de buscar por la web encontré 2 soluciones que explicaré a continuación:

1)     1) Para envío desde correos que no fueran los clásicos Gmail, Hotmail, Yahoo, etc. Encontré una librería que me sirvió mucho y que se llama FoxyDB que puede encontrarse en https://foxydb.wordpress.com/csfoxysmtp-ejemplos/ del compañero Antonio Meza Pérez programador Mexicano y que en su blog escribe sobre su librería lo siguiente “es totalmente gratis (OpenSource) que les permitirá crear una Capa de acceso a Datos, con varios Servidores de Bases de Datos, en especial con MySql, MariaDB y FireBird, en un futuro con ayuda de alguien que use Sql Server y PostgreSql se pueden agregar, al igual que otros mas.”.

2)      Para abordar lo de usar código HTML para embeber los datos encontré una librería que muchos desconocen, Visual FoxPro desde hace ya varias versiones anteriores trae una herramienta para poder convertir tablas, formularios, informes, etiquetas y menús a formato HTML. La herramienta se llama GenHtml.prg y se encuentra en la carpeta donde está instalado VFP. La ruta y nombre de este programa está almacenado en la variable del sistema _GENHTML.

Comprobamos que la variable del sistema este correctamente configurada con:

? _GENHTML

Esta variable del sistema la podemos configurar desde el menú de VFP, en Herramientas, Opciones, en la solapa Archivos, y buscamos en la lista "Generador de HTML".

El programa GenHtml.prg

GenHtml.prg utiliza la librería de clases visuales _Html.vcx que son parte de las FoxPro Foundation Classes (FFC) que vienen con Visual FoxPro y se encuentran en la carpeta \ffc\ del directorio de instalación de VFP.

El compañero Luis María Guayán, de origen español nos cuenta en una entrada que tuvo la necesidad de crear una clase más elemental y sencilla, que solo convierte tablas y cursores a formato HTML. Aquí (https://comunidadvfp.blogspot.com/2005/10/convertir-tablas-formato-html.html) la exponge para que ustedes la utilicen en sus aplicaciones y quizás necesiten modificarla para agregarle más datos al archivo HTML o para cambiar la apariencia de visualización.

Utilizando Foxydb.

El problema de la recolección de datos dependerá de lo que cada quién desee poner en sus correos y dado que no es el tema central lo dejaré como descontado asumiendo que si lees esto eres programador y sabrás como lidiar con ello, entonces el segundo problema es como configurar la librería, lo primero que hice fue ponerme en contacto con el proveedor de correos quienes me dieron la siguiente información, pero que asumiremos que tienen un dominio llamado “repuestosparamotocicletas.com”, es claro que los datos a continuación son ficticios.

Correo saliente tipo :SMTP

   mail.repuestosparamotocicletas.com

puerto de entrada : 645

sin seguridad SSL

cuenta de correo saliente : facturación@repuestosparamotocicletas.com

contraseña:   Tu_c0ntraseni@

 ** Creamos una variable para las pruebas llamada oSmtp, puede ser cualquier nombre.

Public oSmtp

** Creamos el objeto de la librería,** 32 Bit

oSmtp = CreateObject("CsFoxySmtp")

 

** 64 Bit

*oSmtp = CreateObject("CsFoxySmtp64")

 

** Configuramos las propiedades del Servidor para enviar correos desde una cuenta de correo.

 

oSmtp.server = " mail.repuestosparamotocicletas.com "

oSmtp.port = 645

oSmtp.ssl = .F.

oSmtp.user = "facturacion@repuestosparamotocicletas.com "

oSmtp.password = " Tu_c0ntraseni@"

** Configuramos los datos para el correo, la priority por default es normal, para el ejemplo la cambio a Alta.

oSmtp.from = "No responder < facturacion@repuestosparamotocicletas.com >"

oSmtp.subjet = "Informe de documentos no enviados al MH del día "+DTOC(DATE())

 

lcBody = TEXTMERGE(lcFile)

*!*   * Incrustar imágenes

oSmtp.body = lcBody

oSmtp.EmbedImage("imágenes\Logo.jpg", "imagen1")

oSmtp.priority = 1

** Agregamos las direcciones de correo, es decir los Destinatarios.

oSmtp.AddTo("logistica@tuempresa.com")

*oSmtp.AddTo(“correoDos@dominio.com”)

*oSmtp.AddTo(“correoTres@dominio.com”)

 

*** Agregamos las direcciones de los Destinatarios que irán en Copia

oSmtp.AddCc("asistenciaporoperadora@gmail.com")

oSmtp.AddCc("gerencia.general@lacruz-ada.com")

 

** Agregamos las direcciones de los Destinatarios que irán en Copia Oculta

*oSmtp.AddBcc(“correoOcultoUno@dominio.com”)

*oSmtp.AddBcc(“correoOcultoDos@dominio.com”)

 

** Agregamos los archivos Adjuntos al correo, dado que no quieren adjuntos se ** van como comentarios pero lo dejo por si te sirve

*oSmtp.AddAttachments(“c:\carpeta\archivoUno.pdf”)

*oSmtp.AddAttachments(“d:\foto\imagen.jpg”)

*oSmtp.AddAttachments(“c:\doc\listado.xls”)

 

** Finalmente enviamos el correo y validamos si se envió correctamente

IF oSmtp.Smtp() = .t.

      wait windows "Correo Enviado" NOWAIT

ELSE

      gError = .T.

      gMsg = oSmtp.Error

      RETURN -1

ENDIF

RETURN 1

Es claro que el TEXTMERGE debe ser creado previamente, esto es lo que yo tengo en mi código, la función AgregarListaResumen() se mostrará luego en esta entrada.

SET TEXTMERGE OFF

TEXT TO lcFile NOSHOW

<p><i> Informe automático <br>

<b> De Fecha: <<DTOC(DATE())>>, Generado a las <<TIME()>></b><br>

</i></p>

<hr>

<p>A continuación el listado de los Documentos de fecha <<ldFecha2>> no enviados al MH:</p>

<<AgregarListaResumen()>>

<p>La cantidad total de documentos es <b><<TotalRegistros()>></b>.</p>

<p>Sin más por el momento, atentamente</p>

<p><u><i>Factura Fácil</i></u></p>

       <body style="background-color: blank">

             <h2>Apuntando al éxito</h2>

             <img src='cid:imagen1' alt="no se muestra" width="250" height="150" align="left" />

             <br>

ENDTEXT

 

Y pues las otras funciones son :

PROCEDURE TotalRegistros()

 LOCAL lcHtml

 *-- Total de Ordenes por Empleado

 SELECT Dos

  COUNT to Tot_Regis

 lcHtml = TRANSFORM(Tot_Regis)

 RETURN lcHtml

 USE IN Dos

ENDPROC

 

PROCEDURE AgregarListaResumen()

 LOCAL lcHtml, loHtml

 *-- Listado de documentos no enviados a MH

 loHtml = CREATEOBJECT("ClaseHtml")

 lcHtml = loHtml.AgregarTabla('Dos') + CHR(13) + CHR(10)

 RELEASE loHtml

 RETURN lcHtml

ENDPROC

Y finalmente la clase “ClaseHtml” es la misma que te mencioné antes de Luis María Guayán.

Espero les sirva de ayuda u orientación por si tienen algún reto parecido, sin más por el momento me despido no sin antes enviar mi más sentido pésame a mi prima Laura Trejo por la irreparable pérdida de su madre, mi tía Laura Trejo, si se llaman igual.


Mr. Moon. 

La vida es un 10% como viene y un 90% como la tomamos.

Pensar es gratis.

jueves, 9 de febrero de 2023

La editorial Springer ha liberado cientos de libros (osea gratis)

 La editorial Springer ha liberado (osea gratis) 65 libros de Machine Learning

En realidad ha liberado cientos (408 para ser exactos) pero los que me importan son los de ciencia de datos y machine learning, ya saben es que estoy embebido con este tema.

The Elements of Statistical Learning
Trevor Hastie, Robert Tibshirani, Jerome Friedman
http://link.springer.com/openurl?genre=book&isbn=978-0-387-84858-7
Paul S.P. Cowpertwait, Andrew V. Metcalfe
A Beginner’s Guide to R
Introduction to Evolutionary Computing
Linear and Nonlinear Programming
David G. Luenberger, Yinyu Ye
http://link.springer.com/openurl?genre=book&isbn=978-3-319-18842-3

Introduction to Partial Differential Equations
David Borthwick
http://link.springer.com/openurl?genre=book&isbn=978-3-319-48936-0

Fundamentals of Robotic Mechanical Systems
Jorge Angeles
http://link.springer.com/openurl?genre=book&isbn=978-3-319-01851-5

Data Structures and Algorithms with Python
Kent D. Lee, Steve Hubbard
http://link.springer.com/openurl?genre=book&isbn=978-3-319-13072-9

Introduction to Partial Differential Equations
Peter J. Olver
http://link.springer.com/openurl?genre=book&isbn=978-3-319-02099-0

Methods of Mathematical Modelling
Thomas Witelski, Mark Bowen
http://link.springer.com/openurl?genre=book&isbn=978-3-319-23042-9

Introduction to Statistics and Data Analysis
Christian Heumann, Michael Schomaker, Shalabh
http://link.springer.com/openurl?genre=book&isbn=978-3-319-46162-5

Computational Geometry
Mark de Berg, Otfried Cheong, Marc van Kreveld, Mark Overmars
http://link.springer.com/openurl?genre=book&isbn=978-3-540-77974-2

Statistical Analysis and Data Display
Richard M. Heiberger, Burt Holland
http://link.springer.com/openurl?genre=book&isbn=978-1-4939-2122-5

Statistics and Data Analysis for Financial Engineering
David Ruppert, David S. Matteson
http://link.springer.com/openurl?genre=book&isbn=978-1-4939-2614-5

Stochastic Processes and Calculus
Uwe Hassler
http://link.springer.com/openurl?genre=book&isbn=978-3-319-23428-1

Statistical Analysis of Clinical Data on a Pocket Calculator
Ton J. Cleophas, Aeilko H. Zwinderman
http://link.springer.com/openurl?genre=book&isbn=978-94-007-1211-9

Clinical Data Analysis on a Pocket Calculator
Ton J. Cleophas, Aeilko H. Zwinderman
http://link.springer.com/openurl?genre=book&isbn=978-3-319-27104-0

The Data Science Design Manual
Steven S. Skiena
http://link.springer.com/openurl?genre=book&isbn=978-3-319-55444-0

An Introduction to Machine Learning
Miroslav Kubat
http://link.springer.com/openurl?genre=book&isbn=978-3-319-63913-0

Guide to Discrete Mathematics
Gerard O’Regan
http://link.springer.com/openurl?genre=book&isbn=978-3-319-44561-8

Introduction to Time Series and Forecasting
Peter J. Brockwell, Richard A. Davis
http://link.springer.com/openurl?genre=book&isbn=978-3-319-29854-2

Multivariate Calculus and Geometry
Seán Dineen
http://link.springer.com/openurl?genre=book&isbn=978-1-4471-6419-7

Statistics and Analysis of Scientific Data
Massimiliano Bonamente
http://link.springer.com/openurl?genre=book&isbn=978-1-4939-6572-4

Modelling Computing Systems
Faron Moller, Georg Struth
http://link.springer.com/openurl?genre=book&isbn=978-1-84800-322-4

Search Methodologies
Edmund K. Burke, Graham Kendall
http://link.springer.com/openurl?genre=book&isbn=978-1-4614-6940-7

Understanding Statistics Using R
Randall Schumacker, Sara Tomek
http://link.springer.com/openurl?genre=book&isbn=978-1-4614-6227-9

An Introduction to Statistical Learning
Gareth James, Daniela Witten, Trevor Hastie, Robert Tibshirani
http://link.springer.com/openurl?genre=book&isbn=978-1-4614-7138-7

Statistical Learning from a Regression Perspective
Richard A. Berk
http://link.springer.com/openurl?genre=book&isbn=978-3-319-44048-4

Applied Partial Differential Equations
J. David Logan
http://link.springer.com/openurl?genre=book&isbn=978-3-319-12493-3

Robotics
Bruno Siciliano, Lorenzo Sciavicco, Luigi Villani, Giuseppe Oriolo
http://link.springer.com/openurl?genre=book&isbn=978-1-84628-642-1

Regression Modeling Strategies
Frank E. Harrell , Jr.
http://link.springer.com/openurl?genre=book&isbn=978-3-319-19425-7

A Modern Introduction to Probability and Statistics
F.M. Dekking, C. Kraaikamp, H.P. Lopuhaä, L.E. Meester
http://link.springer.com/openurl?genre=book&isbn=978-1-84628-168-6

Machine Learning in Medicine — a Complete Overview
Ton J. Cleophas, Aeilko H. Zwinderman
http://link.springer.com/openurl?genre=book&isbn=978-3-319-15195-3

Object-Oriented Analysis, Design, and Implementation
Brahma Dathan, Sarnath Ramnath
http://link.springer.com/openurl?genre=book&isbn=978-3-319-24280-4

Introduction to Data Science
Laura Igual, Santi Seguí
http://link.springer.com/openurl?genre=book&isbn=978-3-319-50017-1

Applied Predictive Modeling
Max Kuhn, Kjell Johnson
http://link.springer.com/openurl?genre=book&isbn=978-1-4614-6849-3

Concise Guide to Databases
Peter Lake, Paul Crowther
http://link.springer.com/openurl?genre=book&isbn=978-1-4471-5601-7

Digital Image Processing
Wilhelm Burger, Mark J. Burge
http://link.springer.com/openurl?genre=book&isbn=978-1-4471-6684-9

Bayesian Essentials with R
Jean-Michel Marin, Christian P. Robert
http://link.springer.com/openurl?genre=book&isbn=978-1-4614-8687-9

Foundations of Programming Languages
Kent D. Lee
http://link.springer.com/openurl?genre=book&isbn=978-3-319-70790-7

Introduction to Artificial Intelligence
Wolfgang Ertel
http://link.springer.com/openurl?genre=book&isbn=978-3-319-58487-4

Linear Algebra and Analytic Geometry for Physical Sciences
Giovanni Landi, Alessandro Zampini
http://link.springer.com/openurl?genre=book&isbn=978-3-319-78361-1

Applied Linear Algebra
Peter J. Olver, Chehrzad Shakiban
http://link.springer.com/openurl?genre=book&isbn=978-3-319-91041-3

Neural Networks and Deep Learning
Charu C. Aggarwal
http://link.springer.com/openurl?genre=book&isbn=978-3-319-94463-0

Data Science and Predictive Analytics
Ivo D. Dinov
http://link.springer.com/openurl?genre=book&isbn=978-3-319-72347-1

Analysis for Computer Scientists
Michael Oberguggenberger, Alexander Ostermann
http://link.springer.com/openurl?genre=book&isbn=978-3-319-91155-7

A Beginners Guide to Python 3 Programming
John Hunt
http://link.springer.com/openurl?genre=book&isbn=978-3-030-20290-3

Advanced Guide to Python 3 Programming
John Hunt
http://link.springer.com/openurl?genre=book&isbn=978-3-030-25943-3

Fuente : https://medium.com/coinmonks/springer-has-released-65-machine-learning-and-data-books-for-free-e0744f5b5918

Salu2 a tod@s y feliz mes del amor y la amistad


Mr. Moon.

miércoles, 18 de agosto de 2021

Cómo conectar Python con Mongodb Atlas

 Atlas es el servicio en la nube de Mongodb, una base de datos no SQL, pues aquí un CRUD

una base llamada evalucion01, y una colección llamada CE (centro escolar)


import connection as net
import os
import pymongo
import dns

db = net.client.test

mydb = net.client["Evalucion01"]
mycol = mydb["CE"]
#conectamos con la base de datos y con la coleccións
#input() lo utilicé para hacer pausas y avanzar cuando se presione el teclado

while True#Generamos el Ciclo repetitivo para el menu
    
    os.system("cls"#Limpieza de pantalla
    print("Menu:")
    print("1. Añadir un registro")
    print("2. Ver los registro")
    print("3. Actualizar registro")
    print("4. Eliminar Registro")
    print("5. Salir")

    opcion = input("Ingrese su opción: "#Capturamos Opción
    
    if opcion == "1":
        ID = input("Digite el ID del centro escolar: "#Capturamos el ID
        Nombre = input("Digite el Nombre del centro escolar: "#Capturamos el Nombre
        Depto = input("Digite el departamento: "#Capturamos el Depto
        Munic = input("Digite el Municipio: "#Capturamos el Municipio

        mydict = { "_id"ID"Nombre"Nombre,"Departamento"Depto"Municipio"Munic } #Creamos diccionario
        x = mycol.insert_one(mydict#Lo ingresamos a la base
        input()

    elif opcion == "2":
       # for x in mycol.find(): #Ciclo repetitivo para imprimir todos los registros
       #     print(x)    
        
        ID = int(input("Digite el ID del centro escolar: ")) #Capturamos el ID
        for x in mycol.find({"_id"ID}):
            print(x)

        input()

    elif opcion == "3":
        ID = int(input("Digite el ID del centro escolar: ")) #Capturamos el ID
        for x in mycol.find({"_id"ID}):
            print(x)
        Nombre = input("Digite el nombre del centro escolar: ")
        Depto = input("Digite el departamento: "#Capturamos el Depto
        Munic = input("Digite el Municipio: "#Capturamos el Municipio

        mydict = { "$set": {"Nombre"Nombre,"Departamento"Depto"Municipio"Munic }} 
        x = mycol.update_one({"_id"ID}, mydict#actualizamos la base
        input()

    elif opcion == "4":
        ID = input("Digite el ID del centro escolar: "#Capturamos el ID
        x = mycol.find({"_id"ID})

        x = mycol.delete_one({"_id":ID}) 
        input()

    elif opcion == "5":
        print("Saliendo del Sistema")
        input()
        break  #saliendo del ciclo repetitivo

    else:
        print("Opción incorrecta")
        input()
        continue     #Continuando el ciclo repetitivo