I'm not very good with ASP.NET I normally code in perl on unix so here goes...
I'm trying to get a form to be processed by a ASP.NET script and it email the forms fields to me.
I've got the script working on a windows server at work but can't get it working on a names.co.uk server.
This is the asp.net code I have:
<%@ Page Language="C#" EnableSessionState="False" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Web.Mail" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
<script runat="server">
/* Configuration Variables */
// Allow posting in cases where the Referer: header has been stripped.
bool AllowEmptyReferer = false;
// Allowed e-mail addresses for formmail.aspx to send e-mail to. The elements of this
// array can be either simple e-mail addresses ("you@your.domain") or domain
// name ("your.domain"). If its a domain name, then *any* address at the domain
// will be allowed.
string[] AllowMailTo = { "my@email.co.uk" };
// If true, then a blank line is printed after each form value in the e-mail.
bool DoubleSpacing = true;
// Max recipients; maximum number of recipients that a form should be allowed to e-mail
// messages to.
int MaxRecipients = 1;
// No Content - indicates that rather than returning the HTML confirmation page or
// doing a redirect the script will output a header that indicates that no content should
// be returned and that the submitted form should not be replaced. This should be used
// carefully as an unwitting visitor may click the submit button several times thinking
// that nothing has happened.
bool NoContent = false;
// A hash for predefining a list of recipients in the script, and then choosing
// between them using the recipient form field, while keeping all the e-mail
// addresses out of the HTML so that they don't get harvested.
//
// The key is the alias, the value is the e-mail address.
//
// The recipients in RecipientAliases are automatically added to the allowed
// recipients list, so there's no need to list them all in AllowMailTo as well.
Hashtable RecipientAliases = new Hashtable();
// Referer: hosts allowed to relay through this script;
// unlike formmail.pl, the option to allow any is *not* possible.
string[] Referers = { " };
// The envelope sender address to use for all e-mails sent by the
// script. This address will receive bounce messages if any of the
// e-mails cannot be delivered.
string Sender = "sender@email.com";
// SMTP relay
string SmtpRelay =
"smtp.hosts.co.uk";
// Wrap text at around 72 columns.
bool WrapText = true;
// Handle the posted form data when the page loads and convert it to an e-mail to send.
protected void Page_Load(object sender, EventArgs e)
{
// Check the request method of this page is "POST", as if we aren't receiving form data, we can't
// do a damn thing.
if (Request.HttpMethod != "POST")
{
this.SetError("Configuration Error: Did not arrive at this page through a POST.");
return;
}
if (!this.CheckReferer())
{
this.SetError(String.Format("Usage Error: Referer {0} is not permitted.", this.Request.UrlReferrer.ToString()));
return;
}
// Parse out the form fields.
Hashtable metaFields;
Hashtable contentFields;
this.ParseForm(this.Request.Form, out metaFields, out contentFields);
// Split out "required" and validate fields present; if not, redirect to "missing_fields_redirect";
// if not present, throw error.
if (metaFields.ContainsKey("required"))
{
string[] reqFields = ((string)metaFields["required"]).Split(new char[] {','});
foreach (string s in reqFields)
{
if (!contentFields.ContainsKey(s))
{
if (metaFields.ContainsKey("missing_fields_redirect"))
{
this.Response.Redirect((string)metaFields["missing_fields_redirect"], true);
// Execution terminates here.
}
else
{
this.SetError(String.Format("User Error: The {0} field was not provided.", s));
return;
}
}
}
}
// Split out the "recipient" metaField around commas; if it doesn't exist, throw error.
if (!metaFields.ContainsKey("recipient"))
{
// If no recipient specified, use the first member of the AllowMailTo variable, thus
// emulating the formmail behaviour.
if (this.AllowMailTo.Length > 0)
{
// Fake it.
metaFields.Add("recipient", this.AllowMailTo[0]);
}
else
{
this.SetError("Usage Error: No recipients were specified for the form.");
return;
}
}
string[] rawRecipients = ((string)metaFields["recipient"]).Split(new char[] { ',' });
// Validate recipient count (MaxRecipients).
if ((MaxRecipients != 0) && (rawRecipients.Length > this.MaxRecipients))
{
this.SetError(String.Format("Usage Error: Too many recipients; maximum number is {0}.", this.MaxRecipients));
return;
}
// Perform recipient alias substitution (RecipientAliases) to temp list.
ArrayList trueRecipients = new ArrayList();
ArrayList aliasRecipients = new ArrayList ();
foreach (string s in rawRecipients)
{
if (this.RecipientAliases.ContainsKey(s))
aliasRecipients.Add(this.RecipientAliases);
else
trueRecipients.Add(s);
}
// Validate recipient addresses (AllowMailTo).
foreach (string s in trueRecipients)
{
bool valid = false ;
foreach (string v in this.AllowMailTo)
{
// If it ends with the valid string, it's either the same, or in that domain.
// Yeah, partial addresses and domains will also work, this way, but let's not point
// it out, huh? If anyone does anything stupid with this option, it's their own damn
// fault.
if (s.EndsWith(v))
valid = true;
}
if (valid = false)
{
this.SetError(String.Format("Usage Error: Recipient {0} is not valid for this script.", s));
return;
}
}
// Add aliases back in, format final sending list.
StringBuilder sb = new StringBuilder();
foreach (string s in aliasRecipients)
{
sb.Append(s);
sb.Append(",");
}
foreach (string s in trueRecipients)
{
sb.Append(s);
sb.Append(",");
}
sb.Remove(sb.Length - 1, 1);
string recipients = sb.ToString();
// Split out and set "subject".
string subject;
if (metaFields.ContainsKey("subject"))
subject = (string)metaFields["subject"];
else
subject = "Booking Form";
// Create message body pre-amble.
StringBuilder body = new StringBuilder ();
body.Append("Below is the result of your feedback form. It was submitted by\n");
if (contentFields.ContainsKey("realname"))
body.Append((string)contentFields["realname"]);
else
body.Append("the user");
if (contentFields.ContainsKey("email"))
body.Append(String.Format(" <{0}>", (string)contentFields["email"]));
body.Append(String.Format(" on {0}.\n", DateTime.Now));
body.Append("--------------------------------------------------------------------------\n\n");
// Loop on content fields and prepare message body; obey values of
// DoubleSpacing, WrapText, "sort", "print_blank_fields".
bool printBlankFields ;
ArrayList sortOrder ;
if (metaFields.ContainsKey("print_blank_fields"))
printBlankFields = true;
else
printBlankFields = false;
if (metaFields.ContainsKey("sort"))
{
string sv = (string)metaFields["sort"] ;
if (sv == "alphabetic")
{
sortOrder = this.GetFields(contentFields);
sortOrder.Sort();
}
else if (sv.StartsWith("order:"))
{
sortOrder = new ArrayList();
string [] skeys = (sv.Substring(6)).Split(new char[] { ',' });
foreach (string s in skeys)
{
sortOrder.Add(s);
}
}
else
{
this.SetError(String.Format("Usage Error: the sort order {0} is not supported.", sv));
return;
}
}
else
{
// Or it can be blank, in which case we take them as they come.
sortOrder = this.GetFields (contentFields) ;
}
// Loop through the sort order
foreach (string key in sortOrder)
{
// Does the field exist? If so, append it if PrintBlankFields, if not, not,
// while wrapping the text.
if (contentFields.ContainsKey(key))
{
if ((string)contentFields[key] != String.Empty)
{
body.Append(String.Format("{0}\n", this.BuildSingleField(key, (string)contentFields[key])));
}
else
{
if (printBlankFields)
body.Append (String.Format ("{0}\n", this.BuildSingleField (key, ""))) ;
}
// If DoubleSpacing, append extra blank line.
if (this.DoubleSpacing)
body.Append ("\n") ;
}
}
// Check for "email" and "realname" values in contentValues to decide whether or not to
// use as sender address.
string senderaddr;
if (contentFields.ContainsKey("_email"))
{
if (contentFields.ContainsKey("realname"))
{
senderaddr = String.Format("{0} ({1})", (string)contentFields["email"], (string)contentFields["realname"]);
}
else
{
senderaddr = (string)contentFields["email"];
}
}
else
{
senderaddr = this.Sender;
}
// Send e-mail to "recipient"s, from "email"/"realname", or Sender, accordingly, going
// though SmtpServer.
this.SendMail(recipients, senderaddr, subject, body.ToString());
// If redirect, redirect to that page, otherwise...
if (metaFields.ContainsKey("redirect"))
{
Response.Redirect((string)metaFields["redirect"], true);
}
// If NoContent, return that code...
if (this.NoContent)
{
Response.StatusCode = 204;
Response.End();
}
// ...otherwise display "return_link", "return_link_title". If both
// are not present, drop through.
if ((metaFields.ContainsKey("return_link")) && (metaFields.ContainsKey("return_link_title")))
{
hlReturn.NavigateUrl = (string)metaFields["return_link"];
hlReturn.Text = (string)metaFields["return_link_title"];
hlReturn.Visible = true;
}
lbError.Text = "Your form was successfully submitted.\n" ;
}
private string BuildSingleField(string key, string value)
{
string baseval = String.Format("{0}: {1}", key, value);
if (!this.WrapText)
return baseval;
else
{
// Wrap the text at the 72nd column.
StringBuilder retval = new StringBuilder();
// Loop chopping the text at the 1st space before 72 and appending it as a new line.
while (baseval.Length > 72)
{
int cutPosition = 72;
while ((baseval[cutPosition] != ' ') && (cutPosition > 0))
{
cutPosition-- ;
}
if (cutPosition == 0)
cutPosition = 72 ; // if we hit the beginning, hard-cut it.
retval.Append (baseval.Substring (0, cutPosition+1)) ;
retval.Append("\n");
baseval = baseval.Remove (0, cutPosition+1) ;
}
// Append the remains, *without* a new line.
retval.Append(baseval);
return retval.ToString();
}
}
// Check the referer header of this post against the authorised list; if it is allowed, return
// true; if not allowed, return false.
private bool CheckReferer()
{
// Check for empty referer first.
if (this.Request.UrlReferrer == null)
{
if (this.AllowEmptyReferer)
return true;
else
return false;
}
// Get the host part.
string host = this.Request.UrlReferrer.Host;
foreach (string s in this.Referers)
{
if (s == host)
return true;
}
// If we don't find it in the array, it's not allowed.
return false;
}
private ArrayList GetFields(Hashtable fields)
{
ArrayList retval = new ArrayList();
foreach (string s in fields.Keys)
{
retval.Add(s);
}
return retval;
}
// Split up the posted form values into meta-keys that command formmail and content keys that are values
// to return.
private void ParseForm(NameValueCollection formValues, out Hashtable metaValues, out Hashtable contentValues)
{
string[] metaKeys = { "recipient", "subject", "redirect", "return_link_url", "return_link_title",
"sort", "required", "missing_fields_redirect", "print_blank_fields", "submit" };
metaValues = new Hashtable();
contentValues = new Hashtable();
foreach (string k in formValues.Keys)
{
foreach (string m in metaKeys)
{
if (k.Equals(m))
{
metaValues.Add(k, formValues[k]);
goto iterate;
}
}
contentValues.Add(k, formValues[k]);
iterate: ;
}
// return the two new Hashtables
}
private void SendMail(string recipient, string sender, string subject, string body)
{
// Construct the message.
MailMessage msg = new MailMessage();
// TODO: envelope from
msg.From = sender;
msg.To = recipient ;
msg.Subject = subject;
msg.Body = body;
SmtpMail.SmtpServer = this.SmtpRelay;
try
{
SmtpMail.Send(msg);
}
catch (Exception ex)
{
this.SetError(String.Format("Your submission could not be delivered: {0}", ex.Message));
return;
}
}
// Set the text of an error message and colorise it.
private void SetError(string errorMessage)
{
lbError.Text = errorMessage;
lbError.ForeColor = Color.Red;
}
</script>
<html xmlns="<head runat="server">
<title>Formmail.ASPX - Form Submission By Mail</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lbError" runat="server"></asp:Label> <br />
<asp:HyperLink ID="hlReturn" runat="server" EnableViewState="False" Visible="False">[hlReturn]</asp:HyperLink></div>
</form>
</body>
</html>
It all works fine (no script errors) but I don't get the email.
Does anyone else host with namesco or know what I might be doing wrong?
I'm trying to get a form to be processed by a ASP.NET script and it email the forms fields to me.
I've got the script working on a windows server at work but can't get it working on a names.co.uk server.
This is the asp.net code I have:
<%@ Page Language="C#" EnableSessionState="False" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Web.Mail" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
<script runat="server">
/* Configuration Variables */
// Allow posting in cases where the Referer: header has been stripped.
bool AllowEmptyReferer = false;
// Allowed e-mail addresses for formmail.aspx to send e-mail to. The elements of this
// array can be either simple e-mail addresses ("you@your.domain") or domain
// name ("your.domain"). If its a domain name, then *any* address at the domain
// will be allowed.
string[] AllowMailTo = { "my@email.co.uk" };
// If true, then a blank line is printed after each form value in the e-mail.
bool DoubleSpacing = true;
// Max recipients; maximum number of recipients that a form should be allowed to e-mail
// messages to.
int MaxRecipients = 1;
// No Content - indicates that rather than returning the HTML confirmation page or
// doing a redirect the script will output a header that indicates that no content should
// be returned and that the submitted form should not be replaced. This should be used
// carefully as an unwitting visitor may click the submit button several times thinking
// that nothing has happened.
bool NoContent = false;
// A hash for predefining a list of recipients in the script, and then choosing
// between them using the recipient form field, while keeping all the e-mail
// addresses out of the HTML so that they don't get harvested.
//
// The key is the alias, the value is the e-mail address.
//
// The recipients in RecipientAliases are automatically added to the allowed
// recipients list, so there's no need to list them all in AllowMailTo as well.
Hashtable RecipientAliases = new Hashtable();
// Referer: hosts allowed to relay through this script;
// unlike formmail.pl, the option to allow any is *not* possible.
string[] Referers = { " };
// The envelope sender address to use for all e-mails sent by the
// script. This address will receive bounce messages if any of the
// e-mails cannot be delivered.
string Sender = "sender@email.com";
// SMTP relay
string SmtpRelay =
"smtp.hosts.co.uk";
// Wrap text at around 72 columns.
bool WrapText = true;
// Handle the posted form data when the page loads and convert it to an e-mail to send.
protected void Page_Load(object sender, EventArgs e)
{
// Check the request method of this page is "POST", as if we aren't receiving form data, we can't
// do a damn thing.
if (Request.HttpMethod != "POST")
{
this.SetError("Configuration Error: Did not arrive at this page through a POST.");
return;
}
if (!this.CheckReferer())
{
this.SetError(String.Format("Usage Error: Referer {0} is not permitted.", this.Request.UrlReferrer.ToString()));
return;
}
// Parse out the form fields.
Hashtable metaFields;
Hashtable contentFields;
this.ParseForm(this.Request.Form, out metaFields, out contentFields);
// Split out "required" and validate fields present; if not, redirect to "missing_fields_redirect";
// if not present, throw error.
if (metaFields.ContainsKey("required"))
{
string[] reqFields = ((string)metaFields["required"]).Split(new char[] {','});
foreach (string s in reqFields)
{
if (!contentFields.ContainsKey(s))
{
if (metaFields.ContainsKey("missing_fields_redirect"))
{
this.Response.Redirect((string)metaFields["missing_fields_redirect"], true);
// Execution terminates here.
}
else
{
this.SetError(String.Format("User Error: The {0} field was not provided.", s));
return;
}
}
}
}
// Split out the "recipient" metaField around commas; if it doesn't exist, throw error.
if (!metaFields.ContainsKey("recipient"))
{
// If no recipient specified, use the first member of the AllowMailTo variable, thus
// emulating the formmail behaviour.
if (this.AllowMailTo.Length > 0)
{
// Fake it.
metaFields.Add("recipient", this.AllowMailTo[0]);
}
else
{
this.SetError("Usage Error: No recipients were specified for the form.");
return;
}
}
string[] rawRecipients = ((string)metaFields["recipient"]).Split(new char[] { ',' });
// Validate recipient count (MaxRecipients).
if ((MaxRecipients != 0) && (rawRecipients.Length > this.MaxRecipients))
{
this.SetError(String.Format("Usage Error: Too many recipients; maximum number is {0}.", this.MaxRecipients));
return;
}
// Perform recipient alias substitution (RecipientAliases) to temp list.
ArrayList trueRecipients = new ArrayList();
ArrayList aliasRecipients = new ArrayList ();
foreach (string s in rawRecipients)
{
if (this.RecipientAliases.ContainsKey(s))
aliasRecipients.Add(this.RecipientAliases
else
trueRecipients.Add(s);
}
// Validate recipient addresses (AllowMailTo).
foreach (string s in trueRecipients)
{
bool valid = false ;
foreach (string v in this.AllowMailTo)
{
// If it ends with the valid string, it's either the same, or in that domain.
// Yeah, partial addresses and domains will also work, this way, but let's not point
// it out, huh? If anyone does anything stupid with this option, it's their own damn
// fault.
if (s.EndsWith(v))
valid = true;
}
if (valid = false)
{
this.SetError(String.Format("Usage Error: Recipient {0} is not valid for this script.", s));
return;
}
}
// Add aliases back in, format final sending list.
StringBuilder sb = new StringBuilder();
foreach (string s in aliasRecipients)
{
sb.Append(s);
sb.Append(",");
}
foreach (string s in trueRecipients)
{
sb.Append(s);
sb.Append(",");
}
sb.Remove(sb.Length - 1, 1);
string recipients = sb.ToString();
// Split out and set "subject".
string subject;
if (metaFields.ContainsKey("subject"))
subject = (string)metaFields["subject"];
else
subject = "Booking Form";
// Create message body pre-amble.
StringBuilder body = new StringBuilder ();
body.Append("Below is the result of your feedback form. It was submitted by\n");
if (contentFields.ContainsKey("realname"))
body.Append((string)contentFields["realname"]);
else
body.Append("the user");
if (contentFields.ContainsKey("email"))
body.Append(String.Format(" <{0}>", (string)contentFields["email"]));
body.Append(String.Format(" on {0}.\n", DateTime.Now));
body.Append("--------------------------------------------------------------------------\n\n");
// Loop on content fields and prepare message body; obey values of
// DoubleSpacing, WrapText, "sort", "print_blank_fields".
bool printBlankFields ;
ArrayList sortOrder ;
if (metaFields.ContainsKey("print_blank_fields"))
printBlankFields = true;
else
printBlankFields = false;
if (metaFields.ContainsKey("sort"))
{
string sv = (string)metaFields["sort"] ;
if (sv == "alphabetic")
{
sortOrder = this.GetFields(contentFields);
sortOrder.Sort();
}
else if (sv.StartsWith("order:"))
{
sortOrder = new ArrayList();
string [] skeys = (sv.Substring(6)).Split(new char[] { ',' });
foreach (string s in skeys)
{
sortOrder.Add(s);
}
}
else
{
this.SetError(String.Format("Usage Error: the sort order {0} is not supported.", sv));
return;
}
}
else
{
// Or it can be blank, in which case we take them as they come.
sortOrder = this.GetFields (contentFields) ;
}
// Loop through the sort order
foreach (string key in sortOrder)
{
// Does the field exist? If so, append it if PrintBlankFields, if not, not,
// while wrapping the text.
if (contentFields.ContainsKey(key))
{
if ((string)contentFields[key] != String.Empty)
{
body.Append(String.Format("{0}\n", this.BuildSingleField(key, (string)contentFields[key])));
}
else
{
if (printBlankFields)
body.Append (String.Format ("{0}\n", this.BuildSingleField (key, ""))) ;
}
// If DoubleSpacing, append extra blank line.
if (this.DoubleSpacing)
body.Append ("\n") ;
}
}
// Check for "email" and "realname" values in contentValues to decide whether or not to
// use as sender address.
string senderaddr;
if (contentFields.ContainsKey("_email"))
{
if (contentFields.ContainsKey("realname"))
{
senderaddr = String.Format("{0} ({1})", (string)contentFields["email"], (string)contentFields["realname"]);
}
else
{
senderaddr = (string)contentFields["email"];
}
}
else
{
senderaddr = this.Sender;
}
// Send e-mail to "recipient"s, from "email"/"realname", or Sender, accordingly, going
// though SmtpServer.
this.SendMail(recipients, senderaddr, subject, body.ToString());
// If redirect, redirect to that page, otherwise...
if (metaFields.ContainsKey("redirect"))
{
Response.Redirect((string)metaFields["redirect"], true);
}
// If NoContent, return that code...
if (this.NoContent)
{
Response.StatusCode = 204;
Response.End();
}
// ...otherwise display "return_link", "return_link_title". If both
// are not present, drop through.
if ((metaFields.ContainsKey("return_link")) && (metaFields.ContainsKey("return_link_title")))
{
hlReturn.NavigateUrl = (string)metaFields["return_link"];
hlReturn.Text = (string)metaFields["return_link_title"];
hlReturn.Visible = true;
}
lbError.Text = "Your form was successfully submitted.\n" ;
}
private string BuildSingleField(string key, string value)
{
string baseval = String.Format("{0}: {1}", key, value);
if (!this.WrapText)
return baseval;
else
{
// Wrap the text at the 72nd column.
StringBuilder retval = new StringBuilder();
// Loop chopping the text at the 1st space before 72 and appending it as a new line.
while (baseval.Length > 72)
{
int cutPosition = 72;
while ((baseval[cutPosition] != ' ') && (cutPosition > 0))
{
cutPosition-- ;
}
if (cutPosition == 0)
cutPosition = 72 ; // if we hit the beginning, hard-cut it.
retval.Append (baseval.Substring (0, cutPosition+1)) ;
retval.Append("\n");
baseval = baseval.Remove (0, cutPosition+1) ;
}
// Append the remains, *without* a new line.
retval.Append(baseval);
return retval.ToString();
}
}
// Check the referer header of this post against the authorised list; if it is allowed, return
// true; if not allowed, return false.
private bool CheckReferer()
{
// Check for empty referer first.
if (this.Request.UrlReferrer == null)
{
if (this.AllowEmptyReferer)
return true;
else
return false;
}
// Get the host part.
string host = this.Request.UrlReferrer.Host;
foreach (string s in this.Referers)
{
if (s == host)
return true;
}
// If we don't find it in the array, it's not allowed.
return false;
}
private ArrayList GetFields(Hashtable fields)
{
ArrayList retval = new ArrayList();
foreach (string s in fields.Keys)
{
retval.Add(s);
}
return retval;
}
// Split up the posted form values into meta-keys that command formmail and content keys that are values
// to return.
private void ParseForm(NameValueCollection formValues, out Hashtable metaValues, out Hashtable contentValues)
{
string[] metaKeys = { "recipient", "subject", "redirect", "return_link_url", "return_link_title",
"sort", "required", "missing_fields_redirect", "print_blank_fields", "submit" };
metaValues = new Hashtable();
contentValues = new Hashtable();
foreach (string k in formValues.Keys)
{
foreach (string m in metaKeys)
{
if (k.Equals(m))
{
metaValues.Add(k, formValues[k]);
goto iterate;
}
}
contentValues.Add(k, formValues[k]);
iterate: ;
}
// return the two new Hashtables
}
private void SendMail(string recipient, string sender, string subject, string body)
{
// Construct the message.
MailMessage msg = new MailMessage();
// TODO: envelope from
msg.From = sender;
msg.To = recipient ;
msg.Subject = subject;
msg.Body = body;
SmtpMail.SmtpServer = this.SmtpRelay;
try
{
SmtpMail.Send(msg);
}
catch (Exception ex)
{
this.SetError(String.Format("Your submission could not be delivered: {0}", ex.Message));
return;
}
}
// Set the text of an error message and colorise it.
private void SetError(string errorMessage)
{
lbError.Text = errorMessage;
lbError.ForeColor = Color.Red;
}
</script>
<html xmlns="<head runat="server">
<title>Formmail.ASPX - Form Submission By Mail</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lbError" runat="server"></asp:Label> <br />
<asp:HyperLink ID="hlReturn" runat="server" EnableViewState="False" Visible="False">[hlReturn]</asp:HyperLink></div>
</form>
</body>
</html>
It all works fine (no script errors) but I don't get the email.
Does anyone else host with namesco or know what I might be doing wrong?