Step by Step

Friday, May 13, 2011

How to send mail using Asp.net



Default to send mail
using System.Net.Mail;




MailMessage email = new MailMessage();


email.Subject = "My first test email";
email.SubjectEncoding = System.Text.Encoding.UTF8;
email.Body = body;
email.BodyEncoding = System.Text.Encoding.UTF8;
email.To.Add(new MailAddress("recipient@domain.com"));
email.Sender = new MailAddress("sender@domain.com");
email.From = new MailAddress("sender@domain.com");
email.Attachments.Add(new Attachment("c:\\my-attachment.pdf"));


try {
SmtpClient client = new SmtpClient("mail.my-domain.com", 25);
// 25 is the default SMTP port
client.Send(email);
} catch (SmtpException ex) {
...
}


Email Address Validation
Another common problem - validating email address input - can be handled easilly in ASP .NET
Validation is important. It reduces the amount of incorrect or fabricated email addresses clogging up your database.
At a very minimum, the format of the address should be tested, and this is typically accomplished using regular expressions.
using System.Text.RegularExpressions;


...


private bool EmailAddressIsValid(string email) {
string regExPattern = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
@"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
@".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
Regex regEx = new Regex(regExPattern);
return regEx.IsMatch(email);
}
Note that this can be tested client-side using Javascript as well.
Socket to 'em
But let's say you want to be extra sure that bogus addresses will not violate your precious database space.
There are two other aspects you can test, and here ASP .NET comes into its own, using its socket functionality.
(SMTP emails are sent using socket connections. In fact you can write your own version of the SmtpClient class using sockets. But why re-invent the wheel? Unless you're really bored. Or drunk. Or both.)
Domain validation


First, test whether the email domain (the part after the @) exists.
All you have to do is open a socket connection with the domain, and see what happens.
using System.Net;
using System.Net.Sockets;


string email = "recipient@some-domain.com";
string[] host = email.Split('@');
string hostName = host[1];
Socket socket;
try {
IPHostEntry entry = Dns.GetHostEntry(hostName);
IPEndPoint endPoint = new IPEndPoint(entry.AddressList[0], 25);
socket = new Socket(endPoint.AddressFamily, SocketType.Stream,
ProtocolType.Tcp);
socket.Connect(endPoint);
//Yippee - the email domain exists!
} catch (SocketException se) {
//Oops - the email domain is not valid!
}


Account validation


Even if the domain exists and is willing to receive mail, we still don't know whether the mail account exists for the domain. The only way to be sure of this is to try to connect to the account.
We continue with the socket communication process that we started in the previous stage (domain validation). This is the very process used to send an email, and we stop only very short of sending email content. This requires a series of interactions with the email server. We use utility functions to help us: SendData and

CheckSmtpResponse

if (!CheckSmtpResponse(SmtpResponse.CONNECT_SUCCESS)) { //account is invalid! }


//test HELO server
SendData(string.Format("HELO {0}\r\n", Dns.GetHostName()));
if (!CheckSmtpResponse(SmtpResponse.GENERIC_SUCCESS)) { //account is invalid! }


//test for sender domain on blacklist
SendData(string.Format("MAIL From: {0}\r\n", _SenderEmail));
if (!CheckSmtpResponse(SmtpResponse.GENERIC_SUCCESS)) { //account is invalid! }


//test send
SendData(string.Format("RCPT TO: {0}\r\n", email));
if (!CheckSmtpResponse(SmtpResponse.GENERIC_SUCCESS)) { //account is invalid! }


//account is valid!


//utility funtions:


void SendData(string message) {
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(message);
socket.Send(bytes, 0, bytes.Length, SocketFlags.None);
}


enum SmtpResponse : int {
CONNECT_SUCCESS = 220,
GENERIC_SUCCESS = 250,
DATA_SUCCESS = 354,
QUIT_SUCCESS = 221
}


bool CheckSmtpResponse(SmtpResponse code) {
string responseString;
int responseCode;
byte[] bytes = new byte[1024];
while (socket.Available == 0) {
System.Threading.Thread.Sleep(100);
}
socket.Receive(bytes, socket.Available, SocketFlags.None);
responseString = System.Text.Encoding.ASCII.GetString(bytes);
responseCode = Convert.ToInt32(responseString.Substring(0, 3));
return responseCode.Equals(Convert.ToInt32(code));
}

0 comments: