AspEmail.NET Manual Chapter 2: Advanced Features

Contents

2.1 Unicode

2.1.1 Quoted-Printable Format

AspEmail.NET is capable of sending messages in alphabets other than US-ASCII by supporting the "Quoted-Printable" format. This format is described in RFC-2045. The idea of the format is that characters with codes less than 33 and greater than 126 are represented by an "=" followed by a two digit hexadecimal representation of the character's value. For example, the decimal value 12 (US-ASCII form feed) is represented as =0C, and the decimal value 61 (US-ASCII "=") can be represented as =3D.

AspEmail.NET encodes the message body in the Quoted-Printable format automatically if the ContentTransferEncoding property is set to the string "Quoted-Printable".

objMail.ContentTransferEncoding = "Quoted-Printable";
objMail.ContentTransferEncoding = "Quoted-Printable"

The ContentTransferEncoding property is a premium feature.

2.1.2 UTF-8 Encoding

UTF-8 (Unicode Transformation Format, 8-bit encoding form) is the recommended format to be used to send Unicode text over the Web and email. UTF-8 represents a Unicode value as a sequence of 1, 2, or 3 bytes. UTF-8 is compatible with ASCII format.

AspEmail.NET offers full UTF-8 support in both a message body and headers. To send a UTF-8 encoded message, you must set the CharSet property to the string "UTF-8" (case is immaterial), and ContentTransferEncoding to "Quoted-Printable". The following code snippet sends a message with the body in Russian:

objMail.ContentTransferEncoding = "Quoted-Printable";
objMail.CharSet = "UTF-8";
objMail.Body = "Сообщение по-русски";
objMail.ContentTransferEncoding = "Quoted-Printable"
objMail.CharSet = "UTF-8"
objMail.Body = "Сообщение по-русски"

The CharSet property is a premium feature.

2.1.3 Header Encoding

If you wish to send a message with certain mail headers such as Subject:, To: or From: containing non-US-ASCII characters, you should use the method EncodeHeader to encode your character string. The main version of the EncodeHeader method takes a single parameter, the header string. The overloaded version of the method also takes a 2nd parameter, the character set, which is "ISO-8859-1" by default.

The following code snippet specifies a message Subject in Russian, UTF-8 encoded:

objMail.Subject = objMail.EncodeHeader("Тема По-русски", "UTF-8");
objMail.Subject = objMail.EncodeHeader("Тема По-русски", "UTF-8")

The EncodeHeader method should also be used if you need to include Emojis in your message subject. Emojis are characters outside the standard 0000-FFFF Unicode range. They need to be encoded with two 16-bit numbers as shown in the right column of the table below:

Icon
Code Point (Hex)
Encoding (Hex)
😂
1F602
D83D DE02
🌹
1F339
D83C DF39

These two numbers are referred to as high surrogate code point and low surrogate code point. The formulas to convert the Emoji's code point to its high and low surrogates are as follows:

hi = (cp - 0x10000) / 0x400 + 0xD800
lo = (cp - 0x10000) % 0x400 + 0xDC00

The following code snippet includes the two Emojis above in a message subject:

objMail.Subject = objMail.EncodeHeader( _
   "Emoji Test: \uD83D\uDE02\uD83C\uDF39", "utf-8");
objMail.Subject = objMail.EncodeHeader("Emoji Test: " + ChrW(&HD83D) +
   ChrW(&HDE02) + ChrW(&HD83C) + ChrW(&HDF39), "utf-8")

2.1.4 Other Character Set Values

The string "UTF-8" is not the only valid value for the CharSet property and the second parameter to the EncodeHeader method. Other values include "Windows-1250", "Windows-1251", "shift_jis", "chinese", and others. Below is the complete list of valid CharSet values:

