Sending Mail from a .NET App Using Amazon SES (Simple Email Service)

Amazon’s Simple Email Service (SES) is a great solution for any project which requires bulk emails. the primary advantage of SES is cost, at $0.10 per 1000 emails sent it is between 5-10x cheaper than other alternatives such as SendGrid. There is a downside to the SES service, however and it is that it currently doesn’t provide an SMTP wrapper so whilst SendGrid and others allow you to simple change your SMTP settings, with SES you will have to do a bit more work.

Amazon (AWS) provides a very useful .NET SDK (complete with dll’s for .NET 2.0, 3.5 and 4.0) which you can simply copy into your project and start calling the Amazon functions from a .NET app such as an ASP.NET site. You can download the SDK here.

The below code shows a simple example of how to use the Amazon AWS SDK in .NET to send emails.

Dim listColl As New System.Collections.Generic.List(Of String)
'//TODO - Write a simple loop to add the recipents email addresses to the listColl object.

Dim client As New Amazon.SimpleEmail.AmazonSimpleEmailServiceClient("aws_public_key_here", "aws_private_key_here")

Dim mailObj As New SendEmailRequest
Dim destinationObj As New Destination(listColl)
mailObj.Source = "from@youremail.com"  '//The from email address
mailObj.ReturnPath = "bounce@youremail.com" '//The email address for bounces
mailObj.Destination = destinationObj

'//Create Message
Dim emailSubjectObj As New Amazon.SimpleEmail.Model.Content("This is the Subject")
Dim emailBodyContentObj As New Amazon.SimpleEmail.Model.Content("This is the Body<br /><em>In Html</em>")

Dim emailBodyObj As New Amazon.SimpleEmail.Model.Body()
emailBodyObj.Html = emailBodyContentObj
Dim emailMessageObj As New Message(emailSubjectObj, emailBodyObj)
mailObj.Message = emailMessageObj

Dim response = client.SendEmail(mailObj)

That’s it, there’s really not a lot of heavy lifting to get starting using SES with .NET. the only thing I didn’t show in the code above is the loop for adding email addresses as strings to the generic collection, this loop will vary a lot depending on your exact requirements.
One thing to note above is that you will need to import the namespace Amazon.SimpleEmail.Model

AWS SES is not as full featured as a lot of solutions such as SendGrid, however it does have several useful features out-of-the-box such as the ability to perform email validation:

Dim testEmail As String = "anemail@domain.com"

Dim verRequest As New VerifyEmailAddressRequest()
verRequest.EmailAddress = testEmail
client.VerifyEmailAddress(verRequest)

This should get you going with SES, I will update this page once the service develops.

Filling a Grid with Files in a Folder – C#

This code sample shows, in C#, how to get all the files within a specific folder, and list them all, including the file size, in a Gridview control.

To access the FileSystem, you’ll need to import the System.IO namespace, and to use a DataTable, you must import the System.Data namespace:
using System.IO;
using System.Data;

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Web.UI" %>
<%@ Import Namespace="System.Web.UI.WebControls" %>
<%@ Import Namespace="System.IO" %>
<html>
	<head>
		<meta name="generator" Content="ASP Express 5.1">
		<title>Untitled</title>
<script language="C#" Runat="server">
// declare the page level variable for the path
		String FilePath;
        protected void Page_Load(object sender, EventArgs e)
        {
            FilePath=Server.MapPath("~/Files");
            GetFiles();  //call the GetFiles method
            lblHeader.Text = "Files in " + FilePath;
        }
        private void GetFiles()
          {
            //Create the DataTable, with columns in which to add the file list
            DataTable dt=new DataTable();
            dt.Columns.Add("FileName",typeof(System.String));
            dt.Columns.Add("Size",typeof(System.String));
            DataRow dr=null;
            DirectoryInfo dir=new DirectoryInfo(FilePath);

            // Iterate through the datatable,
			// adding file to a new row, along with the  filesize to each row
            foreach (FileInfo fi in dir.GetFiles())
            {
                dr=dt.NewRow();
                dr[0] =  fi.Name.ToString();
                dr[1] = fi.Length.ToString("N0");  //'N0'formats the number with commas
                dt.Rows.Add(dr);
            }
            // Bind DataTable to GridView - voila!
            grdFiles.DataSource = dt;
            grdFiles.DataBind();
        }

