Telnet and SMTP - how to send email using telnet commands

Monday, 28 September 2009 23:06 by myro

What is the best place to keep telnet commands used to test a SMTP service than you personal blog? Laughing
Communication between clients and SMTP services happens using simple text commands and after each commend sent by the client, the SMTP server replies with a response code followed by a message.
You can use these commands to test if your SMTP is running correcly and compare them with my SMTP's conversation to see what the server should reply.
As you will see my SMTP service is installed into a windows enviroment using IIS 6.0 and with the NTLM authentication enabled.
Let's see first few besic commands:

Command Example Description
HELO (now EHLO) EHLO 193.56.47.125 Identification using the IP address or domain name of the originator computer
MAIL FROM: MAIL FROM: originator@domain.com Identification of the originator's address
RCPT TO: RCPT TO: recipient@domain.com Identification of the recipient's address
DATA DATA message Email body
QUIT QUIT Exit the SMTP server
HELP HELP List of SMTP commands supported by the server
AUTH LOGIN
AUTH LOGIN Authenticates you user

And now, see how can you use these commands with a SMTP server.

telnet mail.server.com 25
Trying 70.87.xxx.xxx...
Connected to mail.server.com.
Escape character is '^]'.
220 C34495-51701 Microsoft ESMTP MAIL Service, Version: 6.0.3790.3959 ready at  Fri, 25 Sep 2009 14:27:48 +0200
ehlo myrocode.com
250-C34495-51701 Hello [93.62.0.xxx]
250-AUTH GSSAPI NTLM LOGIN
250-AUTH=LOGIN
250-TURN
250-SIZE
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250 OK
auth login
334 VXNlcm57uWU6
aXBlcmJvcmVh
334 UFFzc3dzcmQ7
aXBlcmIwMSE=
235 2.7.0 Authentication successful
mail from:miro@miro.com
250 2.1.0 miro@miro.com....Sender OK
rcpt to:test@myrocode.com
250 2.1.5 test@myrocode.com
data
354 Start mail input; end with <CRLF>.<CRLF>
ciaooooo
.
250 2.6.0 <C34495-51701DcBi4FS00000001@C34495-51701> Queued mail for delivery
quit
Connection closed by foreign host.

An important part of this communication is when it come's to autenticate your user: after AUTH LOGIN is send, you should provide first the username and then the password, both encoded using the base64 algoritam.
you can encode a string into a base64 format follwing this link

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories:   Developer Life
Actions:   Bookmark and Share | Permalink | Comments (0) | Comment RSSRSS comment feed

Using Reflection to display object's property values in c#.

Monday, 28 September 2009 17:08 by myro

This code snippet posted below can be used to display all object's property values, by inkoing the ToString() of each property. An usefull implementation could be when you are in need of logging an object's state by writing to a log file all his properties states. 
The DisplayObjectProperties static method cycles throught the object's properties and as told before, it calls the ToString() method, which is always implemented since every class is derived from the Object class. Recuirsion is not implemented, the ToString() method will be called only at the first level.

public static class ReflectionHelper
{
    public static string DisplayObjectProperties(Object o)
    {
        StringBuilder sb = new StringBuilder();
        System.Type type = o.GetType();
        foreach (PropertyInfo p in type.GetProperties())
        {
            if (p.CanRead)
            {
                object obj = p.GetValue(o, null);
                if (obj != null)
                {
                    sb.AppendLine(String.Concat("-Property name: ", p.Name ));
                    sb.AppendLine(String.Concat("-Property value:", obj.ToString()));
                    sb.AppendLine();
                }
                else sb.Append(String.Concat(p.Name, " # Value is null"));

            }
        }
        return sb.ToString();
    }
}

Now immagine that you' ve got this sample class called PersonalAttribute:

 public class PersonalAttribute
{

    public string AttributeName { get; set; }

    public string AttributeValue { get; set; }

}

An usefull implementation could be:

