Click here to Skip to main content
Click here to Skip to main content

How to make a mail enabled contact in C#

, 22 Sep 2005
Rate this:
Please Sign up or sign in to vote.
This little article explains how to make a mail enabled contact in C#.

Introduction

I spent quite a while finding and converting code-snippets to make an e-mail enabled contact. It seemed to me like it should be a relatively easy task to carry out, but I was missing the intricacies of CDO vs. ADSI users. There is a tech-note on Microsoft which is quite clear, but you have to have a bit of CDO experience to decode what it means. The tech-note is available here.

The key pieces of information are:

  1. You cannot use ADSI or an ADSI object to create a Mail Enabled anything.
  2. You must use CDO and CDOEXM and ADODB.
  3. You can only develop this on an Exchange server.
  4. You can only deploy it on an Exchange server.

The tech-note states that you can develop it on a Win200x machine with the Admin tools installed. This does not work. The reason is that the ADODB lib from Admin tools are not compatible with ADODB on .NET. You get a nasty error when trying to add a reference to CDOEXM with Admin Tools only. On a real Exchange Server, this does not seem to be a problem.

Eventually I downloaded the Exchange 2003 SDK and found the VB code for making a Mail Enabled Person. I then converted that into C#. That code can be found at MSDN.

A fairly serious fault I found with the original code one day later was that you must make sure that there will be no duplicate addresses in your domain. People were getting NDR reports, because of duplicate e-mail addresses.

LDAP could be used to repopulate so many things, and there are many attributes that contain e-mail addresses, that I was not sure how to test for "exchange enabled". Searching Proxy Addresses seemed to be a good way, because I read on tech boards that Proxy Addresses is what Exchange looked up to send email addresses. I found a relative tech-note that seemed to support this idea.

The way I chose to do it was to search all objects (this really takes a lot of processor and time). Because you can have mail enabled folders, contacts, persons, etc... I thought this the best way, as you might have "mail enabled" toasters ending up in Active Directory sometime in the future: sendto:popup@mytoaster.com, you never know.

As far as function naming goes, I always like to ask questions in the positive so the code reads easier (in my opinion). I think it is more understandable to write:

  if (! EmailAddressExistInLDAP( "bsmith@mycompany", strRootDSE)

than to write:

  if ( NotInAddressBook( ... ))

When you want to write the opposite, the logic can be difficult to follow.

  if ( ! NotInAddressBook( ... ))

However in this case it does mean the function returns "true" to not add the contact, and that might be confusing reading the EmailAddressExistInLDAP through the first time.

This code takes about 5 minutes to run with the 600 contacts I am transferring so the *emailaddress* is an "expensive" way to go about it. If anyone knows something faster and better, I certainly would be interested.

Obviously as with all other freeware code in the world, this is as is and I recommend that you test it thoroughly in a development environment before releasing it on the real world.

You will also need to have created an ADSI contact, before this can MailEnable that contact. There are lots of code articles around about making a mail enabled contact.

Here is the code snippet:

using CDOEXM;
 
// strLDAPcn is an LDAP URL "LDAP://cn=Bill Smith,
//           ou=Connecticut,ou=Partners,DC=mynetwork,DC=com"
// strMailAddress is an valid Exchange
//      address "SMTP:bsmith@mypartnercompany.com
// strRootDSE is the Root DSE Example "DC=mynetwork,DC=com"
 

private bool MailEnablePerson(string strLDAPcn, 
             string strMailAddress, string strRootDSE)
{
    // Create a CDO Person and a Recipient Object
 
    CDO.Person cdoPerson = new CDO.PersonClass();
    CDOEXM.IMailRecipient cdoRecipient;
    bool bRetVal = false;
 
    // set the parameters and fetch the user.  The contact must already exist.  
    
    cdoPerson.DataSource.Open(strLDAPcn,null,
        ADODB.ConnectModeEnum.adModeReadWrite,
        ADODB.RecordCreateOptionsEnum.adFailIfNotExists,
        ADODB.RecordOpenOptionsEnum.adOpenSource,"","");
 
    // Cast the person onto the recipient 
 
    cdoRecipient = (IMailRecipient) cdoPerson;
 
    // If the user already has an SMTP mail property,
    // don't Email Enable them. 
    // "SMTPmail", is normally set by exchange
    // where the property "email" is 
    // the one that is in use from a contact.
 

    if (cdoRecipient.SMTPEmail == "")
    {
 
        // If the user does not  have an SMTP address in LDAP then MailEnable them. 
        // The contact must already exist as an basic LDAP entry.
        
        if (! EmailAddressExistInLDAP(strMailAddress,strRootDSE) )
        {
            // The key call to CDO, and then Save it
            // I am not sure why CDO.Person is saved but it was in the
            // Microsoft code, so I left it.
 
            cdoRecipient.MailEnable(strMailAddress);
            cdoPerson.DataSource.Save() ; 
            bRetVal = true;
        }
    }
    return bRetVal ;
}
 
// EmailAdressExistInLDAP. As per the Technote,
// proxyAddresses = Exchange Email Addresses
// This takes two parameters
 
// strMailAddress the Email address example: bsmith@mypartnercompany.com
// strRootDSE the Root DSE example: DC=mycompany,DC=com
 
private bool EmailAddressExistInLDAP(string strMailAddress, 
                                         string strRootDSE)
{
    // Set the return value to True    
    // True means that the Active Directory would NOT be updated and
    // I prefer the default to be "don't do"     
 
    bool bRetVal = true;
 
    // Set a objSearch starting at RootDSE, and a place to return it.
 
    System.DirectoryServices.DirectorySearcher objSearch 
                    = new DirectorySearcher(strRootDSE);
    System.DirectoryServices.SearchResult objResult;
 
    // Filter only on the proxyAddress
 
    objSearch.Filter = "(& ( proxyAddresses=*"+strMailAddress+"*))";
 
    // if we even find one, we can't add another.
    // This is a slow way to look, but
    // it is better than having two Exchange Proxy
    // Address's and getting NDR's.
 
    objResult = objSearch.FindOne();
 
    if (objResult == null)
        bRetVal = false;
    return bRetVal;
}

Links

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

mapleleafsfan

Bermuda Bermuda
No Biography provided

Comments and Discussions

 
GeneralA simpler solution avoiding the use of ADODB Pinmemberrotorua21-May-09 11:39 
GeneralInvalidCastException PinmemberJosh Hawley27-Sep-07 17:23 
System.InvalidCastException was caught
Message="Unable to cast object of type 'CDO.PersonClass' to type 'CDOEXM.IMailRecipient'."
 
Oddly enough it seems to think this is ok at compile time, but at runtime it throws this exception.
I am getting that error at the following line:
 
cdoRecipient = (IMailRecipient)cdoPerson;
 

 
Any help would be greatly appriciated.
 
Josh Hawley
GeneralRe: InvalidCastException Pinmembermapleleafsfan28-Sep-07 2:57 
AnswerRe: InvalidCastException Pinmembermapleleafsfan28-Sep-07 3:00 
GeneralRe: InvalidCastException PinmemberJosh Hawley28-Sep-07 12:00 
GeneralCDOEXM Manipulation PinmemberM. J. Jaya Chitra7-Oct-07 18:19 
GeneralCDO.Person Pinmembershashankkadge13-Aug-07 11:11 
GeneralRe: CDO.Person Pinmembermapleleafsfan13-Aug-07 16:24 
GeneralRe: CDO.Person Pinmembershashankkadge14-Aug-07 2:38 
GeneralA Thanks, and a Comment PinmemberRoger CS14-Jan-07 7:04 
GeneralBad Filter Pinmemberjordi_gonzalez28-Sep-05 21:50 
QuestionWhat includes are you using? Pinmemberblinkowski7-Sep-05 11:55 
Answer[Msg Deleted] Pinmembermwdiablo7-Sep-05 12:21 
GeneralRe: [Msg Deleted] PinsussAnonymous13-Sep-05 15:40 
AnswerRe: What includes are you using? Pinmembermwdiablo7-Sep-05 12:24 
AnswerRe: What includes are you using? Pinmemberdevonsprings7-Sep-05 13:55 
AnswerRe: What includes are you using? Pinmemberdevonsprings7-Sep-05 14:12 
AnswerRe: What includes are you using? Pinmemberdevonsprings7-Sep-05 14:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 22 Sep 2005
Article Copyright 2005 by mapleleafsfan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid