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 m.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 m.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 m.lcclose [/body][/html] ENDTEXT m.lcMsgBody = "" m.lnIndex = 1 DO WHILE .T. m.lcPictFile = GETPICT() IF EMPTY(m.lcPictFile) EXIT ENDIF m.lcIndex = TRANSFORM(m.lnIndex) m.lcJustFNamePictFile = JUSTFNAME(m.lcPictFile) m.lcMsgBody = m.lcMsgBody + TEXTMERGE(m.lcBody) m.lnIndex = m.lnIndex + 1 ENDDO m.lcHTML = m.lcHeader + m.lcMsgBody + m.lcClose * strtofile(lchtml,"c:\myhtmfile.htm") LOCAL loMail AS CDOSYSMAIL m.loMail = CREATEOBJECT("cdosysmail") WITH m.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 = m.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) LOCAL lnFiles IF VARTYPE(m.tcFile) = "c" AND FILE(m.tcFile) m.lnFiles = ALEN(THIS.aFiles) DIMENSION THIS.aFiles(m.lnFiles + 1) THIS.aFiles(m.lnFiles + 1) = m.tcFile ENDIF ENDPROC PROCEDURE SEND #DEFINE CDOREFERENCETYPENAME 1 #DEFINE CDOREFERENCETYPEID 0 LOCAL lcSchema, loConfig AS "cdo.configuration", loMsg AS "cdo.message" m.lcSchema = "http://schemas.microsoft.com/cdo/configuration/" m.loConfig = CREATEOBJECT("cdo.configuration") WITH m.loConfig.FIELDS .ITEM(m.lcSchema + "smtpserver") = THIS.Smtpserver && host of smtp server .ITEM(m.lcSchema + "smtpserverport") = "25" && smtp port .ITEM(m.lcSchema + "sendusing") = 2 && send it using port .ITEM(m.lcSchema + "smtpauthenticate") = .T. && authenticate .ITEM(m.lcSchema + "smtpusessl") = .F. .ITEM(m.lcSchema + "sendusername") = THIS.UserName && login .ITEM(m.lcSchema + "sendpassword") = THIS.PASSWORD && your password .ITEM(m.lcSchema + "smtpconnectiontimeout") = 10 && assign timeout in seconds .UPDATE() ENDWITH m.loMsg = CREATEOBJECT ("cdo.message") WITH m.loMsg .configuration = m.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) m.loMsg.createmhtmlbody("file://" + THIS.Body) CASE LOWER(LEFT(THIS.Body,7)) = "http://" m.loMsg.createmhtmlbody(THIS.Body) && this.body CASE THIS.HtmlFormat = .T. LOCAL N, lcFile, lcPictRef, lcHtml, lcImgTag m.lcHtml = THIS.Body m.N = 1 DO WHILE .T. m.lcImgTag = STREXTRACT(m.lcHtml, "<img", "]", m.N, 1) m.lcFile = STREXTRACT(m.lcImgTag, ["], ["]) IF EMPTY(m.lcImgTag) EXIT ENDIF IF "http:" $ LOWER(m.lcFile) && reference to a picture stored on the web, so skip ! m.N = m.N + 1 LOOP ENDIF m.lcPictRef = "cid:" + JUSTFNAME(m.lcFile) m.lcHtml = STRTRAN(m.lcHtml, m.lcFile, m.lcPictRef, 1, 1) m.loMsg.addrelatedbodypart(m.lcFile, JUSTFNAME(m.lcFile), CDOREFERENCETYPEID) m.loMsg.FIELDS.ITEM("urn:schemas:mailheader:content-id") = "<" + (JUSTFNAME(m.lcFile)) + "]" m.loMsg.FIELDS.UPDATE() m.N = m.N + 1 ENDDO .htmlbody = m.lcHtml OTHERWISE .textbody = THIS.Body ENDCASE IF ALEN(THIS.aFiles) ] 1 LOCAL lnCount FOR m.lnCount = 2 TO ALEN(THIS.aFiles) .AddAttachment(THIS.aFiles(m.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#
Este articulo esta traducido al español en PortalFox:
ReplyDeleteIncruste imágenes a sus correos electrónicos con CDOSYS
http://www.portalfox.com/article.php?sid=2476
He probado y funciona bien pero tengo algunos problemas
ReplyDelete1 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
No funciona el cc y bcc cuando intento enviar a mas de una cuenta de correo da error
ReplyDeletehe intentado todo y no me funciona ?????
que hago ????
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.
ReplyDeleteHi,
ReplyDeleteI 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
Dear Cesar,
ReplyDeleteToo bad CDO does not support TLS over 587 (office365).
Any advise?
Thanks and regards,