public class PersonalAttribute
{

    public string AttributeName { get; set; }

    public string AttributeValue { get; set; }

    public override string ToString()
    {
        return ReflectionHelper.DisplayObjectProperties(this); 
    }

}

Now, when the ToString() method is invoked in a new PersonalAttribute's istance, the returned string is something similar to:

-Property name: AttributeName
-Property value:SiteName

-Property name: AttributeValue
-Property value:myrocode.com

Remember that using Reflection is slow compared to direct access of a property, field or method. If you are building a complex application, this could be not the best solution for you case.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   ,
Categories:   .NET
Actions:   Bookmark and Share | Permalink | Comments (0) | Comment RSSRSS comment feed

An unhandled execption occurred in the user interface: OSearch - SharePoint 2007

Tuesday, 22 September 2009 11:26 by myro

When configuring a SharePoint 2007 farm through the Central Administration, you should always use domain accounts for you services, to avoid errors or strange behaviors. But what happens when you just need to configure services in a stand alone enviroment?
For web site's application pools identities you should use the default Network Service account, but when it comes to configure SharePoint's 2007 Services, the easiest way is to create a local administrator account and use it to run all your services. 

Almost every Central Administration's page uses a people picker to avoid errors, but sometimes you will just see a blank textbox which asks you to input the credentials for running determined service.  This is the place when sometimes strange errors starts...

Here's an example:
during a Shared Services configuration in a stand alone enviroment, I was configuring the Index Service and when I was asked for credentials, I have simply insered the new local admin account I've created.
SharePoint 2007 didn't like it and reported this error:  An unhandled execption occurred in the user interface: OSearch.

WTF?
Why they didn't provide any information about the error in that page? 
Anyway, you can solve the problem by preceding your admin account name with your server name: YOURSERVERNAME\YourAdminAccount.

Obvious! right? ......

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   SharePoint 2007
Actions:   Bookmark and Share | Permalink | Comments (0) | Comment RSSRSS comment feed

Code Snippet: Send Bulk Emails in C#

Tuesday, 15 September 2009 09:55 by myro

This small snippets can be used in your project if you need to deliver many emails using c# without caring if the receiver's email is defined in the recipients and in the Carbon Copy (Cc) or in the Blind CArbon Copy (Bcc) twice.
This method simply checks every time if an email is present in the To header is also contained in the Cc and/or in the Bcc.

Bulk emailing is also supported: just separate you emails, using a separator character (in my case is a comma ',').

