Windows service retrieve/send mails via Exchange server (without POP3).

Hi,

I need to adapt a service to retrieve/send mails via an Exchange server (without POP3 communication). In a test application I used components in the Servers, which seemed to work fine. While incorporating this in the service I came across this site: "The Outlook Object Model is unsuitable to run in a Windows service" (http://support.microsoft.com/?kbid=237913). So my question now is what is the best way to handle this. Just incorporate the components into my service or use another solution? Thanks.

Regards,
Wim.
ecomasterAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jhanceCommented:
Exchange supports multiple methods of communicating with clients and POP3 is only one of them.  It also supports IMAP as well as MAPI which is the API that Outlook uses to communicate with Exchange.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Hamlet10Commented:
Hi Wim,

I recently had the same issues. I was for security reasons not allowed to access the Exchange server using POP3. IMAP4, or WebDAV.

Instead I used CDO objects which works fine. The windows service I  have written takes emails tha arrive into the mail box are transfers the information to a SQL server.


I can include all of the code from the windows service if you would like.



Regards


Hamlet
ecomasterAuthor Commented:
Thanks Hamlet10, that would be a great help!
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

Hamlet10Commented:
Wim,

Here is teh code I used as requested. It is a but messy but If you open it in VS the colour coding should clear things up slightly.

=============================================================


Imports Outlook = Microsoft.Office.Interop.Outlook
Imports System.Runtime.InteropServices


Public Class clsEmailRetriever
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Dim EmailLog As New EventLog

    Public Sub Main()

        Dim cdoSession As MAPI.Session
        Dim cdoFolder As MAPI.Folder
        Dim cdoField As MAPI.Field


        Dim strLabels As String
        Dim strLabelName As String
        Dim strAllLabels As String
        Dim strChar As String
        Dim j As Integer
        Dim Messages As MAPI.Messages
        Dim Message As MAPI.Message


        Dim sendMail As MAPI.Message

        ' create a new event log
        EmailLog.Source = "Email Log"



        Dim EntryID As String
        Dim StoreID As String
        Dim oldFolderEntryID As String
        Dim ForecastInValue As String
        Dim ForecastOutValue As String


        EntryID = Me.GetConfigSetting("EntryID")
        StoreID = Me.GetConfigSetting("StoreID")

        ForecastInValue = Me.GetConfigSetting("ForecastInValue")
        ForecastOutValue = Me.GetConfigSetting("ForecastOutValue")

        Dim i As Integer

        ' Create Outlook application.
        cdoSession = CreateObject("MAPI.Session")

        cdoSession.Logon("Forecast Data", , False, True)


        cdoFolder = cdoSession.GetFolder(EntryID, StoreID)


        Messages = cdoFolder.Messages()



        Dim Subject As String

        Dim m As Int32
        Dim Item As Integer

        Dim msgType As String = "Invalid"

        Dim Body As String
        For Each Message In cdoFolder.Messages()

            Try
                Subject = String.Empty
                Subject = Message.Subject


                msgType = String.Empty
                Body = String.Empty

                If Subject.IndexOf(ForecastOutValue) > 0 Then
                    msgType = "ForecastsOut"

                ElseIf Subject.IndexOf(ForecastInValue) > 0 Then
                    msgType = "ForecastsIn"

                End If

                Dim Data() As String
                Dim DataHeader() As String

                If msgType = "ForecastsIn" Then

                    Body = Message.Text

                    Body = Body.Replace(Chr(13) & Chr(10) & Chr(9), ",")
                    Body = Body.Replace(Chr(13) & Chr(10) & Chr(13) & Chr(10), "%")


                    Data = Body.Split("%")

                    DataHeader = Data(0).Split(" ")

                    Body = Data(1).Replace(Chr(9), "")

                    Body = Body.Replace("Notes,", ("Notes," & DataHeader(5) & " " & DataHeader(6)))
                    'Replace invalid characters here
                    'Replace
                    'Forecast Time,Windspeed (m/s),Direction (°N),Temperature (°C)
                    'with
                    'Forecast Time Windspeed (m/s),Direction (ºN),Temperature (ºC)
                    Body = Body.Replace("Direction (°N),Temperature (°C)", "Direction (ºN),Temperature (ºC)")
                    Body = Body.Replace(",Windspeed (m/s),", " Windspeed (m/s),")

                    Body = (Body & Chr(13) & Chr(10))

                    EmailLog.WriteEntry("Email Log", "Email Processed: " & Subject, EventLogEntryType.Information)
                    CreateFile(msgType, Body)
                    Message.Unread = False
                    Message.Update()
                    Message.MoveTo(oldFolderEntryID)

                ElseIf msgType = "ForecastsOut" Then
                    Body = Message.Text
                    Body = Body.Replace(Chr(13) & Chr(10) & "Windspeed", "Windspeed")
                    Body = Body.Replace("," & Chr(13) & Chr(10), ", " & Chr(13) & Chr(10))
                    EmailLog.WriteEntry("Email Log", "Email Processed: " & Subject, EventLogEntryType.Information)
                    CreateFile(msgType, Body)
                    Message.Unread = False
                    Message.Update()
                    Message.MoveTo(oldFolderEntryID)
                End If


                Body = String.Empty

            Catch ex As Exception
                EmailLog.WriteEntry("Email Log", "There was an error retrieving an email: " & Subject, EventLogEntryType.Warning)
                EmailLog.WriteEntry("Email Log", "Error: " & ex.ToString, EventLogEntryType.Error)
                EmailLog.WriteEntry("Email Log", "StackTrace: " & ex.StackTrace, EventLogEntryType.Error)

            End Try

           

        Next

        cdoSession.Logoff()



        cdoSession = Nothing
        cdoFolder = Nothing
        cdoField = Nothing

    End Sub
    Public Sub Delete(ByVal fileName As String)
        EmailLog.Source = "Email Log"
        Try
            System.IO.File.Delete(fileName)
        Catch ex As Exception
            EmailLog.WriteEntry("Email Log", "There was an error deleting a file", EventLogEntryType.Warning)
            EmailLog.WriteEntry("Email Log", "Error: " & ex.ToString, EventLogEntryType.Error)
            EmailLog.WriteEntry("Email Log", "StackTrace: " & ex.StackTrace, EventLogEntryType.Error)
        End Try
    End Sub
    Public Sub CreateFile(ByVal msgType As String, ByVal Body As String)
        EmailLog.Source = "Email Log"
        Dim FileName As String
        Select Case msgType
            Case "ForecastsIn"
                FileName = Me.GetConfigSetting("ForecastInQueue")
            Case "ForecastsOut"

                FileName = Me.GetConfigSetting("ForecastOutQueue")
        End Select

        FileName = FileName & Guid.NewGuid().ToString() & Date.Now.Millisecond & ".txt"
        EmailLog.WriteEntry("Email Log", "Filename: " & FileName, EventLogEntryType.Information)
        If Me.DoesExist(FileName) Then
            Me.Delete(FileName)
        End If


        Try
            Dim objFileStream As System.IO.FileStream
            objFileStream = System.IO.File.Create(FileName)
            objFileStream.Close()
            Dim objFileWrite As System.IO.StreamWriter = System.IO.File.AppendText(FileName)

            objFileWrite.Write(Body)

            objFileWrite.Close()
        Catch ex As Exception
            EmailLog.WriteEntry("Email Log", "There was an error writing a file: " & FileName, EventLogEntryType.Warning)
            EmailLog.WriteEntry("Email Log", "Error: " & ex.ToString, EventLogEntryType.Error)
            EmailLog.WriteEntry("Email Log", "StackTrace: " & ex.StackTrace, EventLogEntryType.Error)
        End Try

    End Sub
    Public Shared Function DoesExist(ByVal fileName As String) As Boolean

        Dim bReturnedValue As Boolean = False

        If System.IO.File.Exists(fileName) Then
            bReturnedValue = True
        Else
            bReturnedValue = False
        End If

        Return bReturnedValue

    End Function

    Private Function GetConfigSetting(ByVal key As String) As String
        Dim doc As New Xml.XmlDocument
        Dim strValue As String = String.Empty

        Try
            doc.Load("C:\Projects\EmailService\EmailRetrieve\Config.xml")
            strValue = doc.DocumentElement.SelectSingleNode(key).InnerText

        Catch ex As Exception
            strValue = String.Empty
            EmailLog.WriteEntry("Email Log.GetConfigurationSettings", "There was an error wgetting the congif settings " & ex.Message, EventLogEntryType.Warning)
        End Try

        Return strValue

    End Function



End Class
ecomasterAuthor Commented:
Thanks for the code, but for the moment I can't rely on CDO, since it's not installed by default during MS Office installation. So at the moment I'm looking for alternatives.
Hamlet10Commented:
Here is some webdav code for access an exchange server. It is in C sharp.

Hope this is helpful


  try

                        {

                              ADODB.Connection oCn = new ADODB.Connection();

                              ADODB.Recordset oRs = new ADODB.Recordset();


                              ADODB.Fields oFields;
                              ADODB.Field oField;

                              // TODO:

                              string sFdUrl = "http://exh1/Exchange/cistest/Inbox";

 

                              oCn.Provider = "MSDAIPP.DSO";

                              oCn.Open(sFdUrl, "USERNAME", "PASSWORD", -1);

                               if(oCn.State == 1)
                              {
                                    Console.WriteLine("Good Connection");
                              }

                              else

                              {

                                    log.Error("Failed to connect to mail server : " + sFdUrl) ;

                              }



                              string strSql;

                              strSql = "";

                              strSql = "select ";

                              strSql = strSql + " \"urn:schemas:mailheader:content-class\"";

                              strSql = strSql + ", \"DAV:href\" ";

                              strSql = strSql + ", \"urn:schemas:mailheader:content-class\" ";

                              strSql = strSql + ", \"DAV:displayname\" ";

                              strSql = strSql + ", \"urn:schemas:mailheader:subject\" ";

                              strSql = strSql + ", \"DAV:subject\" ";

                              strSql = strSql + ", \"urn:schemas:mailheader:date\" ";

                              strSql = strSql + ", \"DAV:date\"";

                              strSql = strSql + " from scope ('shallow traversal of " + "\"";

                              strSql = strSql + sFdUrl + "\"') ";

                              strSql = strSql + " WHERE \"DAV:ishidden\" = false";

                              strSql = strSql + " AND \"DAV:isfolder\" = false";

 

 

                              oRs.Open(strSql, oCn,

                                    ADODB.CursorTypeEnum.adOpenUnspecified,

                                    ADODB.LockTypeEnum.adLockOptimistic, 1);

                       

 

                              oRs.MoveFirst();

                              while(!oRs.EOF )

                              {

                                    IFormatProvider culture = new CultureInfo("en-IE", true);

                                    string localDate = oRs.Fields["urn:schemas:mailheader:date"].Value.ToString() ;

 

                                    DateTime mailDate = DateTime.Parse(localDate,

                                          culture,

                                          DateTimeStyles.NoCurrentDateDefault);

                                    if(this.testStarted.CompareTo(mailDate) == -1)

                                    {

                                          log.Error("The error " + oRs.Fields["DAV:displayname"].Value.ToString() + " occoured please see " + oRs.Fields["DAV:href"].Value.ToString()) ;

 
                                          Trace.Write("Showing Mail For : " + mailDate.ToShortDateString() + " " +  mailDate.ToShortTimeString());

                                    }
                                    else
                                    {
                                        Trace.Write("Not showing : " + mailDate.ToShortDateString() + " " +  mailDate.ToShortTimeString()) ;
                                    }
                                    oRs.MoveNext() ;

                              }
                        }

                        catch(Exception ex)
                        {
                              Assert.Fail("Mail Retrival Failed. " + ex.Message + " " + ex.StackTrace) ;
                        }

}
AJesaniCommented:
Use of CDO Objects require Outlook to be installed on your machine and will use outlook configurations.
WebDav is kind of complicated to use. IMAP will be the best solution to retrieve emails
and Exchange SMTP to send emails - you can use System.Web.Mail in ASP.NET and specify smtp server as exchange to send emails.
For IMAP, if you want I can send you a simple Project, which has been written to retrieve emails thru IMAP.

Thanks,
Amit
ecomasterAuthor Commented:
I found just what I was looking for on this site: www.evocorp.com/Delphi/ADDExtendedMapi.htm. Thanks for the tips and pointing me in the right direction.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming

From novice to tech pro — start learning today.