DaniB
DaniB

Reputation: 191

ASP.net Razor - Sending email from a website using GMail SMTP

(FOR FINISHED RESULT GO TO EDIT/EDIT AT BOTTOM)

As the title states I am trying to send an email from a website using GMail SMTP as described in the ASP.net tutorial here: http://www.asp.net/web-pages/tutorials/email-and-search/11-adding-email-to-your-web-site.

After resolving an ISAPI.dll handler mapping error early on there are no more errors in the Webmatrix error console just success markers for the 'GET' and 'POST' actions; however, the web page is returning the try catch error, "the email was not sent...."

In SQL Server Manager I tried to see if the server and sa admin role are setup for mail but I can't see the agent properties, I understand as I have the Express edition of SQL Management Studio. That said, if there was an issue with the server role or mail settings an error message would surely be generated?

Can someone please be kind enough to take a quick look at the SMTP settings and overall code please for errors or suggestions?

(By the way, I have changed my email address and password in the example code. My email address was repeated for webmail.username and webmail.from)

Thanks.

Here is EmailRequest.cshtml

        @{

    }

    <!DOCTYPE html>
    <html>
    <head>
        <title>Request for Assistance</title>
    </head>
    <body>
      <h2>Submit Email Request for Assistance</h2>
      <form method="post" action="ProcessRequest.cshtml">
        <div>
            Your name:
            <input type="text" name="customerName" />
        </div>

        <div>
            Your email address:
            <input type="text" name="customerEmail" />
        </div>

        <div>
            Details about your problem: <br />
            <textarea name="customerRequest" cols="45" rows="4"></textarea>
        </div>

        <div>
            <input type="submit" value="Submit" />
        </div>
      </form>
    </body>
    </html>

**Here is ProcessRequest.cshtml**

        @{
        var customerName = Request["customerName"];
        var customerEmail = Request["customerEmail"]; 
        var customerRequest = Request["customerRequest"];
        var errorMessage = "true";
        var debuggingFlag = false;
        try {
            // Initialize WebMail helper
            WebMail.SmtpServer = "smtp.gmail.com";
            WebMail.EnableSsl = true;
            WebMail.SmtpPort = 465;
            WebMail.UserName = "MY EMAIL ADDRESS.com";
            WebMail.Password = "MYPASSWORD";
            WebMail.From = "MY EMAIL ADDRESS.com";

            // Send email
            WebMail.Send(to: customerEmail,
                subject: "Help request from - " + customerName,
                body: customerRequest
            );
        }
        catch (Exception ex ) {
            errorMessage = ex.Message;
        }
    }
    <!DOCTYPE html>
    <html>
    <head>
      <title>Request for Assistance</title>
    </head>
    <body>
      <p>Sorry to hear that you are having trouble, <b>@customerName</b>.</p>
        @if(errorMessage == ""){
          <p>An email message has been sent to our customer service
             department regarding the following problem:</p>
          <p><b>@customerRequest</b></p>
        }
        else{
            <p><b>The email was <em>not</em> sent.</b></p>
            <p>Please check that the code in the ProcessRequest page has 
               correct settings for the SMTP server name, a user name, 
               a password, and a "from" address.
            </p>
            if(debuggingFlag){
                <p>The following error was reported:</p>
                <p><em>@errorMessage</em></p>
            }
        }
    </body>
    </html>
____________________________________________________

EDIT:

Thanks for the help Mike and Gokhan. This morning I took another look in detail. Sure enough, two emails got send from the web page last night; therefore, at some point all the factors were correct.

I had tried ports 25, 465 and 587, but, I was following the tutorial and 'not the code'. The tutorial is a bit misleading in my opinion and caused confusion - I was looking for an email in the wrong inbox. One would think it usual for a problem report to be sent to the host and not the user reporting the problem.

Also, the try catch errors were still showing even though the email was being sent. Surely the error message should be activated by making an error. The error message seems to appear only if [var errorMessage = "true";] is set to true.

What am I missing? Can anyone please explain how this tutorial try catch method works?

Anyway, it's all working - I always find Mike's comments reassuring.

I got the code down to one page using another tutorial and added some form validation and then I amended the code so the email is sent to the host and not the user.

Here is the new EmailRequest.cshtml:

    @{

    Layout = "/_SiteLayout.cshtml";
    Page.Title = "Compare";

    Validation.RequireField("emailAddress", "customerName is required.");
    Validation.RequireField("emailSubject", "customerEmail is required.");
    Validation.RequireField("emailBody", "customerRequest is required."); 

        var message = "";
        var companyname = Request.Form["emailAddress"];
        var contactname = Request.Form["emailSubject"];
        var employeecount = Request.Form["emailBody"];


    try{
        if (IsPost && Validation.IsValid()) {

        // Send email
        WebMail.Send(to:"ADMIN-EMAIL-ADDRESS.COM",
            subject: Request.Form["emailSubject"],

            body: "Help request from -   " + Request.Form["customerName"] + " - " + "Email Subject -   " + Request.Form["emailSubject"]  + " - " + "Customer email -   " + Request.Form["emailAddress"]
           );
           message = "Email sent!";
        }
    }
    catch(Exception ex){
        message = "Email could not be sent!";
    }
}
<!DOCTYPE html>
<html lang="en">
  <head>
     <meta charset="utf-8" />
     <title>Test Email</title>

              <style type="text/css">
          .validation-summary-errors {font-weight:bold; color:red; font-size: 11pt;}
             .validation-summary-valid {
    display: none;
}

         </style>

  </head>
  <body>
    <h1>Test Email</h1>
    <form method="post">
        @Html.ValidationSummary("Errors with your submission:")

       <p>
        <label for="customerName">Name:</label>
        <input type="text" name="customerName" value="@Request.Form["customerName"]"  />


      </p>

      <p>
        <label for="emailAddress">Email address:</label>
        <input type="text" name="emailAddress" value="@Request.Form["emailAddress"]"  />


      </p>
      <p>
        <label for="emailSubject">Subject:</label>
        <input type="text" name="emailSubject" value="@Request.Form["emailSubject"]"  /> 

      </p>
      <p>
        <label for="emailBody">Text to send:</label><br/>
        <textarea name="emailBody" rows="6"></textarea>

      </p>
    <p><input type="submit" value="Send!" /></p>
    @if(IsPost){
        <p>@message</p>
    }
    </form>
  </body>