public static void SendMail(string Subject, string Body, bool IsHtml, string From, string To, string Cc, string Bcc)
{
    const char SEPARATOR = ',';
    string[] Tos = new string[0];
    string[] Ccs = new string[0];
    string[] Bccs = new string[0];


    MailMessage mailMessage = new MailMessage();
    mailMessage.From = new MailAddress(From);
    mailMessage.Subject = Subject;
    mailMessage.Body = Body;
    mailMessage.IsBodyHtml = IsHtml;

    if (!String.IsNullOrEmpty(To))
         Tos = To.Split(new char[] { SEPARATOR }, StringSplitOptions.RemoveEmptyEntries);
    if (!String.IsNullOrEmpty(Cc))
         Ccs = Cc.Split(new char[] { SEPARATOR }, StringSplitOptions.RemoveEmptyEntries);
    if (!string.IsNullOrEmpty(Bcc))
        Bccs = Bcc.Split(new char[] { SEPARATOR }, StringSplitOptions.RemoveEmptyEntries);

    foreach (var item in Tos)
    {
        mailMessage.To.Add(new MailAddress(item));
    }

    foreach (string item in Ccs)
    {
        if (!isMailCointained(item, Tos))
        {
            mailMessage.CC.Add(new MailAddress(item));
        }  
    }

    foreach (string item in Bccs)
    {
        if (!isMailCointained(item, Tos) && !isMailCointained(item ,Ccs))
        {
            mailMessage.Bcc.Add(new MailAddress(item));
        }
    }
    try
    {
        SmtpClient smtpClient = new SmtpClient();
        // add your smtp server!
        smtpClient.Host = ConfigurationManager.AppSettings["YOUR EMAIL SERVER"];
        smtpClient.Send(mailMessage);
 }
     catch(Exception exc){// add your exception handlers.. }
}

private static bool isMailCointained(string mail, string[] mails)
{
    bool toRet = false;

    foreach (var item in mails)
    {
        if (mail == item)
            return true;
    }
    return toRet;
}

If you call the SendMail method using:

  SendMail("Hello", "<h3>Hello from myrocode!</h3>", true,
                "myEmail@a.com", "a@a.com,b@a.com,c@a.com", "z@a.com,b@a.com", "x@a.com,y@a.com,z@a.com");

You email will be deliverd with the following headers:

To: a@a.com
      b@a.com
      c@a.com

Cc:z@a.com

Bcc:x@a.com
      y@a.com

this post is nothing special.. but can be usefull for a fast refernce or a copy & paste code snippet for your project.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   ,
Categories:   .NET | .NET
Actions:   Bookmark and Share | Permalink | Comments (2) | Comment RSSRSS comment feed

using Active directory with C#: LDAP query to get all users in a specific Group

Monday, 14 September 2009 11:14 by myro

This post illustrates how can you retreive all user's emails that belongs to an Active Directory group in c# using the .NET framework 3.5.
Code snippets provides 3 classes that shows you how to obtain basic informations about users and group, quering a LDAP server:

  • AdUser.cs is just a container class that rappresents a user with 3 basic properties: Distinguished Name, Display Name and Email
  • AdUserCollection.js is just an AdUser collection
  • ADSearcher.cs rappresents your Active Directory wrapper that retrieves your users based on LDAP queries

Use this classes and modify them to rappresents better your needs: right now the ADSearcher provides just methods to get Users that belongs to and Active Directory Group

ADUser class

public class AdUser
{
    string _email;
    string _name;
    string _displayName;

    public string Name
    {
        get { return _name; }
        private set { _name = value.ToLower().Trim(); }
    }

    public string DisplayName
    {
        get { return _displayName; }
        private set { _displayName = value.ToLower().Trim(); }
    }

    public string Email
    {
        get { return _email; }
        private set { _email = value.ToLower().Trim(); }
    }


    public AdUser(string name, string displayName, string email)
    {
        Name = name;
        DisplayName = displayName;
        Email = email;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof(AdUser)) return false;

        return Equals((AdUser)obj);
    }

    public bool Equals(AdUser other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.Name, Name);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int result = (Name != null ? Name.GetHashCode() : 0);
            return result;
        }
    }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("Name: "+ Name);
        sb.AppendLine("DisplayName: " + DisplayName);
        sb.AppendLine("Email: " + Email);
        return sb.ToString();
    }
}

ADUserCollection class 

public class AdUserCollection : List<AdUser>
{
    public string GetAllMails()
    {
        StringCollection sc = new StringCollection();
        foreach (var item in this)
        {
            string email = item.Email.ToLower().Trim();
            if (!String.IsNullOrEmpty(email) && !sc.Contains(email) )
            {
                sc.Add(email);
            }
        }
        string toRet = string.Empty;

        foreach (var item in sc)
        {
           toRet =  string.Concat(toRet, ",", item );
        }
        toRet =  toRet.Remove(0, 1);
        return toRet;        
    }

    new public void AddRange(AdUserCollection users)
    {
        foreach (var user in users)
        {
            if (!this.Contains(user))
            {
                this.Add(user);
            }
        }
    }
}

ADSearcher class

public class ADSearcher
{

    string _ldap = string.Empty;

    public ADSearcher(string ServerLDAP)
    {
        _ldap = ServerLDAP;
    }

