Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Email not sending

Status
Not open for further replies.

kevin197

Programmer
Mar 21, 2002
88
GB
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>&nbsp;<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?
 
if this works on a windows server(local?), but not a remote server and there are not errors then I would say the problem is the remote server's email configuration. or your code needs to provide a username/password for the remote server's email.

this can be done through the web.config so you don't need to re-compile your code. checkout for more assistance.


Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thats what I thought so I added the authentication to web.config but it still don't work :(
 
use ex.ToString(); instead of ex.Message. this will give you more details as to what the problem is.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thanks jmeckley, I changed that code but still don't get any errors. I just don't get the email :(
 
Well I've got my script working now, I changed the smtp server from smtp.hosts.co.uk to localhost and it worked straight away.

However, using localhost doesn't help when we try and send email from a application being built in asp.net to be run in the office.

I've been given this error by the programmer so wondered if any one can give me a clue on what might be causing it?

This is part of his email to me:

The problem I have is with the smtp server at smtp.hosts.co.uk.

I get the following error when I send an email.

System.Net.Mail.SmtpException: Failure sending mail. ---> System.FormatException: Invalid length for a Base-64 char array.
at System.Convert.FromBase64String(String s)
at System.Net.NTAuthentication.GetOutgoingBlob(String incomingBlob)
at System.Net.Mail.SmtpNtlmAuthenticationModule.Authenticate(String challenge, NetworkCredential credential, Object sessionCookie)
at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpClient.GetConnection()
at System.Net.Mail.SmtpClient.Send(MailMessage message)
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.Send(MailMessage message)

This error is being generated from WITHIN the .NET Framework. From googling the exception I think there is a problem with the message being returned from the smtp server.

If I send an email using my home email account - bt smtp server - I get no problems, sends mail everytime.



This error is NOT from running the code above, this is different code that I don't have but is still trying to email out using namesco's SMTP server.
 
I think I found the problem. you're hard coding the email server within the code.
// SMTP relay string SmtpRelay = "smtp.hosts.co.uk";
use the web.config file to configure the host/port/user/pwd.

Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Thanks jmeckley, but I already had all that in the web.config file too.

I've got it to work in the end by using localhost instead of smtp.hosts.co.uk
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top