Welcome to MSDN Blogs Sign in | Join | Help

FYI: MSDN Protocol Docs...

Steve posted a link to the MSDN protocol documentation.  He talks about them here and here as well.

Posted by mstehle | 0 Comments

OOM.NET: Part 5 - Event Planning

Plan For What You Can Control

One of the common scenarios in OOM programming in managed code that required calling GC.Collect() was handling events.  As has been discussed earlier in this series, item references need to be released before they go out of scope.  This includes items passed into event handlers.  Take the ItemSend event for example...

// This leaks 'Item'
void app_ItemSend(object Item, ref bool Cancel)
{
    
}

// This does not leak...
void app_ItemSend(object Item, ref bool Cancel)
{
    try
    {

    }
    finally
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(Item);
    }
}

...In most cases you would expect that the caller invoking the delegate and passing 'Item' would be responsible for releasing it since that is where it was created.  However, that is not the case here - 'Item' must be released within the delegate, the caller does not call ReleaseCOMObject().

Know The Symptoms

The most common symptoms of this kind of leak (especially with the ItemSend event) are scenarios involving sending meeting requests and meeting updates.  If there is a leak in the ItemSend event and a meeting request or update is sent out the appointment in the calendar is ultimately leaked.  The user experience goes something like this...

  1. Organizer sends a meeting update.
  2. Organizer makes a change to the appointment item in his/her calendar.
  3. Outlook prompts the organizer to send a meeting update and save the changes.
  4. Organizer attempts to send the meeting update or save and close and Outlook throws a warning/error dialog stating that the appointment has been modified elsewhere and cannot be saved.

Another common scenario is there is a leak in the NewInspector event.  Typically the symptom here is that a user will open a message and close it, then try to open the message again at which time Outlook displays a dialog stating that the "Operation failed."

Get Fixes For What You Can't Control

There were some scenarios in Outlook 2003 and Outlook 2007 where - even if the OptionPagesAdd event was the only event handled - users still saw the meeting request experience described above.  To make a long story short the interop assembly is generated by tblimp.exe (more information here) in such a way that if one event on an interface such as ApplicationEvents_11_Events interface then "underneath the covers" they are all handled - in the case of OptionPagesAdd that means ItemSend and ItemLoad are handled too.  Because these events are not handled in the AddIn code there is no way to release the reference the items passed to them.  To address this issue, the Outlook team released a fix for Outlook 2003 and Outlook 2007.  Any Outlook install that is using extensive or multiple .NET AddIns should have the following fixes installed to avoid this issue...

Description of the Outlook 2007 post-Service Pack 1 hotfix package: January 28, 2008

Description of the Outlook 2003 post-Service Pack 3 hotfix package: December 13, 2007

OOM.NET: Part 4 - Don't Thread On Me

Patrick posted a discussion of multithreading with Outlook Object Model and why it doesn't help to make OOM calls on a seperate thread...

"Outlook Object Model is run in a STA COM server. This means that all OOM calls are executed on the main thread...You don't gain any performance [when multithreading] because all the calls are going to run on the same thread anyway and you incur the overhead hit of doing the marshaling to begin with, so there's not really an advantage to multithreading Outlook Object Model."

The typical scenario is a VSTO or .NET Shared AddIn for Outlook that wants to do some kind of "background" processing of items in a seperate thread as to not hold up the UI.  This other thread will have OOM code in it that loops through items, folders, or both.  This is the kind of thread that actually hurts performance - using OOM on a seperate thread rather than the main thread.  If an AddIn makes use of seperate threads for working with things outside Outlook such as a database, filesystem, etc. then these recommendations don't apply necessarily.

Creating new threads and even marshalling between them is pretty easy in .NET and like many things in .NET (and VB6 before it) is that this marshalling and threading is supposed to "just work".  Developers can get a lot of this working with out really understanding what is going on and what is required to make this work.  An understanding of COM and what it means to STA like Outlook Object Model is required to come to the conclusions in Patrick's post.

Posted by mstehle | 1 Comments

OOM.NET: Part 3 - Back to the Basics, MSDN Must Reads

The Outlook Developer Reference on MSDN has great information on .NET and COM interop which I would consider a prerequisite to any managed code development with Outlook Object Model.  It simply isn't enough to know how to accomplish tasks with OOM or to call GC.Collect here and there - it is important to understand the whole story...