</html>

Finally, here is the _AppStart code to go with the example that I did not post yesterday:

    @{
        WebSecurity.InitializeDatabaseConnection("StarterSite", "UserProfile", "UserId", "Email", true);

        // WebMail.SmtpServer = "mailserver.example.com";
        // WebMail.UserName = "[email protected]";
        // WebMail.Password = "your-password";
        // WebMail.From = "[email protected]";
        // WebMail.EnableSsl = true; (add this if smtp is encrypted)
        // WebMail.SmtpPort = 587;
    }

EDIT/ EDIT

I was having trouble retaining data/value in the textarea box after submit as well as validating the textarea box. More research reminded me of the "required" attribute which in this case does both and also provides a neat tool tip.

Therefore, I have stripped out the previous code which retained the text box values and validated the form and used the "required" attribute instead - much neater.

Also, the processing code and success message is now built into the email request page so the ProcessRequest.cshtml page is no longer required.

Here is the finished code for a contact form that sends a request to a static email address - don't forget you need to use the _AppStart page code too, unless you add mail server authentication in the page - you don't need both. But, be advised it is not secure to add the server email settings in the page as users will be able to view them. I recommend using the _AppStart page as files that begin with an underscore in Asp.net Razor cannot be viewed online.

@{

    Layout = "/_SiteLayout.cshtml";
    Page.Title = "Compare";

    var message = "";
    var companyname = Request.Form["emailAddress"];
    var contactname = Request.Form["emailSubject"];
    var employeecount = Request.Form["emailBody"];


    try{
        if (IsPost && Validation.IsValid()) {

        // Send email
        WebMail.Send(to:"ADMIN EMAIL.COM",
            subject: Request.Form["emailSubject"],

            body: "Help request from -   " + Request.Form["customerName"] + " - " + "Email Subject -   " + Request.Form["emailSubject"]  + " - " + "Customer email -   " + Request.Form["emailAddress"]
           );
           message = "Email sent!";
        }
    }
    catch(Exception ex){
        message = "Email could not be sent!";
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
    <title>Test Email</title>


</head>

  <body>
    <h1>Test Email</h1>

    <form method="post">

       <p>
        <label for="customerName">Name:</label>
        <input type="text" name="customerName"  required />
       </p>

      <p>
        <label for="emailAddress">Email address:</label>
        <input type="text" name="emailAddress" required />
      </p>
      <p>
        <label for="emailSubject">Subject:</label>
        <input type="text" name="emailSubject" required /> 

      </p>

      <p>
        <label for="emailBody">Text to send:</label><br/>
        <textarea name="emailBody" rows="6" required></textarea>
       </p>

    <p><input type="submit" value="Send!" /></p>
    @if(IsPost){
        <p>@message</p>
    }
    </form>
  </body>
</html>  

Upvotes: 2

Views: 10171

Answers (2)

Ehsan Mirsaeedi
Ehsan Mirsaeedi

Reputation: 7592

If you want to rich the email bodies with razor, you can use Mailzory. Also, you can download the nuget package from here. The usage is simple:

// template path
var viewPath = Path.Combine("Views/Emails", "hello.cshtml");
// read the content of template and pass it to the Email constructor
var template = File.ReadAllText(viewPath);

var email = new Email(template);

// set ViewBag properties
email.ViewBag.Name = "Johnny";
email.ViewBag.Content = "Mailzory Is Funny";

// send email
var task = email.SendAsync("[email protected]", "subject");
task.Wait()

Upvotes: 0

G&#246;khan Girgin
G&#246;khan Girgin

Reputation: 1164

I've written the code for a project long time before. Try this.

public void SendEmail(string from, string to, string subject, string body)
{
    string host = "smtp.gmail.com";
    int port = 587;

    MailMessage msg = new MailMessage(from, to, subject, body);
    SmtpClient smtp = new SmtpClient(host, port);

    string username = "[email protected]";
    string password = "1234567890";

    smtp.Credentials = new NetworkCredential(username, password);
    smtp.EnableSsl = true;
    smtp.UseDefaultCredentials = false;

    try
    {    
        smtp.Send(msg);
    }
    catch (Exception exp)
    {
        //Log if any errors occur
    }
}

Upvotes: 3

Related Questions