</script>
</head>
	<body>
		<form id="form1" Runat="server">
	    <div style="text-align:center">
	        <asp:Label ID="lblHeader" runat="server"></asp:Label>
	        <asp:GridView ID="grdFiles" runat="server">
	            </asp:GridView>
	    </div>
		</form>
	</body>
</html>

Displaying an Image with a DataList

Sometimes, with a Datalist, it would be nice to actually display an image as one of the Data items. This sample uses a simple Access DataSource ID to do so

<asp:AccessDataSource ID="AccDS1"
Runat="Server"
SelectCommand = "SELECT  id, ProdName, ImgPath, Comments From  Products"
DataFile="\YourPath\products.mdb">
</asp:AccessDataSource>
<asp:DataList id="MyDataList" Runat="Server" DataSourceID="accDS1">
<HeaderTemplate>
<table border="1">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td colspan="2">
<font color="#000000">
<b>ProdName : </b>
<%# Container.DataItem("ProdName")%>
</td>
</tr>
<tr>
<td align="Left" valign="Top">
<b>Comments: </b>
<br>
<%# Container.DataItem("Comments")%></td>
<td align="Left" valign="Top">
<asp:Image Runat="server" ID="myImage"
ImageUrl=''<%# Container.DataItem("ImgPath")%>''>
</asp:Image>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>

List and Read Text Files

This sample takes files from a folder (in this situation, text files), and lists them in a listbox. Then, the user can click on a particular file, and display the text from the selected text file, in the textbox to the right of the listbox.

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
Dim strFilePath As String
Dim objFileWriter As StreamWriter
Dim objStreamReader As StreamReader
Dim sContents As String = ""
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim strEntries() As String
Dim f As String
Dim FileName As String
strFilePath = Server.MapPath("/Yourpath/TextFiles/")
strEntries = Directory.GetFiles(strFilePath)

If Not Page.IsPostBack Then
For Each f In strEntries
FileName = Path.GetFileName(f)
lstFiles.Items.Add(FileName)
Next
End If
End Sub

Protected Sub lstFiles_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
ReadFile()
End Sub

Sub ReadFile()
objStreamReader = File.OpenText(strFilePath & _
lstFiles.SelectedItem.Value)
Dim contents As String = objStreamReader.ReadToEnd()
txtContent.Text = contents
objStreamReader.Close()
End Sub
</script>

<html>
<head runat="server">
<title>List and Show Text From Text Files</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<tr>
<td>
<asp:ListBox ID="lstFiles" AutoPostBack="true" runat="server"
Height="150px" Width="93px"
OnSelectedIndexChanged="lstFiles_SelectedIndexChanged" />
</td>
<td>
<asp:Label ID="Label1" runat="server"></asp:Label><br />
<asp:TextBox ID="txtContent" TextMode="MultiLine"
runat="server" Height="115px" Width="374px"></asp:TextBox>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>

					

Visible Panels via RadioButtonList

This is a sample which shows how to, by choosing items in a RadioButtonList, you can show (make visible/invisible) only certain panels.

<script language="VB" Runat="server">
	Sub GetPanel(Source as Object, E as EventArgs)
		Select Case rb1.selectedItem.Value
			Case 1
				pnl1.visible=True
				pnl2.visible=False
				pnl3.visible=False
			Case 2
				pnl1.visible=False
				pnl2.visible=True
				pnl3.visible=False
			Case 3
				pnl1.visible=False
				pnl2.visible=False
				pnl3.visible=True
		End Select
	End Sub
</script>
<html>
	<head>
		<meta name="GENERATOR" Content="ASP Express 5.0">
		<title>RadioButtonList - Panels</title>
	</head>
	<body>
		<form id="form1" Runat="server">
			<asp:RadioButtonList ID="rb1" Runat="Server"
				OnSelectedIndexChanged="GetPanel"
				AutoPostBack="True">
				<asp:ListItem Value="1">Panel 1</asp:ListItem>
				<asp:ListItem Value="2">Panel 2</asp:ListItem>
				<asp:ListItem Value="3">Panel 3</asp:ListItem>
			</asp:RadioButtonList>
			<asp:panel ID="pnl1" Runat="server" Visible="False">
			This is panel 1
			</asp:panel>

			<asp:panel ID="pnl2" Runat="server" Visible="False">
			This is panel 2
			</asp:panel>

			<asp:panel ID="pnl3" Runat="server" Visible="False">
			this is panel 3
			</asp:panel>
		</form>
	</body>
</html>

Mass Delete Using Gridview with Checkboxes

This sample shows how to use a Gridview to delete multiple records all at once, having marked them with a Checkbox, and clicking one button, external to the Gridview, to delete them all

As usual, here, we’re using the Northwind Database. If you want to try this on your own Northwind database, adhere to this word of caution – “BACK IT UP FIRST”. You will be making multiple deletes, so in order to get it back to the original state, you must make a backup and then restore afterwards.

Remember too, that you will need to substitute your own Web.Config connectionstring entry for “YourNorthwindString” in the sample code

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SQLClient" %>
<%@ Page Language="VB" %>

<script language="VB" Runat="server">
Dim ConnString as String
Sub Page_Load(Source as Object, E as EventArgs)
ConnString=ConfigurationManager.ConnectionStrings("YourNorthwindString").ConnectionString
if not page.IsPostBack then
BindGrid
end if
End Sub

Sub DeleteRecord(intProd as Integer)
Dim Conn As New SqlConnection(ConnString)
Dim cmd As New SqlCommand("Delete from Products where productID=@ProductID", Conn)
cmd.Parameters.Add(New SqlParameter("@ProductID", intProd))
Conn.Open()
cmd.ExecuteNonQuery()
Conn.Close
End Sub

Sub DoDelete()
Dim i As Integer
For i = 0 To gvProducts.Rows.Count – 1
Dim dgItem As GridViewRow = gvProducts.Rows(i)
Dim lblid As Label = CType(dgItem.FindControl("lblid"), Label)
Dim cb As CheckBox = CType(dgItem.FindControl("chk1"), CheckBox)
If cb.Checked Then
DeleteRecord(CInt(lblid.Text))
End If
Next i
BindGrid()
End Sub

Sub BindGrid()
Dim Conn As New SqlConnection(ConnString)
Dim dr as SqlDataReader
Dim mySQL as String
mySQL="SELECT Top 10 [ProductID], [ProductName], [QuantityPerUnit], " & _
"[UnitPrice] FROM [Products]"
Dim cmd As New SqlCommand(mySQL, Conn)
Conn.Open()
dr=cmd.ExecuteReader
gvProducts.DataSource=dr
gvProducts.DataBind
Conn.Close
End Sub

Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs)
DoDelete()
End Sub
</script>

<head runat="server">
<title>Mass Deletes Using a Gridview with Checkboxes</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID">
<Columns>
<asp:TemplateField HeaderText="Mark for Delete">
<ItemTemplate>
<asp:CheckBox ID="chk1" runat="server" Checked="False" />
<asp:Label ID="lblID" Visible="True" runat="server" Text=”<%# Bind("ProductID") %>”></asp:Label>
</ItemTemplate>
</asp:TemplateField>

<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" HtmlEncode="False" DataFormatString="{0:C}" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:Button ID="btnDelete" runat="server" Text="Delete Checked" OnClick="btnDelete_Click" />
</form>
</body>
</html>

Databound Accordian Control

This sample shows how to bind data to an AJAX Accordian control, using the AJAX Control Toolkit. The first thing you will need to do, is to download it from the AJax.ASP.Net website.

Then, once it’s downloaded and installed, go to the Bin folder, where it’s located, find the AjaxcontrolToolkit.dll and copy it to the Bin folder of your website.

