Frequently
Asked
Questions


Poll

Which Web server are you using with Active FoxPro Pages?
 


Navigation

Active FoxPro Pages FAQ
AFP 2.x
AFP in general
First steps
News
Plugins
Resources
Samples
Votes
Web server
FAQuarium
Glossary
Plugins
Server
Sidebar
Site Navigation Bar
Top Articles


Your Location

Germany


Partner Sites

- Microsoft Community Guide -
- AFPBB Boost your Board -
- AFP-Community -
- MiDeK - Internet Publishing -
- VfpNetwork.Com -
- MSDN VFP -
- CoDe Magazine -
- Golo Haas -


Advertisement

Imprint

Microsoft CLIP member

 
  [58] How to send e-mails with Active FoxPro Pages
Rate this page Print Office Email Discuss
2872 requests - last updated Mittwoch, 06.10.2004
"Is it possible to realize mail transmissions with Active FoxPro Pages?" - "In theory: Yes"

Similar to this could have been some jokes of a German radio station in the mid-eigthies. During the last days and weeks sending mails with Active FoxPro Pages - or more clearly - with an AFP Web application seems to be a very hot topic in the newsgroups. Maybe this is based on the fact that the precessor had native mail capabilities integrated and now mail transfers is handled by plugins.
Someone could discuss on this decision for hours, whether it's useful or not - don't mind.

This article tries to give some sharp and clear instructions and offers some nice opportunities to send mails from your AFP Web applications. It's surely not the last decision for your businesses but we'll see what is possible and that's quite amazing. So, any mechanism shown here should be applicable for your applications:

  • AFP 3.0 Plugin: adcSendMail
  • West Wind wwIPStuff
  • more solutions

Why go abroad, when...

...mail functionalty comes with Active FoxPro Pages 3.0. More detailed we are talking about a plugin named adcSendMail.
To use this plugin and its methods, check your current AFP configuration or add it if missing. To do this, open your AFP configuration - either via AFP ControlCenter or direct editing of the XML file afp.config:

<plugin location="%root%\plugin\adcSendMail.fxp" engine="AFP"/>

save the changes, restart the AFP engine and now AFP is capable to send e-mails. Easy, isn't it?

Now, the AFP offers a new object called adcSendMail in your AFP documents, same as with request object or any other. To get more detailed information about the plugin please look at the provided HTML help file adcSendMail.chm below the plugin folder. I don't repeat those lines...

Sure, using the adcSendMail object directly might be attractive but this article likes to offer you a more elegant and even easier way to send any mails.
Okay, let's take our Web application foobar.afpa.code and create our 'own' method named SendMail with currently three parameters - for recipient name, the mail subject and the mail message:

Function SendMail(cRecipient As String, cSubject As String, cMessage As String) As String
	Local lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName, lcCCList, ;
	      lcBCCList, lcSubject, lcMessage, lcAttachment, ;
	      lcMailServer, lcError, lcContentType, lcExtraHeaders, ;
	      lcErrorMsg, lcUsername, lcPassword, lnPort
	Store "" To lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName, lcCCList, ;
		        lcBCCList, lcSubject, lcMessage, lcAttachment, ;
		        lcMailServer, lcError, lcContentType, lcExtraHeaders, ;
		        lcErrorMsg, lcUsername, lcPassword
	Store 0 To lnPort
	
	*// some checks before processing.
	If  Empty(m.cRecipient) OR ;
		Empty(m.cSubject) OR ;
		Empty(m.cMessage)
			Return m.lcErrorMsg
	EndIf

	*// Default values for this Web site...
	lcSenderEmail = "faq@afpfaq.de"
	lcSenderName = "AFP FAQ"
	lcRecipient = Transform(m.cRecipient)
	lcSubject = Transform(m.cSubject)
	lcMessage = Transform(m.cMessage)
	lcMailServer = "www.afpfaq.de"
	lcError = SPACE(513)
	lcContentType = [text/plain; charset="iso-8859-1"]
	lnPort = 25

	adcSendMail.adcSendMail(lcSenderEmail, lcSenderName,;
	                        lcRecipient, lcRecipientName,;
	                        lcCCList, lcBCCList, ;
	                        lcSubject, lcMessage, lcAttachment, ;
	                        lcMailServer, @lcError, lcContentType, lnPort)

	lcErrorMsg = TRIM(CHRTRANC(lcError,CHR(0),""))

	Return m.lcErrorMsg
EndFunc

Let's look a little bit closer at the presented source code.
As already said our method has only three parameters - recipient, subject and message. I would say that these three are the only 'real' parameters and so they are absolutely mandatory. If one is missing the methods returns and no mail is sent. Next, the standard values of our application are definied. These values should/might be constant all over the time - to me it seems very rare that the mail server changes every 5 minutes; or changing the character set for an English Web site.