Introduction to Interoperability Between COM and .NET - This is a short and sweet run through of COM Interop and sets up a foundation for understanding where some of the issues come from in my previous posts (OOM.NET Part 1 & Part 2).  Be sure to pay attention to the following quote...

"...a COM client manages an internal reference count provided by IUnknown to free a coclass, a .NET client relies on the runtime garbage collector provided by the .NET platform to free an object..."

...That is why RelaseCOMObject is so important - in the Outlook world of item in reuse we cannot rely on the runtime garbage collector provided by the .NET platform to free an object.

There is also some 101 type information about what a PIA is found in Why Use the Outlook PIA - the take away from this is, "Any number of interop assemblies can exist to describe a given COM type. As publisher of the type library, Outlook provides a Primary Interop Assembly (PIA) that contains the official description of the COM-based Outlook object model."  Installing and Referencing the Outlook 2007 PIA takes the next step to show how to add the reference in Visual Studio.  The list of classes and interfaces in OOM as seen by VB6 or VBA differ greatly from what is seen in a .NET project - for an explanation of that phenomenon read, Relating the Outlook PIA with the Object Model.

The MSDN documentation hits on some of the points I made in Part 1 and Part 2 of OOM.NET:

Looking forward to Part 4 of OOM.NET...

A huge area of trouble is in the handling of events and how to structure code and understand the code in the PIA to prevent item leaks.  I'll be posting more information on this topic soon - in the meantime read the following two articles for some background information...

FYI: We're Still Hiring in Charlotte, Las Colinas, and Fargo...

I remember working in Richmond, VA for years thinking how awesome it would be to work at Microsoft.  It always seemed so unrealistic - even if I got past the interview process, I'd still have to move across the country.  Not only would it be a hard opportunity to get but it would be a big personal sacrifice to move.  Well all that changed when I heard about a job in Charlotte, NC with Microsoft.  Microsoft was in Charlotte all this time?!  I had no idea.  It changed everything for me.  I learned about a whole new world of Microsoft that wasn't product development but product support.  Helping people find the right menu item so that they can correctly format text or send an email in Outlook didn't sound too exciting to me but helping some of Microsoft's biggest ISV and business customer's make design decisions and fix their Exchange and Outlook applications was worth investigating.  I found that Developer Support, for me, was a great blend of what I like to do with technology: be creative, learn new things, and communicate with people.  I could do all this without the pressure of unrealistic deadlines laid on me by a bad project specifications/contracts, without travelling to a new city for each project, and with the comfort of the best benefits in the business!

We just hired Rick and we are looking for more good folks who want to work in either Charlotte, Las Colinas, or Fargo on our team.  We are looking for .NET and/or C++ developers with good communication skills, a thirst for knowledge, and the ability to have effective technical discussions with peers and customers.  We don't expect candidates to have Exchange or Outlook development experience necessarily - we can teach you that, you just have to be ready to learn!  Feel free to email or IM me if you think you might be interested in a job in Developer Support for Office or Exchange and want to know more...

Posted by mstehle | 2 Comments
Filed under: ,

FYI: After Installing Exchange 2007 SP1 32-bit CDOSYS Might Not Be Registered...

Exchange 2007 only adds 64-bit components in a 64-bit install, when you install Exchange it will register CDOEX.DLL which will replace CDOSYS.DLL and be used when you instantiate CDO.Message.  So you will see CDO.Message pointing to "C:\Program Files\Common Files\Microsoft Shared\CDO\CDOEX.DLL" in the 64-bit registry and you will see CDO.Message pointing to "C:\WINNT\SysWow64\cdosys.dll" in the 32-bit registry.  If your application is a 64-bit process it will load up CDOEX.DLL when you instantiate CDO.Message.  If your application is a 32-bit process it will load up CDOSYS.DLL when you instantiate CDO.Message.

 

After installing 64-bit Exchange 2007 you may notice that 32-bit scripts and applications get a "Library not found" error when using CDOSYS.  This appears to be a side effect of registering the 64-bit CDOEX.dll.  To resolve the issue simply open a 32-bit instance of cmd.exe from the SysWow64 directory and run "regsvr32 cdosys.dll" to re-register the 32-bit CDOSYS.

Posted by mstehle | 2 Comments

OOM.NET: Part 2 - Outlook Item Leaks