Once it’s there, you’re off to the races. Note the ‘Register’ statement at the top of the code here, and then, look at the different properties in the control itself. When databinding the Accordian control, you will use the HeaderTemplate and ContentTemplate tags, instead of the normal Header and Content pane tags.

Add a little CSS for flavor (see the ContentCssClass property of the Accordian control, and the DIV class for the header), and we’re good to go.

<%@ Page Language="VB" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<html>
<head>
<meta name="GENERATOR" Content="ASP Express 5.0">
<title>Databound Accordian Control</title>
<style type="text/css">
<!--
.collapsePanel
{
height:0px;
background-color:#FAFAD2;
overflow:hidden;
border-left:dotted 1px Silver;
padding:5px;
padding-top:10px;
border-right:2px solid silver;
border-bottom:2px solid silver;
z-index:0;
}
.collapsePanelHeader
{
border-right:2px solid silver;
border-bottom:2px solid silver;
color:white;
background-color:#6687BD;
overflow:hidden;
font-weight:bold;
cursor:pointer;
margin-top:5px;
padding:5px;
}
-->
</style>
</head>
<body>
<form id="form1" Runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="
<%$ ConnectionStrings:myConnectionString %>"
SelectCommand="SELECT [Field1], [Field2] FROM [MyTable]">
</asp:SqlDataSource>
<table width="100%">
<tr>
<td align="left">
<cc1:Accordion ID="Accordion2"
ContentCssClass="collapsePanel"
runat="server" SelectedIndex="0"
DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table>
<tr>
<td>
<div class="collapsePanelHeader">
<asp:Label ID="TitleLabel" runat="server"
Text=''<%# Eval("Title") %>''>
</asp:Label>
</div>
</td>
</tr>
</table>
</HeaderTemplate>
<ContentTemplate>
<asp:Label ID="TipLabel" runat="server"
Text=''<%# Eval("Tip") %>''>
</asp:Label>
<br />
</ContentTemplate>
</cc1:Accordion>
</td>
</tr>
</table>
</form>
</body>
</html>

HTML Named Colors + Hex Using Reflection

This sample actually shows several things, like how to add controls to a page/Placeholder, dynamically, how to get a color from RGB, convert a color to Hex, plus (the main point) it shows how, using reflection, you can iterate through the system colors and display them (using dynamic labels), plus get the HTML hex for each color.

<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>

<script language="VB" Runat="server">
	Sub Page_Load(Source as Object, E as EventArgs)
        Dim t As Type = GetType(Color)
        For Each fi As PropertyInfo In t.GetProperties
            If (fi.PropertyType.ToString = "System.Drawing.Color") Then
                Dim colorName As String = fi.Name
                Dim lbl As Label = New Label
                Dim lit As LiteralControl = New LiteralControl
                Dim c As Color = System.Drawing.Color.FromName(colorName)
                lit.Text = ("&nbsp; " + colorName + " (" & GetHexColor(c) & ")")
                lbl.BackColor = c
                lbl.Width = Unit.Pixel(125)
                lbl.Height = Unit.Pixel(20)
                lbl.BorderColor=Color.FromArgb(&H78E0E0E0)
                lbl.BorderWidth = Unit.Pixel(1)
                phl.Controls.Add(lbl)
                phl.Controls.Add(New LiteralControl(" "))
                phl.Controls.Add(lit)
                phl.Controls.Add(New LiteralControl("<br />"))
            End If
        Next
    End Sub

    Function GetHexColor(colorObj as Color) as String
		return "#" & CheckZero(Hex(colorObj.R)) & CheckZero(Hex(colorObj.G)) & CheckZero(Hex(colorObj.B))
	End function

	Function CheckZero(sNum as String) as String

		if sNum="0" then
			return "00"
		else
			return sNum
		End If

	End Function
</script>
<html>
	<head>
		<meta name="GENERATOR" Content="ASP Express 5.0">
		<title>System Colors Using Reflection</title>
	</head>
	<body>
		<form id="form1" Runat="server">
			<asp:PlaceHolder ID="phl" runat="server"></asp:PlaceHolder>
		</form>
	</body>
</html>

Gridview – Conditional Images

This Gridview sample shows how to, for each row, based on other data within that row, to show a different image. We do this by creating a TemplateField, and putting an ASP.Net Image control within it, called ‘Image1′.

Then, inside the RowDataBound event of the Gridview, we put code, which first, checks and finds the Image control in that row, and then assigning a different JPG file to the ImageURL property of that image. One other thing here, you’ll notice, is that when the criteria is matched, we set the Image control’s Visible property to ‘True’. That’s because, one extra criteria is, that if the Units In Stock is larger than 80, we set the Image control’s Visible property to ‘False’.

Naturally, since we’re checking one particular column in the Gridview for this data, we’re using a Select Case statement.

<script language="VB" Runat="server">
Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim img As Image = CType(e.Row.FindControl("image1"), Image)
Select Case cInt(e.Row.Cells(3).Text)
Case 0
img.ImageUrl = "/images/red.jpg"
img.Visible=True
Case 1 to 25
img.ImageUrl = "/images/yellow.jpg"
img.Visible=True
Case 26 to 80
img.ImageUrl = "/images/green.jpg"
img.Visible=True
Case > 80
img.Visible=False
End Select
End If
End Sub
</script>
<html>
<head>
<meta name="GENERATOR" Content="ASP Express 5.0">
<title>Conditional Gridview Images</title>
</head>
<body>
<form id="form1" Runat="server">
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ds1" AllowPaging="True" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Image ID="Image1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False"
ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" HtmlEncode="False"
HeaderText="UnitPrice" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="ds1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [ProductID], [ProductName], [UnitsInStock], [UnitPrice] FROM [Products]">
</asp:SqlDataSource>
</form>
</body>
</html>

Conditional Gridview Text – Checkboxes

This code sample shows how to either show or make invisible, a checkbox in each row of the Gridview, along with making text conditional, based on certain criteria. In this case, if the Postal code starts with a non-numeric character, we change it to “Alt Text”, and we set the Visible property of the checkbox in that row to “False”

<%@ Import Namespace=”System.Drawing” %>
<script language=”VB” Runat=”server”>
Sub doDataCheck(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
Dim chkExp as CheckBox
If e.Row.RowType = DataControlRowType.DataRow Then
Dim sCode as String=e.Row.Cells(7).text
If Not isNumeric(sCode.Substring(1,1)) Then
e.Row.Cells(7).text=”<i style=’color:red’>(Alt Text)</i>”
chkExp= CType(e.row.FindControl(“ck1″), Checkbox)
chkExp.Visible=”False”
End If
End If
End Sub
</script>
<html>
<head runat=”server”>
<meta name=”GENERATOR” Content=”ASP Express 4.5″>
<title>Conditional GridView Cell Coloring</title>
</head>
<body>
<form id=”form1″ Runat=”server”>
<asp:GridView OnRowDataBound=”doDataCheck” AutoGenerateColumns=”False”
DataSourceID=”SqlDataSource1″ ID=”GridView2″ runat=”Server”>
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID=”ck1″ runat=”server”></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField=”FirstName” HeaderText=”First” />
<asp:BoundField DataField=”LastName” HeaderText=”Last” />
<asp:BoundField DataField=”Title” HeaderText=”Title” />
<asp:BoundField DataField=”Address” HeaderText=”Address” />
<asp:BoundField DataField=”City” HeaderText=”City” />
<asp:BoundField DataField=”Region” HeaderText=”Region” />
<asp:BoundField DataField=”PostalCode” HeaderText=”PostalCode” />
<asp:BoundField DataField=”country” HeaderText=”country” />
</Columns>
<HeaderStyle BackColor=”Blue” Font-Bold=”True” ForeColor=”White” />
</asp:GridView>
<asp:SqlDataSource ID=”SqlDataSource1″ runat=”server” ConnectionString=”<%$ ConnectionStrings:NorthwindConnectionString %>”
SelectCommand=”Select FirstName, LastName, Title, Address, City, Region, PostalCode, country from Employees”>
</asp:SqlDataSource>
</form>
</body>
</html>