20 de julio de 2007

Incruste imágenes a sus correos electrónicos con CDOSYS

Artículo original: Embed images to your emails with CDOSYS
http://weblogs.foxite.com/vfpimaging/archive/2007/07/03/4256.aspx
Autor: Cesar Ch.
Traducido por: Luis María Guayán

Basado en algunos excelentes ejemplos que encontré en la Web, especialmente los de Mike Gagnon, he creado mi propia clase para enviar correos electrónicos. Decidí usar CDOSYS (Microsoft Collaboration Data Objects for Windows 2000) porque esto viene con Win2000 / XP / Vista y 2003, y permite enviar mensajes de varios maneras, especialmente incrustando imágenes que son usadas en el contenido HTML del mensaje.

MAPI era mi primera opción, pero lamentablemente esto no permite incrustar imágenes, sólo son permitidos los adjuntos. La automatización de MS Outlook también funcionaría, pero no lo tengo.

Abajo está un simple código que genera una página HTML que contiene algunas imágenes que deben ser enviadas. Las imágenes son incrustadas al mensaje, ¡no como simples adjuntos!. Este permite que mostremos las imágenes en el sitio y con las características que deseamos.

Aparte de las características más comunes, esto también permite que incruste imágenes, agregue adjuntos, configure la prioridad, solicite confirmación de lectura y envíe HTML.

La propiedad "Body" de la clase acepta 3 diferentes tipos de parámetros: 1-un código de HTML, 2-una URL (CDOSYS incrustará la página entera en el mensaje) o 3-un archivo HTML que será incustado. Para esta última opción, mis pruebas fallaron cuándo usé espacios en el nombre de directorio y/o en el nombre del archivo, ¡entonces evite espacios en nombres del archivo!.

Las imágenes de abajo muestran algunas pantallas de ejemplo que generé y recibí, utilizando el código de abajo, abriendo con Outlook Express. Esto también fue probado con algunos correos Web, como por ejemplo Hotmail y los resultados son similares.





Guarde el código de abajo como un PRG, y no olvide cambiar la información en Rojo por la propia, y ejecútelo.


Esto le pedirá elegir algunas imágenes. Cuando termine, haga Clic en "Cancelar" en el cuadro de diálogo de GETPICT(), luego elija otros 2 archivos cualquiera que serán adjuntados. Espere durante algunos segundos, los suficientes como para enviar el correo electrónico, y compruebe su bandeja de entrada.
LOCAL lcHeader, lcBody, lcClose, lcMsgBody, lnIndex, lcIndex, lcPictFile, lcJustFnamePictFile, lcHTML
TEXT TO lcHeader
<HTML><HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Verdana size=4><STRONG>EMBED PICTURES SAMPLE WITH CDOSYS</STRONG></FONT></DIV>
<P></P><P></P>
ENDTEXT
TEXT TO lcBody
<DIV><IMG src="<<lcPictFile>>"></DIV>
<DIV><FONT face=Verdana size=2>Image <<lcIndex>> - <<lcJustFnamePictFile>></FONT></DIV>
<P></P><P></P><div></div><div></div>
ENDTEXT
TEXT TO lcClose
</BODY></HTML>
ENDTEXT
lcMsgBody = ""
lnIndex = 1
DO WHILE .T.
  lcPictFile = GETPICT()
  IF EMPTY(lcPictFile)
    EXIT
  ENDIF
  lcIndex = TRANSFORM(lnIndex)
  lcJustFnamePictFile = JUSTFNAME(lcPictFile)
  lcMsgBody = lcMsgBody + TEXTMERGE(lcBody)
  lnIndex = lnIndex + 1
ENDDO
lcHTML = lcHeader + lcMsgBody + lcClose
* STRTOFILE(lcHtml,"c:\myHtmFile.htm")

LOCAL loMail as CDOSYSMAIL
loMail = CREATEOBJECT("CDOSYSMAIL")
WITH loMail
  .SMTPServer = "smtp.yourdomain.com" && place your smtp here
  .UserName = "yourusername" && Username
  .Password = "yourpassword" && Password
  .From = "Your Name <you@yourserver.com>"
  .To = "destination@server.com" 
  .Subject = "Testing CDOSYSMail"
  .HTMLFormat = .T. && Default = .T.
  .Priority = 1 && Default = 0 -1=Low, 0=Normal, 1=High
  .ReadReceipt = .T. && Default = .F.
  .Body = lcHTML
  * .Body = "http://www.microsoft.com"
  * .Body = "c:/myHtmFile.htm"
  .AddAttachment(GETFILE()) && FullPath of attachment
  .AddAttachment(GETFILE())
  .Send()
ENDWITH
RETURN

DEFINE CLASS CDOSYSMAIL AS Custom
  SMTPServer = ""
  UserName = "" 
  Password = ""
  From = ""
  To = ""
  Body = ""
  Subject = ""
  CC = ""
  BCC = ""
  HTMLFormat = .T.
  Priority = 0
  ReadReceipt = .F. 
  DIMENSION aFiles(1)

  PROCEDURE AddAttachment(tcFile)
    IF VARTYPE(tcFile) = "C" AND FILE(tcFile)
      lnFiles = ALEN(This.aFiles)
      DIMENSION This.aFiles(lnFiles + 1)
      This.aFiles(lnFiles+1) = tcFile
    ENDIF
  ENDPROC

  PROCEDURE Send
    #DEFINE CdoReferenceTypeName 1
    #DEFINE CdoReferenceTypeId 0

    LOCAL lcSchema, loConfig, loMsg
    lcSchema = "http://schemas.microsoft.com/cdo/configuration/"
    LOCAL loConfig as "CDO.Configuration"
    loConfig = CREATEOBJECT("CDO.Configuration")
    WITH loConfig.FIELDS
      .Item(lcSchema + "smtpserver") = This.SMTPServer && host of smtp server
      .Item(lcSchema + "smtpserverport") = "25" && SMTP Port
      .Item(lcSchema + "sendusing") = 2 && Send it using port
      .Item(lcSchema + "smtpauthenticate") = .T. && Authenticate
      .Item(lcSchema + "smtpusessl") = .F.
      .Item(lcSchema + "sendusername") = This.UserName && login
      .Item(lcSchema + "sendpassword") = This.Password && your password
      .Item(lcSchema + "smtpconnectiontimeout") = 10 && Assign timeout in seconds
      .Update()
    ENDWITH
    LOCAL loMsg as "CDO.Message"
    loMsg = CREATEOBJECT ("CDO.Message")
    WITH loMsg
      .Configuration = loConfig
      .Subject = This.Subject
      .FROM = This.From
      .TO = This.To
      IF VARTYPE(This.CC) = "C"
        .CC = This.CC
      ENDIF
      IF VARTYPE(This.BCC) = "C"
        .BCC = This.BCC
      ENDIF

      DO CASE 
        CASE FILE(This.Body)
          loMsg.CreateMHTMLBody("file://" + This.Body)

        CASE LOWER(LEFT(This.Body,7)) = "http://"
          loMsg.CreateMHTMLBody(This.Body) && This.Body

        CASE This.HTMLFormat = .T.

          LOCAL n, lcFile, lcPictRef, lcHTML, lcImgTag
          lcHTML = This.Body
          n = 1

          DO WHILE .T.
            lcImgTag = STREXTRACT(lcHTML, "<IMG", ">", n, 1)
            lcFile = STREXTRACT(lcImgTag, ["], ["])

            IF EMPTY(lcImgTag)
              EXIT
            ENDIF
            IF "http:" $ LOWER(lcFile) && reference to a picture stored on the web, so skip !
              n = n + 1
              LOOP
            ENDIF

            lcPictRef = "cid:" + JUSTFNAME(lcFile)

            lcHTML = STRTRAN(lcHTML, lcFile, lcPictRef, 1, 1)
            loMsg.AddRelatedBodyPart(lcFile, JUSTFNAME(lcFile), CdoReferenceTypeId)
            loMsg.Fields.Item("urn:schemas:mailheader:Content-ID") = "<" + (JUSTFNAME(lcFile)) + ">" 
            loMsg.Fields.Update()
            n = n + 1
          ENDDO
          .HTMLBody = lcHTML

        OTHERWISE 
          .TextBody = This.Body
      ENDCASE 

      IF ALEN(This.aFiles) > 1
        LOCAL lnCount
        FOR lnCount = 2 TO ALEN(This.aFiles)
          .AddAttachment(This.aFiles(lnCount))
          .Fields.Update()
        ENDFOR
      ENDIF

      * Set priority if needed
      IF This.Priority <> 0
        .Fields.Item("urn:schemas:mailheader:X-Priority") = This.Priority && -1=Low, 0=Normal, 1=High
        .Fields.Item("urn:schemas:httpmail:importance") = This.Priority
        .Fields.Update()
      ENDIF
      * Ask for Reading Receipt if needed
      IF This.ReadReceipt = .T. 
        .Fields("urn:schemas:mailheader:disposition-notification-to") = "you@yourserver.com"
        .Fields("urn:schemas:mailheader:return-receipt-to") = "you@yourserver.com"
        .Fields.Update()
      ENDIF

      * Set DSN options. This still needs some checking. 
      * For some SMTP servers this makes CDOSYS not to send the msg.
      * Name Value Description
      * cdoDSNDefault 0 No DSN commands are issued.
      * cdoDSNNever 1 No DSN commands are issued.
      * cdoDSNFailure 2 Return a DSN if delivery fails.
      * cdoDSNSuccess 4 Return a DSN if delivery succeeds.
      * cdoDSNDelay 8 Return a DSN if delivery is delayed.
      * cdoDSNSuccessFailOrDelay 14 Return a DSN if delivery succeeds, fails, or is delayed.
      .MDNRequested = .T. 
      * .DSNOptions = 2
      .Fields.Update()
      .Send()
    ENDWITH
  ENDPROC
ENDDEFINE

Enlaces relacionados:

Mike Gagnon: Étude sur l'utilisation de CDO et MAPI avec Visual Foxpro
http://fox.wikis.com/wc.dll?Wiki~CdoEmail~VFP
Craig Boyd article
How do I alter the priority / importance of an e-mail message?
Email, POP3, SMTP Scripts, Components and Articles
Lots of samples here
How to use the Cdosys.dll library to embed a message in a new message by using Visual C#

No hay comentarios. :

Publicar un comentario