Using a Simple MAPI in API that Runs as a Windows NT Service

Environment: Internet and Networking, E-Mail

Introduction

As you should know, a Win NT service is an application that does not have a user interface and can run (if configured) automatically every time the workstation/server boots. This is an advantage for some applications that need to be executed without user intervention (the user is not required to log in and execute an application) and they’re running permanently in an infinite cycle, waiting for an event to do one or more tasks.

An example of this is the application that I’m developing. In general, its main goals are:

  1. Send via e-mail some documents every time they are modified, to their destination registered on a MSSQL database.
  2. Reply to request of those documents made by clients anywhere.

Enumerating the Problems

The first problem (and the objective of this article) was how to make an application run as a service. I found the article http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mapi/html/_mapi1book_windows_nt_service_client_applications.asp in MSDN that explains it. I would like to take your attention to the following rules so the service can work:

  1. The e-mail account must be configured. This means that you have to log on to Win NT and configure the e-mail on Control Panel + Mail.
  2. The Service has to run with the user-configured mail account, as explained in Point 1. To do this, go to Control Panel + Service + <double-click on the service you want to change> and change the Log On As from System Account to This Account: and input the user name, password, and then confirm the password.
  3. The user has to be a member of the Administrators group on the machine where the service is running. Check the MSDN article for more information.

The second problem was how to read and send e-mail. To do this, I found a class in the article http://codeguru.earthweb.com/internet/imapi.shtml and added some more functionality to read mail to it (great class).

The Solution

The main function to run the service application is the logon using the Mail profile configured in Point 1:

// Global application objects
CIMapi  gMail;
CHAR    gcMailProfileName[MAX_PATH];

HRESULT EfaLogOnMail ()
{
  HRESULT              hRes = S_OK;
  BOOL                 bRes = TRUE;
  MAPIINIT_0           MapiInitParams;
  LPMAPISESSION FAR    lppSession;
  char                 cMsg[1024];

  //******* Get the profile name from the "Mail.ini" file ******//
  bRes = EfaGetConfigOption (INI_FILE, "[Inicializacao]",
                             PROFILE_NAME, gcMailProfileName);
  if (bRes != TRUE)
  {
    sprintf (cMsg, "Não foi possmvel obter o nome do perfil do
             mailn", hRes);
    EfaWriteLog (LOG_FILE, cMsg);
    return (S_FALSE);
  }

//*************** Initializes MAPI *****************************//
  MapiInitParams.ulFlags        = MAPI_NT_SERVICE;
  MapiInitParams.ulVersion      = MAPI_INIT_VERSION;
  hRes = MAPIInitialize ((LPVOID)&MapiInitParams);
  if (hRes != S_OK)
  {
    sprintf (cMsg, "MAPIInitialize falhou com erro = %in",
             hRes);
    EfaWriteLog (LOG_FILE, cMsg);
    return (hRes);
  }

  hRes = OleInitialize (NULL);
  if (hRes != S_OK)
  {
    sprintf (cMsg, "OleInitialize falhou com erro = %in", hRes);
    EfaWriteLog (LOG_FILE, cMsg);
    return (hRes);
  }

  //******* Executes the Log On *******//
  hRes = MAPILogonEx (0, gcMailProfileName, NULL,
                         MAPI_NT_SERVICE +
                         MAPI_NO_MAIL,
                         &lppSession);
  if (hRes != S_OK)
  {
    sprintf (cMsg, "MAPILogonEx falhou com erro = %in", hRes);
    EfaWriteLog (LOG_FILE, cMsg);
    return (hRes);
  }

  // Executes Log On again to initialize the session handle on the
  // CIMAPI class
  bRes = gMail.Logon (gcMailProfileName, NULL);
  if (bRes == FALSE)
  {
    sprintf (cMsg, "CIMapi::Logon falhou com erro = %in",
             gMail.Error
());
    EfaWriteLog (LOG_FILE, cMsg);
    return ((HRESULT)gMail.Error ());
  }

  // Test to send e-mail
  // EfaTestSendMail ();

  // Test to read e-mails
  // EfaTestGetMail ();

  return (bRes);
}

Notes

  1. To be honest, I don’t know if it is possible to debug a service (maybe debugging attaching to a process), so to simply debug the application, just uncomment the lines below on the code and between EfaLogOnMail and EfaLogOffMail add your code to be executed. These lines are just before the code needed for the service definition.
  2.       // COMMENT THE FOLLOWING LINES TO RUN AS A WINNT
          // SERVICE //
          EfaLogOnMail ();
          EfaLogOffMail ();
          return (0);
          // COMMENT THE FOLLOWING LINES TO RUN AS A WINNT
          // SERVICE //
    
  3. Don’t forget to edit “Mail.ini” and change the option ProfileName = <your profile name>.
  4. To install the service, just run the application in command prompt with the following arguments:
  5.     To Install   -> Mail.exe -i <Path to executable>
        To Uninstall -> Mail.exe -u
        To display this message -> Mail.exe -h
    
  6. I’m sorry for the log and commented messages. I didn’t have time to translate all of them.

I hope this can be helpful.

Downloads

Download source – 123 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read