2007-07-03

Embed images to your emails with CDOSYS

based on some great samples that i found on the web, specially those from mike gagnon, i've created my own class to send emails. i chose to use cdosys (microsoft collaboration data objects for windows 2000)because it comes with win2000 / xp / vista and 2003, and it allows to send messages in various ways, specially embedding images that are used in the html content of the message.


mapi was my first choice, but unfortunately it does not allow to embed pictures, only attachments are allowed. ms outlook automation would work too, but i don`t have it too.


 


below is a simple code that generates an html page that contains some images that is to be sent. the images are embedded to the message, not as common attachments ! this allows us to show the pictures in the place and characteristics we desire.


apart from the most common features, it also allows you to embed pictures, add attachments, set priority, ask for a read receipt and send html.


the "body" property of the class accepts 3 different kinds of parameters: 1- an html code, 2- an url (cdosys will embed the entire page in the message) or 3- a .htm file that will be embedded. for this last option, my tests failed when i used spaces in either the directory name of the filename, so avoid spaces in filenames !


the pictures below show some screenshots of some samples that i generated and received using the code below, opened with outlook express. this was tested in some webmails too, eg. hotmail, and the result is similar.





 


save the code below as a prg, not forgetting to replace the information in red for your own, and run it.


 


it will ask you to choose some pictures. when finished, click "cancel"at the getpict() dialog, then choose any 2 other files that will be attached. wait for some seconds, enough time for sending the email, and check your inbox.


 


 




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.

   .receiptto = "you@yourserver.com"
   .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.


receiptto = ""
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. 

      if empty(this.receiptto)
         this.receiptto = this.to
      endif
      .
fields("urn:schemas:mailheader:disposition-notification-to") = this.receiptto
      .
fields("urn:schemas:mailheader:return-receipt-to") = this.receiptto
      .
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


 


 


related links:


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#


 


5 comments:

  1. Este articulo esta traducido al español en PortalFox:


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

    http://www.portalfox.com/article.php?sid=2476

    ReplyDelete
  2. He probado y funciona bien pero tengo algunos problemas

    1 Solo puedo mandar mail a cuentasde correo  del mismo SMTP

    2 no funciona "cc" y "bcc"

    3 solo puedo enviar a 1 destino, y deber ser de una cuenta del mismo SMTP


    Espero me puedas indicar que estoy haciendomal

    Felicidades muy buen trabajo

    ReplyDelete
  3. No funciona el cc y bcc cuando intento enviar a mas de una cuenta de correo da error


    he intentado todo y no me funciona ?????


    que hago ????

    ReplyDelete
  4. Hola Cesar, gracias por compartir este codigo, lo ejecute y al parecer algo esta fallando ya que no llega en mi caso enviar si alguien pudiera colocar las modificaciones para poder utilizar este codigo.

    ReplyDelete
  5. Hi,

    I used your code as above, but sometimes I am getting the below error. Any suggestions to avoid this error

    Method: send
    Error: OLE IDispatch exception code 0 from ?: The message could not be sent to the SMTP server. The transport error code was 0x80040217. The server response was not available
    ..
    Code: SELECT ZT90SVI1A

    Any help will be appreciated

    ReplyDelete