     public AdUserCollection GetUsersFromNeastedGroups
   (StringCollection activeDirectoryGroups)
    {
        AdUserCollection users = new AdUserCollection();
        foreach (var item in activeDirectoryGroups)
        {
            IEnumerable<AdUser> group = GetUsersFromAdGroup(item);
            if (group != null)
                users.AddRange(GetUsersFromAdGroup(item));
        }
        return users;
    }

     public IEnumerable<AdUser> GetUsersFromAdGroup
   (string activeDirectoryGroup)
    {

        DirectoryEntry entry = new DirectoryEntry(_ldap);
        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = String.Format("(&(objectCategory=group)(cn={0}))", activeDirectoryGroup);
        search.PropertiesToLoad.Add("distinguishedName");
        SearchResult searchResult = search.FindOne();

        if (searchResult == null)
            return null;
        DirectoryEntry group = searchResult.GetDirectoryEntry();

        Hashtable searchedGroups = new Hashtable();
        return GetUsersInGroup(group.Properties["distinguishedName"].Value.ToString(),
        searchedGroups);
    }


    HashSet<AdUser> GetUsersInGroup(string activeDirectoryGroup,
       Hashtable searchedGroups)
    {
        HashSet<AdUser> groupMembers = new HashSet<AdUser>();
        searchedGroups.Add(activeDirectoryGroup, activeDirectoryGroup);

        // find all users in this group
        DirectorySearcher ds = new DirectorySearcher(_ldap);
        ds.Filter = String.Format("(&(memberOf={0})(objectClass=person))", activeDirectoryGroup);

        ds.PropertiesToLoad.Add("sAMAccountName");
        ds.PropertiesToLoad.Add("mail");
        ds.PropertiesToLoad.Add("displayName");

        //Add user to the list
        foreach (SearchResult sr in ds.FindAll())
        {
            string name = sr.Properties["sAMAccountName"][0].ToString();
            string email = string.Empty;
            if (sr.Properties.Contains("mail"))
            email = sr.Properties["mail"][0].ToString();

            string displayname = string.Empty;
            if (sr.Properties.Contains("displayName"))
                displayname = sr.Properties["displayName"][0].ToString();

            AdUser user = new AdUser(name, displayname, email);
            if (groupMembers.Contains(user) == false)
            {
                groupMembers.Add(user);
            }
        }

        List<string> nestedGroups = GetNestedGroups(activeDirectoryGroup);
        foreach (string directoryGroup in nestedGroups)
        {
            if (searchedGroups.ContainsKey(directoryGroup) == false)
            {
              HashSet<AdUser> users = GetUsersInGroup(directoryGroup,
        searchedGroups);
              foreach (AdUser user in users)
              {
                 if (groupMembers.Contains(user) == false)
                 {
                      groupMembers.Add(user);
                 }
              }
            }
        }

        return groupMembers;
    }

    private List<string> GetNestedGroups(string activeDirectoryGroup)
    {
        List<string> groupMembers = new List<string>();
        DirectorySearcher ds = new DirectorySearcher(_ldap);
        ds.Filter = String.Format("(&(memberOf={0})(objectClass=group))",
     activeDirectoryGroup);

        ds.PropertiesToLoad.Add("distinguishedName");
        foreach (SearchResult sr in ds.FindAll())
        {
            groupMembers.Add(sr.Properties["distinguishedName"][0].ToString());
        }
        return groupMembers;
    }
  }

Once you have copied this classes into your project you could use the ADSearcher to get users' emails that belongs to an Active Directory Group:

ADSearcher searcher = new ADSearcher(ConfigurationManager.AppSettings["LdapServer"]);
AdUserCollection UsersInGroup = searcher.GetUsersFromMulitpleGroups(sc);
string UsersInGroupMails = UsersInGroup.GetAllMails();

 

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:   ,
Categories:   .NET
Actions:   Bookmark and Share | Permalink | Comments (0) | Comment RSSRSS comment feed