Why this overload on creating a new method instead of using the adcSendMail object directly inside the AFP documents? - That's simple - laziness!

You might think, "Ey, more coding for laziness - fool one..." but I will show a small AFP sample document to send an e-mail now:

<%
SendMail("joki@afpfaq.de", "Testmail", "Test, 1, 2, 3...")
%>

And, actually that's all. Instead of using the whole parameters to execute the adcSendMail method of the plugin directly, we reduced all this to a small function call with three - see above - parameters for our recipient("joki@afpfaq.de"), our subject ("Testmail") and our message text ("Test, 1, 2, 3..."). You may use variables here as well - maybe defined by querystring or from a table:

<%
lcRecipient = "joki@afpfaq.de"
lcSubject = "Testmail"
lcBody = "Test, 1, 2, 3..."

SendMail(m.lcRecipient, m.lcSubject, m.lcBody)
%>

Maybe a small exercise for you:
The 'constants' of some mail parameters could be definied in and read from an external configuration file - preferred XML syntax.
On this issue there will a separate article coming the next weeks... Experiences are welcome :-)

In effect the real mail method of the plugin is executed.
If the interface of the plugin changes - who knows... - then any changes are made at one central point of your Web application. That's laziness.

Making Waves on the Web...

...and even this runs with Active FoxPro Pages. After all, we are coding in Visual FoxPro and hey, what about not using the products of West Wind. That's absolutely okay. If you're using wwipstuff with your desktop application, use it as well with your Web applications. No differences!

The integration of West Wind Internet Protocols (wwIPStuff) is similar easy as adding a plugin. Only difference is that integration is done on topic of the Web application instead of the whole AFP engine.

Let's see how this is done. Take the init event of your Web application and place the following code:

Procedure Event_Init
	DECLARE Integer SendMail ;
	   IN (Path.MakePath("%root%\plugin\wwipstuff.dll")) ;
	   AS _SendMail ;
	   STRING cFrom, ;
	   STRING cFromName, ;
	   STRING cTo, ;
	   STRING cCC, ;
	   STRING cBCC, ;
	   STRING cSubject, ;
	   STRING cMessage, ;
	   STRING cAttachment,; 
	   STRING cMailHost,;
	   STRING @cError,;
	   STRING cContentType,;
	   INTEGER nPort,;
	   STRING cExtraHeaders,;
	   String cUsername,;
	   String cPassword
EndProc

As you can see, it's practicable to see the Internet Protocols as just another plugin for the AFP engine.
Due to the fact that the DLL method as well as ours is called SendMail(), we use an alias to avoid any difficulties and create our own method for the application:

That's quite the same function as for the adcSendMail:

Function SendMail(cRecipient As String, cSubject As String, cMessage As String) As String
	Local lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName, lcCCList, ;
	      lcBCCList, lcSubject, lcMessage, lcAttachment, ;
	      lcMailServer, lcError, lcContentType, lcExtraHeaders, ;
	      lcErrorMsg, lcUsername, lcPassword, lnPort
	Store "" To lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName, lcCCList, ;
		        lcBCCList, lcSubject, lcMessage, lcAttachment, ;
		        lcMailServer, lcError, lcContentType, lcExtraHeaders, ;
		        lcErrorMsg, lcUsername, lcPassword
	Store 0 To lnPort
	
	*// some checks before processing.
	If  Empty(m.cRecipient) OR ;
		Empty(m.cSubject) OR ;
		Empty(m.cMessage)
			Return m.lcErrorMsg
	EndIf

	*// Default values for this Web site...
	lcSenderEmail = "faq@afpfaq.de"
	lcSenderName = "AFP FAQ"
	lcRecipient = Transform(m.cRecipient)
	lcSubject = Transform(m.cSubject)
	lcMessage = Transform(m.cMessage)
	lcMailServer = "www.afpfaq.de"
	lcError = SPACE(513)
	lcContentType = [text/plain; charset="iso-8859-1"]
	lnPort = 25

	If _SendMail(lcSenderEmail, lcSenderName,;
	             lcRecipient,;
	             lcCCList,lcBCCList,;
	             lcSubject, lcMessage, lcAttachment,;
	             lcMailServer,@lcError,lcContentType,;
	             lnPort,lcExtraHeaders,lcUsername,lcPassword) <> 1
	EndIf
		
	lcErrorMsg = TRIM(CHRTRANC(lcError,CHR(0),""))

	Return m.lcErrorMsg
EndFunc

