<% // ============================================ // the content of this page // ============================================ function Content ( ) { Out ( '<td width="20%"> </td>' ); Out ( '<td width="60%">' );
// if the form has an email address, validate it first // so that if it fails we can show the form to fix var sEmail = ""; var bSubmitted = (Request.Form.Count > 0);
// has the form been submitted? if ( bSubmitted ) { // get the email address from the form... sEmail = "" + Request.Form ( "email" );
// validate the email address and moan if it fails if ( !IsValidEmail ( sEmail ) ) { Out ( '<h5><font color="red">"' + sEmail + '" <i>appears</i> to be an invalid email address - please try again!</font></h5>' ); Out ( '<p><font color="red">If you disagree, please <a href="Contact.asp">contact me</a> directly.</font><p>' ); // PRetend the form hasn'/t been sent yet bSubmitted = false; } }
// show the form if not submitted yet if ( !bSubmitted ) { Out ( 'If you/'re interested in hearing whenever a new article is posted, or an existing one is updated, type in your email address below and hit <b>Subscribe!</b>' ); Out ( '<p>Whenever you want to stop receiving my emails, guess what? That/'s right, enter your email address and hit <b>Unsubscribe</b>...' ); Out ( '<p><i>Your email address will never sold to or otherwise used by any third party, just me.</i>' );
// here's the form tag. the action attribute is the name of // the file that will be called with the answer - in this case // it's the same page. the method can be "post" to send the // form data 'behind the scenes' or "get" to appending the // data to the URL in the style page.asp?data1=a&data2=b // // use post most of the time - it's neater and "get" is limited // in the amount of data that can be sent. Out ( '<center><form action="Subscribe.asp" method="post">' );
// another table to line up the titles and inputs Out ( '<table border="0" cellpadding="0">' ); Out ( '<tr><td align="right" valign="top">' ); Out ( 'Email:' ); Out ( '</td><td align="left" valign="top">' ); // a simple text box. we'll reference it with the name "name" // and show 22 characters on the form. use the maxlength // attribute to set the maximum characters they can enter. // use value="some text" to pre-fill the input with data. // // IMPORTANT! using names that are commonly used by // other web sites has a big advantage to the user - IE // will drop down a list of previous answers, which they // can usually pick from rather than type in. Think about this. Out ( '<input type="text" name="email" size="31" value="' + sEmail + '"></input>' ); Out ( '</td></tr>' );
Out ( '<tr><td align="right" valign="top">' ); Out ( ' ' ); Out ( '</td><td align="left" valign="top">' ); // type='submit" provides a submit button to perform the // form action. the button says "Submit" unless you override // with the value attribute. Out ( '<input type="submit" name="action" value="Subscribe"></input> <input type="submit" name="action" value="Unsubscribe"></input>' ); Out ( '</td></tr>' );
Out ( '</table>' ); Out ( '</form></center>' ); } else { var sAction = "" + Request.Form ( "action" );
Out ( 'Do you want to see how this form adds and removes addresses to my database? All the source code is just a click away!' ); Out ( '<p><center><a href="ShowSource.asp? page=Subscribe"><img src="images/source.gif" border=0></a></center>' ); Out ( '<p>In <a href="MailToList.asp">Part 2</a> see how I wrote a form to mail all my subscribers...' );
Out ( '</td>' ); Out ( '<td width="20%"> </td>' ); }
// ============================================ // validate email address // ============================================ function IsValidEmail ( sEmail ) { // regular expression courtesy of ed.courtenay@nationwideisp.net // I won't even pretend that I've read through this yet!
// ============================================ // add email to database // ============================================ function AddEmail ( sEmail ) { // open the connection DBInitConnection ( );
// first see if they are already subscribed var sSQL = 'SELECT Email FROM MailingList WHERE Email="' + sEmail + '";';
DBGetRecords ( sSQL );
if ( !oRecordSet.EOF ) { Out ( '<h5><font color="red">' + sEmail + ' is already subscribed to my mailing list!</font></h5>' ); return; }
// this section needs more work - what should be done is that an email is // sent to the email address, and only added to the database when we // get a reply. that way we know the address is valid and the recipient // really wants to join the list. for now though, we'll add to the db now. sSQL = 'INSERT INTO MailingList (Email) VALUES ("' + sEmail + '");';
oConnection.Execute( sSQL );
// free the connection DBReleaseConnection ( );
Out ( sEmail + ' has been successfully subscribed to my mailing list. ' ); Out ( '<p>You will now receive an email whenever I write new articles, or if I make an important update to any.' );
Email ( 'Joined the ShawThing mailing list', sEmail, 'You have successfully subscribed to the mailing list at ShawThing. If you didn/'t request this please reply to this email, or visit http://www.shawthing.com/subscribe.asp to unsubscribe./n/nThank you./n/nJames Shaw/nhttp://www.shawthing.com/' ); }
// ============================================ // remove email from database // ============================================ function RemoveEmail ( sEmail ) { // open the connection DBInitConnection ( );
// first see if they are already subscribed var sSQL = 'SELECT Email FROM MailingList WHERE Email="' + sEmail + '";';
DBGetRecords ( sSQL );
if ( oRecordSet.EOF ) { Out ( '<h5><font color="red">' + sEmail + ' isn/'t subscribed to my mailing list!</font></h5>' ); return; }
// delete from the database sSQL = 'DELETE FROM MailingList WHERE Email="' + sEmail + '";';
oConnection.Execute( sSQL );
// free the connection DBReleaseConnection ( );
Out ( sEmail + ' has been successfully removed from my mailing list. ' ); Out ( '<p>You have been sent a confirmation email, but after that you will not receive any more emails.' );
Email ( 'Removal from ShawThing mailing list', sEmail, 'You have been successfully removed from the mailing list at ShawThing. If you didn/'t request this please reply to this email, or visit http://www.shawthing.com/subscribe.asp to re-subscribe./n/nThank you./n/nJames Shaw/nhttp://www.shawthing.com/' ); }
// ============================================ // email me! // ============================================ function Email ( sSubject, sEmail, sMessage ) { // send an email to the address just to confirm what just happened var oMail = Server.CreateObject ( "CDONTS.NewMail" );
// setup the mail oMail.From = 'DB@shawthing.com';
oMail.To = sEmail; oMail.Importance = 1;
oMail.Subject = sSubject; oMail.Body = sMessage;
// send it oMail.Send ( );
// release object oMail = null; } %>
utils/Database.asp <% // globals var oConnection; var oRecordSet; var sConnection;
// ============================================ // initializes database variables for first use on page // ============================================ function DBInitConnection ( ) { // don't open it again if already opened! if ( sConnection != undefined ) return;
// get connection object oConnection = Server.CreateObject( 'ADODB.Connection' );
// get the database connection string // use MapPath to make relative path into physical path sConnection = 'Provider=Microsoft.Jet.OLEDB.4.0; Data Source=' + Server.MapPath ( sDBPath );
// open the connection oConnection.Open( sConnection );
// as an attempt at optimization we now open // the recordset here, not in DBGetRecords() oRecordSet = Server.CreateObject ( 'ADODB.Recordset' ); }
// ============================================ // tidies up after DBInitConnection // ============================================ function DBReleaseConnection ( ) { // don't release the connection if not connected! if ( sConnection == undefined ) return;
// as an attempt at optimization we now close // the recordset here, not in DBReleaseRecords() if ( oRecordSet.State != 0 ) oRecordSet.Close(); oRecordSet = undefined;
oConnection.Close(); oConnection = undefined;
sConnection = undefined; }
// ============================================ // executes the passed in SQL statement // and returns the oRecordSet object // ============================================ function DBGetRecords ( sSQL ) { // remember that this can fail if passed garbage, and hence // 'oRecordSet' will already be 'closed' oRecordSet = oConnection.Execute( sSQL ); }
// ============================================ // tidies up after DBGetRecords // ============================================ function DBReleaseRecords ( ) { // IMPORTANT: THIS FUNCTION INTENTIONALLY BLANK // as an attempt at optimization we now open/close // the recordset with the connection, not separately // so all code was moved to DBReleaseConnection.
// it is recommended that you still call this function as soon // as the recordset is finished with.
// note that it is assumed by the caller that it is legal // to call DBReleaseConnection without calling this function } %>