Sunday, March 9, 2008

Send and Receive Mail from C# (SMTP and POP)


Today we shall see both sending of mails from a domain and reading mails from a domain.

Some domains wont allow mails to be send from them from an application if no mail is popped from it,ie;read from it. That means , to send a mail we first need to get pop access to the domain.Once we authenticate that we can start sending mails from that domain.

Include the following code bit in any page.

public class Pop3Exception : System.ApplicationException
{
public Pop3Exception(string str)

: base(str)
{

}
};

public class Pop3Message
{

public long number;

public long bytes;

public bool retrieved;

public string message;

};
public class Pop3 : System.Net.Sockets.TcpClient
{
public void Connect(string server, string username, string password)
{
string message;
string response;

Connect(server, 110);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}

message = "USER " + username + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}

message = "PASS " + password + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
}

private void Write(string message)
{
System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding();
byte[] WriteBuffer = new byte[1024];
WriteBuffer = en.GetBytes(message);
NetworkStream stream = GetStream();
stream.Write(WriteBuffer, 0, WriteBuffer.Length);
Debug.WriteLine("WRITE:" + message);
}

private string Response()
{
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] serverbuff = new Byte[1024];
NetworkStream stream = GetStream();
int count = 0;
while (true)
{
byte[] buff = new Byte[2];
int bytes = stream.Read(buff, 0, 1);
if (bytes == 1)
{
serverbuff[count] = buff[0];
count++;
if (buff[0] == '\n')
{
break;
}
}
else
{
break;
};
};
string retval = enc.GetString(serverbuff, 0, count);
Debug.WriteLine("READ:" + retval);
return retval;
}

public void Disconnect()
{
string message;
string response;
message = "QUIT\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
}

public ArrayList List()
{
string message;
string response;

ArrayList retval = new ArrayList();
message = "LIST\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}

while (true)
{
response = Response();
if (response == ".\r\n")
{
return retval;
}
else
{
Pop3Message msg = new Pop3Message();
char[] seps = { ' ' };
string[] values = response.Split(seps);
msg.number = Int32.Parse(values[0]);
msg.bytes = Int32.Parse(values[1]);
msg.retrieved = false;
retval.Add(msg);
continue;
}
}
}
public Pop3Message Retrieve(Pop3Message rhs)
{
string message;
string response;

Pop3Message msg = new Pop3Message();
msg.bytes = rhs.bytes;
msg.number = rhs.number;

message = "RETR " + rhs.number + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}

msg.retrieved = true;
while (true)
{
response = Response();
if (response == ".\r\n")
{
break;
}
else
{
msg.message += response;
}
}

return msg;
}
}

Now calling PopMail(),

private static void PopMail()
{
try
{
Pop3 obj = new Pop3();
obj.Connect("pop.rediffmailpro.com", "full@email.address", "password");
ArrayList list = obj.List();
foreach (Pop3Message msg in list)
{
Pop3Message msg2 = obj.Retrieve(msg);
System.Console.WriteLine("Message {0}: {1}",
msg2.number, msg2.message);
break;
}
obj.Disconnect();
}
catch (Pop3Exception pe)
{
System.Console.WriteLine(pe.ToString());
}
catch (System.Exception ee)
{
System.Console.WriteLine(ee.ToString());
}
}

will do the tricks.

No we'll see the sending of mails.For that we use a button click event on our application.

private void _sendButton_Click(object sender, EventArgs e)
{
System.Data.Odbc.OdbcConnection connect = new System.Data.Odbc.OdbcConnection();
...
{
..
}
foreach (DataGridViewRow row in grid.Rows)
{
count++;
if (row.Cells[0].Value != null)
{
if (row.Cells[0].Value.ToString() == "True")
{
..
if (count % 300 == 0)
PopMail();
sendMail(row);
..
}
}
}
MessageBox.Show("Mails sent Successfully");
}

bool sendMail(DataGridViewRow row)
{
MailMessage message = new MailMessage();

string getToAddress = row.Cells[4].Value.ToString();
try
{
if (getToAddress == "")
message.To.Add("default@email.id");
else
message.To.Add(row.Cells[4].Value.ToString());
}
catch (Exception ex)
{
message.To.Add("default@email.id");
}
try
{
message.From = new MailAddress("emailid", "domain");
message.IsBodyHtml = true;
string messageBody = GetMessageBody(row);
message.Body = messageBody;
message.Subject = "Hi";
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.rediffmailpro.com");
System.Net.NetworkCredential smtpAuthen =
new System.Net.NetworkCredential("emailid", "password");
smtp.UseDefaultCredentials = false;
smtp.Credentials = smtpAuthen;
smtp.Send(message);
return true;
}
catch (SmtpException se)
{
Console.WriteLine(se.Message);
return true;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return true;
}
}

In the code you might have noticed that,the PopMail() is called in a loop during limited time interval.That is because,the authentication time expires after sending a couple of mails.So the PopMail is called after sending every 300 mails.

Hope this is useful..

1 comment:

Cindy Dy said...

This is just the information I am finding everywhere. Thanks for your blog, I just subscribe your blog. This is a nice blog.


Yong
www.gofastek.com