Outlook item leaks are the most common OOM with .NET issues that we see and I’ve debugged enough of them to compile this list of the four basic mistakes that contribute to item leaks.  An “item leak” is most commonly seen as an item that won’t refresh or can’t be saved in the Outlook UI.  A common example of this problem is that a user will complain that they receive a dialog stating that they can’t save or update an appointment in Outlook when a particular AddIn is loaded.  This is because the AddIn has not released the item reference and Outlook is reusing it.  In order to fix the problem properly you need to look at your code for a few of the common mistakes listed below…

 

Outlook Processes Reuse Cached Item References

If an item is in memory in Outlook.EXE then Outlook will reuse it when another action requests it.  For example, if a COM AddIn leaks an item reference and a user is interacting with that item through the UI they might not be able to save their changes all of a sudden.  This is especially true if the item were to be modified in the MAPI store after it has been leaked.  An easy test would be to modify the suspected leaked item using MFCMAPI while Outlook is running then open the item in the Outlook UI and try to modify it.  You will get a dialog saying that the item cannot be saved if you have leaked the item.

 

Do Not Chain Child Object References

One of the advantages of pure .NET programming is that you don't have to worry about memory management because the garbage collector and the dispose pattern handle all of that.  What we have to remember that OOM programming in .NET is not pure .NET programming ***it is COM programming in .NET*** because of that the rules of COM apply here.  Every object referenced must be released.  When you chain objects you lose track of a reference that you need to release. 

 

See the example below...

 

        // This leaks an Attachments reference

        ProcessAttachments(email.Attachments);

 

        // This doesn’t leak

        Outlook.Attachments oAttachs = email.Attachments;

        ProcessAttachments(oAttachs);

        Marshal.ReleaseCOMObject(oAttachs);

        oAttachs = null;

 

Since the reference to the Attachments object is maintained it can be released properly.

 

Leaking a Child Item Leaks the Parent

If a child item that holds an internal reference to its parent – such as attachments or recipients - is leaked then the parent is in turn leaked.  In the example above, chaining and leaking the child Attachments collection of the email will cause the email itself to leak.  The parent object will never get cleaned up regardless of how many times GC.Collect or ReleaseCOMObject are called.

 

Be Careful with foreach Loops

The basic use of a foreach loop to iterate through items in a collection that have an internal reference to their parent – see above - will leak items.  Either avoid foreach loops altogether by using for loops...

 

        // This leaks, GC.Collect will not help

        foreach (Outlook.Attachment oAttach in oAttachs)

        {

            Marshal.ReleaseCOMObject(oAttach);

            oAttach = null;

        }

 

        // This doesn’t leak

        for (int i = 1; i < oAttachs.Count; i++)

        {

            Outlook.Attachment oAttach = oAttachs[i];

 

            // Do nothing with attachment

            Marshal.ReleaseCOMObject(oAttach);

            oAttach = null;

        }

 

…or follow the notes in this discussion to articulate the handling and cleanup of the underlying objects in the enumerator created by the foreach loop to ensure that things get cleaned up properly…

 

        IEnumerator attachsEnum = oAttaches.GetEnumerator();

        while (attachsEnum.MoveNext())

        {

                    Attachment at = (Attachment)attachsEnum.Current;

                    Marshal.ReleaseCOMObject(at);

        }

        ICustomAdapter adapter = (ICustomAdapter)attachsEnum;

        Marshal.ReleaseComObject(adapter.GetUnderlyingObject());

        Marshal.ReleaseComObject(oAttaches);

 

Posted by mstehle | 4 Comments

OOM.NET: Part 1 - Introduction and Why Events Stop Firing...

OOM.NET is not a special API set that was created in managed code.  It is the name I've given to a series of posts I'll do about the “gotchas” of Outlook Object Model development in .NET.  I've compiled some notes over time of the most common issues, how to resolve them, and why they exist.  I'd love to hear back from you on other issues you face with OOM programming in .NET as well so that I can add them to this series...

With the introduction of Visual Studio Tools for Office and the maturity of .NET languages in general more and more Outlook developers are using .NET languages like C# and VB.NET.  The nice thing about .NET is that it encapsulates a lot of common functionality into a framework, manages memory, provides a framework for inter-operating with COM, and allows you to quickly write applications with very little concern for how all this happens.

The bad thing about .NET is that it allows you to quickly write applications with very little concern for how all that happens...

Developers can get caught up in the ease and speed of development in .NET.  They can suffer from an "It Just Works Addiction" - meaning in the bliss of swiftly writing code that just happens to compile and run it is possible to lose sight of what is making everything work.  This mentality simply will not work with Outlook development; especially in .NET because there is just too much that can happen to adversely affect your application.  So on with the show...

Why Events Stop Firing

Typically, the events stop firing problems come from adding an event handler from a locally scoped object or calling ReleaseCOMObject on an object which you are listening to events on.  The code below will eventually stop handling the NewInspector event because inspectors is locally scoped here and when GC runs it will get cleaned up thus stopping the event to fire…

 

        private void ThisAddIn_Startup(object sender, EventArgs e)

        {

            Outlook.Inspectors inspectors;

            inspectors = Application.Inspectors;

            inspectors.NewInspector += Inspectors_NewInspector;

        }

 

To fix it you would need to make inspectors a module level variable and call ReleaseCOMObject within a dispose method or in this case inside ThisAddIn_Shutdown.  You wouldn’t want to call ReleaseCOMObject on inspectors within ThisAddIn_Startup because it would free the underlying COM object and also cause your event to stop firing.

 

        private Outlook.Inspectors inspectors;

        private void ThisAddIn_Startup(object sender, EventArgs e)

        {

            inspectors = Application.Inspectors;

            inspectors.NewInspector += Inspectors_NewInspector;

        }

 

However, in Inspectors_NewInspector you *would* want to call ReleaseCOMObject on inspector once you were done with it.  For example…

 

        private void Inspectors_NewInspector(Outlook.Inspector inspector)

        {

            try

            {

                MessageBox.Show(inspector.Caption);

            }

            finally

            {

                Marshal.ReleaseComObject(inspector);

            }

        }

 

You wouldn’t want to call ReleaseCOMObject until you were done with that particular reference though.  In this case all the work is done within the try/finally block so we can safely release when we are done.  Also, it is highly recommended that you use a try/finally block to release objects in this scenario because it ensure the reference will get released even if there is an exception.

Posted by mstehle | 2 Comments
Filed under:

FYI: Exchange 2007 SP-1 Extensibility (Development) Updates

So Exchange 2007 SP1 is coming and you'll want review the updates and new features for Exchange developers.  Ray and Mike have put together a nice walkthrough with links to the new MSDN docs.

There is a whole new topic to discuss in the way of OWA customization available in Exchange 2007 SP1.  Some of the OWA customization features listed are from Exchange 2007's initial release including OWA themes and web parts.  But there is new SP1 functionality that is bound to impress. 

We have a custom forms registry which replaces the old custom OWA form technology - this is not the old stuff resurrected, this is a brand new architecture for custom forms in OWA...

"Outlook Web Access in Exchange 2007 SP1 includes an XML file that is named the Custom Forms Registry. The default installation includes a template forms registry file that you can rename and then customize to fit the application. The forms registry file specifies how to handle custom content types by indicating what form to display when the user performs the actions that are indicated in the registry file.

To display a custom small icon for a content type, specify the icon file and content class in the SmallIconMapping section of the user interface customization file."

There is also the ability to enhance OWA navigation and menus including the navigation pane...

"To enhance the experience of users who are working with custom content classes, you can register new entries to the New drop-down menu. In this manner, you can enable users to create new items of a custom content class from Outlook Web Access.

To embed Web-based applications within the Outlook Web Access user interface, you can add entries to the navigation pane. This is useful when you want to provide access within Outlook Web access to applications that are loosely integrated with Exchange; for example, expense-tracking applications that store data outside the Exchange store."

Regarding the updates to Exchange Web Services in SP1, make sure to understand the impact of using versioning requests...

"Requests that do not include version headers are handled as requests from the initial release version of Exchange 2007. If the Exchange2007_SP1 version is not specified, schema validation errors might occur because the request will be validated against the initial release version of the Exchange Web Services schema instead of the Exchange 2007 SP1 version of the schema. Other errors might also occur because Exchange 2007 SP1 identifiers will be processed as identifiers for the initial release version of Exchange 2007."

...This is one of those paragraphs in MSDN documentation that is so important to understand but my taking reading a couple times to make sure you get it.  Basically, you want to include the SP1 header in any request from a client that is using SP 1 features because if you don't the Exchange server will respond to use as if you are a Pre-SP1 client.

...Many of these updates are the result of customer feedback and cases that my team has worked since RTM of Exchange 2007.  It is awesome to see the Product Group so focused on supporting the API sets - improving and extending them with each milestone.

FYI: The Outlook Team has a blog

The Outlook team has a blog now and they just put up a post about Outlook development and linked to me.  So I'll return the favor!  It is great to have yet another product team start blogging at MS...good stuff!

Posted by mstehle | 0 Comments
Filed under: ,

FYI: Why are MAPI and CDO 1.21 not supported in managed (.NET) code?

The issue of using MAPI or (most commonly) CDO 1.21 in managed (.NET) code is one that comes back to us a lot on the Messaging Developer Support team. Both the messaging technologies in question and the .NET framework have been around for many years at this point. As well have the KB articles that state the supportability of Outlook and Exchange APIs in managed code. There are three main contributors to steady stream of cases we see – even today – where customers are using MAPI and CDO 1.21 in managed code…

  1. More and more Windows development is done using managed code these days. The .NET Framework has taken hold – especially in the consulting industry – and most custom software consultants use the .NET Framework over C++ or VB6. Many times the decision to use .NET in a solution is an assumption from the beginning and not something evaluated based on the requirements of the application. It can be easy forget in today's environment that you can still write unmanaged code and there are situations where you might have to.
  2. Outlook and Exchange development is a niche – many ISVs and consultants have to get into messaging development to accomplish a small part of a larger application. In other words, they don't do this every day like I do. These developers simply know they need to accomplish a task be it checking an inbox, creating an appointment, or sending an email. They search the web and find a sample that seems to work for them and move on.
  3. CDO 1.21 *appears* to work just fine in managed code. Before entering the ranks of Microsoft and finding myself in this cube thinking about Exchange all day, I too, was a consultant in the wild. I found myself in the situation above – I was writing a .NET Windows Service and needed to check an Inbox. I converted some old VB6 code I had to VB.NET and moved on. Everything worked fine through testing but in production we had this nagging memory leak and an occasional Access Violation which we could never quite figure out. Turns out that many of the problems with using CDO 1.21 or MAPI in managed code didn't show up until our application was under stress or running for a while because they are mainly memory management issues. From a usability perspective, there are no initial red flags or awkwardness to warn you that you are doing something you shouldn't.

Okay, I've heard that before so why exactly is using MAPI or CDO 1.21 not supported in managed code?

MAPI has its own memory management model that conflicts with and is incompatible with the .NET runtime. This the primary reason that MAPI and CDO 1.21 are not supported running in a .NET process. The common symptoms you will see are seemingly random Access Violations and very often memory leaks (especially with CDO 1.21). There is no methodology for avoiding or managing these symptoms by using interop libraries or managing references in a particular fashion in your .NET code – it just won't work.

The trap is that CDO 1.21 and .NET can "appear" to work and you can get pretty far in your dev cycle before you run into problems. Many times we see this come up in soon after a solution is released to production, in late cycle performance testing, or in a pilot program. Opening a critical case with Microsoft when you have end users complaining of crashes or project managers short on budget is not a good time to find out that your solution is unsupportable.

Take a look at Patrick's article on what "unsupported" means. He uses MAPI and .NET as an example in this article for reason #4 that something could be deemed unsupported by Microsoft…

"It has known problems…We KNOW this is a problem, so we don't support it."

Fine, I won't use .NET and MAPI or CDO 1.21 in the same process but I still need to write this application – now what?

The simple answer is you either need to not use .NET or not use MAPI or CDO 1.21. So how do you make that decision?

First let's look at your business requirements to determine where we need to compromise. As I mentioned above a lot of time the decision to write an application in .NET is made long before in depth design has been done and even more frequently the interaction with Exchange is a minimal part of the overall solution. If you are locked into .NET then you can look into alternative APIs that are supported in managed code.

In the pre-Exchange 2007 world, the only supported APIs for managed code from Outlook and Exchange are Outlook Object Model, WebDAV, and CDOEX. Each of these has their limitations:

Outlook Object Model simply automates the Outlook.EXE process and is not supported to run from a service application (Windows Services and ASP.NET applications should not use OOM)

WebDAV is a protocol not an object model and has a steep learning curve (it also has limits on its support for calendaring)

CDOEX is built on top of ExOLEDB which is only intended to be used (and is only supported) on the Exchange server itself – not remotely.