Value Meaning
"UTF-8" UTF-8
"UTF-7" UTF-7
"Windows-1250"
"cp1250"
ANSI - Central Europe
"Windows-1251"
"cp1251"
ANSI - Cyrillic
"Windows-1252"
"cp1252"
"ascii"
"us-ascii"
Latin I
"Windows-1253"
"cp1253"
ANSI - Greek
"Windows-1254"
"cp1254"
ANSI - Turkish
"Windows-1255"
"cp1255"
ANSI - Hebrew
"Windows-1256"
"cp1256"
ANSI - Arabic
"Windows-1257"
"cp1257"
ANSI - Baltic
"Windows-1258"
"cp1258"
ANSI - Vietnamese
"ISO-8859-1" Latin I (default value)
"ISO-8859-2" Central Europe
"ISO-8859-3" Latin 3
"ISO-8859-4" Baltic
"ISO-8859-5" Cyrillic
"ISO-8859-6" Arabic
"ISO-8859-7" Greek
"ISO-8859-8" Hebrew
"ISO-8859-9" Latin 5
"ISO-8859-15" Latin 9
"cp866" Russian DOS
"koi8-r" Russian
"koi8-u" Ukrainian
"shift_jis" Japanese Windows
"ks_c_5601-1987"
"korean"
Korean
"EUC-KR"
"korean"
EUC - Korean
"BIG5" Traditional Chinese Windows
"GB2312"
"chinese"
Simplified Chinese
"HZ-GB-2312" Simplified Chinese HZ
"EUC-JP" EUC - Japanese
"X-EUC-TW" EUC - Traditional Chinese

2.1.5 Code Sample

The following code sample is very similar to the one provided in Chapter 1 of this manual except it uses the CharSet and ContentTransferEncoding properties and EncodeHeader method. The rest of the script is not shown here for brevity.

...
// Unicode support
objMail.ContentTransferEncoding = "Quoted-Printable";
objMail.CharSet = "UTF-8";

// Subject
objMail.Subject = objMail.EncodeHeader(txtSubject.Text, "UTF-8");
...
...
' Unicode support
objMail.ContentTransferEncoding = "Quoted-Printable"
objMail.CharSet = "UTF-8"

' Subject
objMail.Subject = objMail.EncodeHeader(txtSubject.Text, "UTF-8")
...

Click the links below to run this code sample:

2.2 Embedded Images

2.2.1 Why Use Embedded Images?

Commercial e-mail messages often contain images, graphics and other design elements. When a message is sent in the HTML format, images used in the message body can be either linked or embedded. Linked images are not part of the message itself. They are usually hosted by the message sender and referenced in the message body via an <IMG> tag pointing to the sender's server, as follows:

<IMG SRC="http://www.sender-company.com/images/flower.jpg">

The main advantage of linked images is that the message body remains small. The main disadvantage is that most email clients these days block linked images for security purposes and the message appears broken to the viewer.

Unlike linked images, embedded images are part of the message itself. They are similar to regular attachments, although they use the multipart/related format, as opposed to multipart/mixed. An embedded image is also referenced in a message body using an <IMG> tag, but instead of a URL, an image identifier, or Content ID, is used, as follows:

<IMG SRC="cid:My-Image-Identifier">

Messages with embedded images are usually not tempered with by the email client, can be viewed off-line and remain intact over time, as the images are permanently attached to the body. A message may contain regular attachments and embedded images at the same time.

2.2.2 AspEmail.NET's Support for Embedded Images

AspEmail.NET offers support for embedded images via the method AddEmbeddedImage which takes two arguments: the physical path to an image file, and its Content ID, which is simply an arbitrary string without spaces. If your message contains multiple embedded images, each must be assigned a unique Content ID. The following example uses the file margin.gif as the background image for a message (note that here we use the BACKGROUND attribute of the <BODY> tag instead of <IMG>):

objMail.Body="<HTML><BODY BACKGROUND=\"cid:My-Image\">...</HTML>";
objMail.AddEmbeddedImage( @"c:\path\margin.gif", "My-Image" );
objMail.Body="<HTML><BODY BACKGROUND=""cid:My-Image"">...</HTML>"
objMail.AddEmbeddedImage( "c:\path\margin.gif", "My-Image" )

Note: Content-IDs are case-sensitive. Make sure the values specified by "cid:..." and AddEmbeddedImage fully match.

Like AddAttachment, the AddEmbeddedImage method has an overloaded "memory" version which allows you to embed an image coming from memory (such as a database blob) as opposed to disk. This method expects three arguments: the filename (without a path), Content ID and memory array of bytes containing the image:

byte [] arrBytes;
...
objMail.AddEmbeddedImage( "myimage.jpg", "My-Image", arrBytes );
Dim arrBytes() As Byte
...
objMail.AddEmbeddedImage( "myimage.jpg", "My-Image", arrBytes )

2.2.3 Code Sample

The following code sample sends a message containing two embedded images, one used for the body margin and the other embedded in the message body. The body text is read from a text file via the method AppendBodyFromFile described in the previous chapter.

The body text file MessageBody.htm looks as follows:

<html>
<head>
<style>

body
{
   color: #427d64;
   font-family: "Arial";
   font-size: 12pt;
   margin-left: 8em
}

</style>
</head>

<body background="cid:My-Background-Image">
<center>

<h2>Thank-you for Shopping At Our Online Store!</h2>

<b>We hope you will come back soon.</b>

<p>

<a href="http://www.persits.com"><img src="cid:Persits-Software-Logo" border="0"></a>

</center>
</body>
</html>

The code snippet responsible for image embedding is as follows:

...
// Append body from file
objMail.AppendBodyFromFile(Server.MapPath("MessageBody.htm"));

// Embed images used in the message body
objMail.AddEmbeddedImage(Server.MapPath("margin.gif"),
  "My-Background-Image");
objMail.AddEmbeddedImage(Server.MapPath("pslogo.gif"),
  "Persits-Software-Logo");

objMail.IsHTML = true;
...
...
' Append body from file
objMail.AppendBodyFromFile(Server.MapPath("MessageBody.htm"))

' Embed images used in the message body
objMail.AddEmbeddedImage(Server.MapPath("margin.gif"), _
  "My-Background-Image")
objMail.AddEmbeddedImage(Server.MapPath("pslogo.gif"), _
  "Persits-Software-Logo")

objMail.IsHTML = True
...

Click the links below to run this code sample:

2.3 Email Address Validation

AspEmail.NET is capable of validating the syntax of an email address. As of Version 5.2, it is also able to determine, with a high degree of certainty, whether a particular email address actually exists.

The method ValidateAddress takes an email address as an argument and returns 0 if the address is syntactically valid. A number greater than 0 means a syntax error. All possible return values are as follows:

Value
Meaning
0
Valid
1
Too short
2
Too long (greater than 256 chars)
3
No @
4
Nothing before @
5
Characters before @ must be a-z A-Z 0-9 ' _ . - +
6
No dots after @
7
Zero-length subdomain
8
Characters in a subdomain must be a-z A-Z 0-9 -
9
Characters in a top-level subdomain must be a-z A-Z 0-9
10
Top-level subdomain must be at least 2 characters long
11
Name part of address cannot start or end with a dot
12
A subdomain cannot start or end with a dash (-)

For example:

if( objMail.ValidateAddress( strEmail ) != 0 )
{
   Response.Write( "Invalid email address." );
}

The ValidateAddress method makes no determination whether the email address being validated actually exists. As of Version 5.2, AspEmail.NET offers another method, ValidateAddressMX, which internally calls ValidateAddress to determine its syntactic correctness, performs a DNS lookup of the MX records for the address's domain, and then contacts the corresponding SMTP server to determine if it recognizes the address as valid.

ValidateAddressMX expects two arguments: the email address being validated and, optionally, the IP address of the DNS server for the MX record lookup. If the 2nd argument is omitted, the method obtains the addresses of the local DNS servers from the system registry. ValidateAddressMX returns an empty string if the email address is successfully validated, or an error message if the validation fails.

To validate an address against its corresponding SMTP server, ValidateAddressMX sends three SMTP commands: HELO, MAIL FROM and RCPT TO. The value used for the HELO command is the Helo property, for the MAIL FROM command the MailFrom property, and for the RCPT TO command the address being validated. If MailFrom is not specified, the address being validated is used for the MAIL FROM command as well. It is recommended that you specify your domain name for the Helo property, and your valid email address for the MailFrom property before calling ValidateAddressMX, as follows:

objMail.Helo = "mydomain.com";
objMail.MailFrom = "myself@mydomain.com";
string strRes = objMail.ValidateAddressMX("user@somedomain.com");
if( strRes == "" )
{
   Response.Write( "OK" );
}
else
{
   Response.Write( "Not OK: " + strRes );
}

Note that the validation procedure performed by the ValidateAddressMX method is not 100% accurate. An error returned by the method does not always mean the address is invalid, and a lack of error is not always an indication the address exists.