Solution Explorer Recently I had to send an email blast out to about two thousand email subscribers from a client's ASP.NET Web Forms application. The client had an admin form where they would compose and send out the email. Unfortunately, with that many emails the Web form would inevitably hang. Plus, with Exchange Server there is no easy way to know how many emails actually got sent; you could use Powershell to determine this or you could log it but it still isn't a robust way of doing things.

The conventional wisdom is to use a third party service for mass mailings and most times this is probably your best option. In this situation, an email blast is only sent every 5 years so it really didn't make sense to enrol in a monthly plan. With a little due diligence, this can be accomplished with a very simple console application which can be called from the Web form to dispatch the emails.

The basic design is that the subject line and email body text are entered in the form and passed to the console application as string parameters. In the console app, we can obtain the email addresses from a database and send the emails out in batches with a pause between each batch.

Some basics first: the entry point to any console application is the Main method:

// Mailer class in console application

static void Main(string[] args)
{
    if (args.Length >= 2)
    {
        SmtpClient smtpClient = new SmtpClient(EMAIL_HOST);
        smtpClient.Host = "localhost";

        MailMessage message = new MailMessage();
        message.Priority = MailPriority.High;
        message.Subject = args[0];
        message.Body = args[1];
        smtpClient.Send(FROM_ADDRESS, TO_ADDRESS, message.Subject, message.Body);
    }
}

The array of strings args parameter corresponds directly to the command line parameters passed to the console application; string[0] is the first parameter, strg[1] is the second parameter and so on. This is different in C and C++, where the name of the console application itself is the first parameter... when in doubt, try it out!

Note that when testing this on the command line initially, that there is a limitation on the size of the strings you can pass. This will not apply when sending the parameters programmatically from the Web form code-behind. You can test that your console app is sending emails by creating a drop folder on your C drive. Download and install Live Mail to view the .eml files generated. You can create a dummy gmail account to get this running and choose not to make Live Mail your default email client during the install (if this is your preference). This is a really simple and useful way to test email functionality locally on your dev machine. Just update your Web.Config file with the following to get it working:

<system.net>
    <mailSettings>
        <smtp deliveryMethod="SpecifiedPickupDirectory">
            <specifiedPickupDirectory pickupDirectoryLocation="c:\maildrop" />
        </smtp>
    </mailSettings>
</system.net>

To generate a test email with the console app and pass the subject and body parameters, call it like this:

// DOS command line

C:\>ConsoleApplication1 "Subject Line Text" "Some body text"

To call the console app from the Web form code-behind we use the Process.Start method. We can avail of the ProcessStartInfo class to set up any properties in advance of making the process call.

// Web form code-behind
// Pass subject and message strings as params to console app

ProcessStartInfo info = new ProcessStartInfo();

string arguments = String.Format(@"""{0}"" ""{1}""",
     subjectText.Text.Replace(@"""", @""""""),
     messageText.Text.Replace(@"""", @""""""));
info.FileName = MAILER_FILEPATH;
info.Arguments = arguments;
Process.Start(info);

We also need to take account of the possibility of quotes being included in the subject line or body text. I enlisted some help on this issue with a StackOverflow question. The solution was a combination of composite string formatting and verbatim "@" string literals. See the String.Format call in the code snippet above.

 

Email Form

If you've been testing the console app and then go on to debugging with VS, you may come up against a file locking issue. This issue is a known bug - I've seen bug reports going back to 2006 on this one.

Error 9 Unable to copy file "obj\x86\Debug\ConsoleApplication1.exe" to "bin \Debug\ConsoleApplication1.exe". The process cannot access the file 'bin\Debug\ConsoleApplication1.exe' because it is being used by another process.

 

Processes

There are two workarounds to this. My way is to close out VS and then kill any remaining processes for the console app: Windows Task Manager -> Processes tab -> Show processes from all users -> right- click each process and kill it (End Process). The second method is to add a pre-build script as described here.

Tags: , ,

ASP.NET | C#



ASP.NET Programming Tips - Tip #1

by agrace 26. September 2010 09:20

Google Cannot Solve your Coding Problems

Using GoogleStop and think before you do this. Googling for code samples is usually the final step when designing solutions. Start by defining the problem; if you can't define the problem, how can you solve it? Then, and only then, start working on a black-box solution of your own; identify the basic inputs, general logic (phrase it in a single sentence - this is the black box), and outputs of this black box. Even if you're not artistically inclined, always opt to take pencil to paper - it will help.

Finally, with a clearer perception of what it is you need to do, use Google to focus in on relevant code samples. Doing this in reverse order leads us to try and re-imagine the problem to fit somebody else's solution. I imagine 80/90% of programmers, myself included, are guilty of this everyday form of insanity.

kick it on DotNetKicks.com



ASP.NET Security Alert

by admin 19. September 2010 10:02

ASP.NET Security AlertEarlier this week, on the lead up to the ekoparty Security Conference in Argentina, a pair of security researchers announced that they would demonstrate an attack to exploit the way that ASP.NET handles encrypted session cookies.

I first learned of this on Wednesday, when someone posted a question on Stack Overflow. Since then, Microsoft have issued a security alert and Scott Guthrie has put out a blog post giving a full explanation of how this works and how it may affect you. Scott's post includes a link to a script you can run on your servers to identify vulnerable sites. In short, you need to have a <customErrors> section in your Web.Config file and map all errors to a single error page.

As reported here, the attack is 100% reliable; any ASP.NET website can be "owned" in seconds. The longest it takes is less than 50 minutes. Confirm with your bank that this has been remedied before logging into your account (ASP.NET sites)!

Update to Security Advisory 2416728 (09-20-2010)

FAQ about the ASP.NET Security Vulnerability - Scott Guthrie (09-21-2010)

Update on ASP.NET Vulnerability - Scott Guthrie (09-24-2010)

ASP.NET Security Update Shipping Sept 28th - Scott Guthrie (09-27-2010)

Microsoft Security Bulletin MS10-070 (09-28-2010)

ASP.NET Security Fix Now on Windows Updates - Scott Guthrie (09-30-2010)