The second thing to consider is why you needed to use MAPI or CDO 1.21 in the first place. MAPI provides a very raw view of the message store without much business logic so you might want to use that to work with item properties or hidden items not available to the other APIs. CDO 1.21 provides a hefty amount of business logic for working with appointments and meetings. Without any noticeable problems upfront when you try to use CDO 1.21 from .NET code, it might seem worth the risk given the options above. If you really feel that CDO 1.21 or MAPI is your best option based on the business requirements of what your application must do then by all means use CDO 1.21 – just plan to use it *out of process* from your .NET code.

Posted by mstehle | 24 Comments

KB: Respond to Meeting Requests via the MeetingItem Interface in CDO 1.21

...We'll be publishing a KB article to establish this support policy update on CDO 1.21.  I'll update this post with KB number, in the meantime, here is the content of the article...

Calling the Respond method to accept or decline a meeting request using CDO 1.21 is only supported through the MeetingItem interface (http://msdn2.microsoft.com/en-us/library/ms527208.aspx).  It is not supported to call Respond to a meeting through the AppointmentItem interface (http://msdn2.microsoft.com/en-us/library/ms526385.aspx) or by calling Respond on an AppointmentItem retrieved from the GetAssociatedAppointment call of the meeting request.

 

...This has to do with the logic implemented in CDO 1.21 to accomodate changes in the calendaring logic of Exchange and Outlook described in the following article, http://msdn2.microsoft.com/en-us/library/aa363947.aspx.

Posted by mstehle | 0 Comments
Filed under: ,

FYI: We're Still Hiring! In Fargo, North Dakota as well!

...If Charlotte, North Carolina is too warm for you - on top of the two openings we have in Charlotte, we have *five* in Fargo, North Dakota.  These positions are for frontline Support Engineers (opening 1, opening 2, opening 3) as well as for Escalation Engineers (opening 1, opening 2).  If you are interested or have questions please email me or leave a comment...

Posted by mstehle | 0 Comments
Filed under:

KB: Exchange Web Services Does Not Honor Inherited Permissions from Server Level Objects

The following KB article was just published based on a case I worked and bug that I filed against Exchange Web Services in Exchange 2007, have a look...

940846 Error message when an account tries to open a mailbox by using Outlook Web Access or Exchange Web Services in Exchange Server 2007: "You do not have permissions to open this mailbox"
http://support.microsoft.com/default.aspx?scid=kb;EN-US;940846

Previously with other Exchange APIs and in earlier versions of Exchange Server if you set Receive-As rights at the server, storage group, organizational level, etc. for a service account then you could access any mailbox under those objects with your service account.  This is *not* the case with Exchange Web Services or Outlook Web Access in Exchange Server 2007.  In Exchange Server 2007, the underlying components shared by EWS and OWA do not aggregate the security descriptors of all the parent level objects of a mailbox to determine access - they only look at the mailbox security descriptor.  To workaround this, as the KB article states, you have two options...

This is issue only affects the shared underlying components of OWA and EWS in Exchange 2007.  It does not affect other Exchange 2007 APIs such as WebDAV, MAPI, and CDO.

...The customer I was working with was using their experience from Exchange 2000/2003 to test their service account configuration for their WebDAV application in Exchange 2007 using OWA.  They had created their service account, applied permissions to a storage group using Add-ADPermission and were using OWA to verify that it was permissioned appropriately to allow access to all mailboxes in a storage group.  They got hung up on the fact that OWA wouldn't allow access and never tested their WebDAV application.  When they finally did a WebDAV test the service account accessed all mailboxes fine - even though they still could access the mailboxes with the service account using OWA.  This is because while OWA and WebDAV were closing tied in Exchange 2000/2003, in Exchange 2007 they are not - Exchange Web Services and Outlook Web Access are more closely related now...

Posted by mstehle | 0 Comments

FYI: We are hiring!

We have a couple job openings (opening 1 & opening 2) on our team.  If you are reading this blog then you must have some interest in what I do day to day.  All of these posts come from cases I have worked so they should give you a good feel for the type of work you would be doing.   Our Messaging Developer Support team supports the API in Outlook and Exchange primarily but we also get into Windows Mail, Outlook Express, and the .NET Framework SMTP mail classes (System.Web.Mail and System.Net.Mail)...

We have a really great team here in Charlotte, NC (to name a few - Dave, Patrick, Walt, Jeff, Steve - he isn't really on our team but we bug him all the time - and Dan) and are looking forward to have some new additions...

Posted by mstehle | 1 Comments
Filed under:
More Posts Next page »
 
Page view tracker