Any real differences for the Web application? - Hmm, guess not ;-)
Any real changes in our samples AFP document? - None!
And that's exactly the reason for laziness, uhh flexibility. Even changing the real method to send the e-mails from adcSendMail to wwIPStuff does not harm our used AFP documents which use our self-definied SendMail function. in consequence less work, less stress, more fun.

A minimalistic way - Blat

Just Blat...
Blat is available as public domain since years and it is allowed to be used within your own applications. The interesting aspect about Blat is its simplicity of usage. Just create one big string for your mail and send it. Blat works as well with attachments and encodes mails in different ways.

Let's create a similar solution as above to send our own mails with Blat:

Procedure Event_Init
    Declare Long Send ;
        In (Path.MakePath("%root%\plugin\blat.dll")) ;
        As _BlatSend ;
        String cString
EndProc

Notes: This sample code is based on Blat.dll version 1.9.4 - a bit outaged but without any struct parameter to realize the DLL call.
The rest is nearly the same code as already seen:

Function SendMail(cRecipient As String,;
                  cSubject As String,;
                  cMessage As String) As String
    Local lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName,;
          lcCCList, lcBCCList, lcSubject, lcMessage,;
          lcAttachment, lcMailServer, lcErrorMsg, lnPort, lnResult
    Store "" To lcSenderEmail, lcSenderName, lcRecipient, lcRecipientName,;
                lcCCList, lcBCCList, lcSubject, lcMessage, lcAttachment, ;
                lcMailServer, lcErrorMsg
    Store 0 To lnPort, lnResult
    
    *// some checks before processing.
    If  Empty(m.cRecipient) OR ;
        Empty(m.cSubject) OR ;
        Empty(m.cMessage)
            Return m.lcErrorMsg
    EndIf

    *// Default values for this Web site...
    lcRecipient = Transform(m.cRecipient)
    lcSubject = Alltrim(Transform(m.cSubject))
    lcMessage = Transform(m.cMessage)
    lcSenderEmail = "faq@afpfaq.de"
    lcMailServer = "www.afpfaq.de"
    lnPort = 25

    lnResult = _BlatSend([- ] + ;
                         [-t ] + m.lcRecipient + [ ] + ;
                         [-s "] + m.lcSubject + [" ] + ;
                         [-body ] + m.lcMessage + [ ] + ;
                         [-f ] + m.lcSenderEmail + [ ] + ;
                         [-server ] + m.lcMailServer + [ ] + ;
                         [-port ] + Transform(m.lnPort))

    If m.lnResult # 0
        lcErrorMsg = "Error while sending mail: " + Transform(m.lnResult)
    EndIf
        
    Return m.lcErrorMsg
EndFunc

The code itself is shorter but effective. Blat provides authentication and is able to handle (multiple) attachments. Mail can be encoded in several ways - base64, quoted-printable, etc.

It's on you to combine these solutions - maybe to set a fail-over solution or whatever...

There are many ways towards Rome

And definitively the same number of possibilities to enhance Active FoxPro Pages with mail transfers or anything else. In theory any existing add-on for Microsoft Visual FoxPro should work with Active FoxPro Pages out-of-the-box. Just try it...
Naturally only if the add-on doesn't require any user interaction. And as hint, these add-ons should be thread-safe. Otherwise they might interfere with AFP's own multithreaded mode and that would be a pity, or?

Okay, there are several other solutions running through my mind about adding mail functionality:

  • Microsoft Winsock Control
  • CDONTS
  • MAPI-Messaging (s. VFP solutions application)
  • OLE automation via MS Outlook
  • Mabry Mail/X Controls
  • and much more

If you're already using your own class libraries for e-mail or you've any ActiceX control - try to use them with Active FoxPro Pages and use what you already known and are comfortable with.

That flexibilty of using existing resources is IMHO one of the powers of Active FoxPro Pages. Change the product to fulfill your needs, not the other way.
Please read the chapter about writing your own AFP plugin and look at the provided sample code in the AFP UserGuide. Hope to see a lot of new plugins...

Alright, at the end of this article I hope that I could enlight you a little bit about AFP 3.0 and its 'missing' mail functionality and I wish you a lot of fun while programming your Web applications.

Ah, if you are using any alternatives or any other class libraries / ActiveX controls not named before, please drop some lines at my post-office: faq@afpfaq.de - Thanks!

Enjoy the AFP FAQ, JoKi

All text is available under the terms of the
GNU Free Documentation License.

User contributed notesAdd a note
Seite war Helfer in der Not ! DANKE
by Georg - 06/25/2004 16:55:38
Copyright © 2002-2005 AFP FAQ. All rights reserved. Please send any irritations on this Web site to our Webmaster. Validate HTML