Mail viewer sample.

Mail viewer sample - demonstrates how to work with mailboxes contents with using Mail Processor API.

Any mail message stored at any mail program has the following properties: From, To, Subject, message Text. If you need to get these properties from MS Outlook, you must use MAPI or EMAPI or direct reading the PST files - it is hard work. Suppose that you want to connect to your application MS Outlook Express, you do the difficult work again.

Mail Processor API Idea that you use the same code for MS Outlook and MS Outlook Express. We intentionally did Mail Processor API is very simple, please download Mail Viewer and see how it source code is easy.

Here is an example of source code. The code prints mail messages fields From, To, and Subject of all MS Outlook Express mail messages. Simply replace 'MSOE' in OpenMailbox to MS Outlook. PST file name and this code will work for MS Outlook.

program MailViewerConsole;
{$APPTYPE CONSOLE}
uses
  SysUtils,Windows, Engine.pas;
var
  Handle: dword; //Handle of opened mailbox
  FolderCount, MailCount: integer; //folders and mails counters
  MailProp: TMailProp; //mail message properties
begin
  Handle := OpenMailbox('MSOE'); //try open MS Outlook Express default mailbox
  if Handle > OMS_NOERROR then //if mailbox is opened
   for FolderCount := 0 to GetFolderCount(Handle)-1 do //enumerate all MS Outlook Express folders
    for MailCount := 0 to GetMailCount(Handle, FolderCount)-1 do //enumerate all mail messages
       if GetMailProp(Handle, FolderCount, MailCount, MailProp) = OMS_OK then //get mail message properties
          //print mail message properties on the output device
          WriteLn(StrPas(MailProp.SenderName) + #9 + StrPas(MailProp.RecipientNames) + #9 + StrPas(MailProp.Subject));
   ReadLn;
end.

The source code would look like getting the same field from MS Outlook using MS Outlook EMAPI. Why waste your time?

function GetMessageProp: dword;
var
  hr: dword;
  SourceMessage: MapiDefs.IMessage; //message save routine
  pMalloc: pointer; //buffer for message save
  cbStrSize: dword; //file name size
  lpWideCharStr: PWideChar; //file name in widechar
  Param: cardinal; //for lpMessage.CopyTo empty value
  Storage: IStorage; //for save massages store object
  MsgSession: PMSGSESS; //function creates and opens a message session that groups the messages created within it
  Tags: pSPropTagArray; //tags for query emapi obects
  pMessageProperty: PSPropValue; // message subject (get single properties demo)
  _Time, _Time2: FileTime;
  SysTime: _SystemTime;
  g_sptMsgProps: PSPropTagArray;
  pProps: PSPropValue;
  cVals: ULONG;

  function GetOneMessageProperty(pMessage: MapiDefs.IMessage; PropertyTag: ULONG): string;
  var
    pMessageProperty: PSPropValue; // message subject (get single properties demo)
  begin
    result := '';
    if HrGetOneProp(pMessage, PropertyTag, pMessageProperty) = S_OK then
    begin
      result := WideCharToString(PWideChar(pMessageProperty.Value.lpszW));
      MAPIFreeBuffer(pMessageProperty);
    end;
  end;

  procedure GetOneMessageString8Property(lpMessage: MapiDefs.IMessage; PropertyTag: ULONG; var Text: string);
  begin
    if HrGetOneProp(lpMessage, PropertyTag, pMessageProperty) = S_OK then
    begin
      Text := pMessageProperty.Value.lpszA;
      MAPIFreeBuffer(pMessageProperty);
    end;
  end;

begin
  result := OMS_NOT;
  InitMAPILibrary; //Load MAPI32.DLL
  MAPIInitialize(nil); //Initilize Extendex Messaging API
  pMalloc := MAPIGetDefaultMalloc;
  cbStrSize := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PAnsiChar(MSGFileName), -1, lpWideCharStr, 0);
  MAPIAllocateBuffer(cbStrSize * sizeof(WCHAR), pointer(lpWideCharStr));
  MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PAnsiChar(MSGFileName), -1, lpWideCharStr, cbStrSize);

  //try access to EMAPI Storage
  hr := StgOpenStorage(lpWideCharStr, nil, STGM_READ or STGM_SHARE_DENY_WRITE, 0, 0, Storage);
  if hr = S_OK then
  begin //"login" to current session
    OpenIMsgSession(IMalloc(pMalloc), 0, MsgSession);
    OpenIMsgOnIStg(MsgSession, @MAPIAllocateBuffer, @MAPIAllocateMore, @MAPIFreeBuffer,
      IMalloc(pMalloc), nil, Storage, TMSGCALLRELEASE(nil^), 0, 0, SourceMessage);

    g_sptMsgProps := SizedSPropTagArray2(1);
    g_sptMsgProps.aulPropTag[0] := PR_HASATTACH;
    cVals := 0;
    pProps := nil;

    //get MSG (MS Outlook) mail message interface
    SourceMessage.GetProps(g_sptMsgProps, 0, cVals, pProps);
    //Get mail message propertis with using EMAPI Tags
    //Please out this variables self
    Name := GetOneMessageProperty(SourceMessage, PR_SENDER_NAME_W);
    Sender.Address := GetOneMessageProperty(SourceMessage, PR_SENDER_EMAIL_ADDRESS_W);
    FromName := GetOneMessageProperty(SourceMessage, PR_SENDER_NAME_W);
    FromAddress := GetOneMessageProperty(SourceMessage, PR_SENDER_EMAIL_ADDRESS_W);
    Recipients.EMailAddresses := GetOneMessageProperty(SourceMessage, PR_DISPLAY_TO_W);
    CCList := GetOneMessageProperty(SourceMessage, PR_DISPLAY_CC_W);
    BCCList := GetOneMessageProperty(SourceMessage, PR_DISPLAY_BCC_W);

    if HrGetOneProp(SourceMessage, PR_CLIENT_SUBMIT_TIME, pMessageProperty) = S_OK then
    begin
      _Time.dwLowDateTime := pMessageProperty.Value.ft.dwLowDateTime;
      _Time.dwHighDateTime := pMessageProperty.Value.ft.dwHighDateTime;
      FileTimeToLocalFileTime(_Time, _Time2);
      FileTimeToSystemTime(_Time2, SysTime);
      MAPIFreeBuffer(pMessageProperty);
    end
    else
      if HrGetOneProp(SourceMessage, PR_CREATION_TIME, pMessageProperty) = S_OK then
      begin
        _Time.dwLowDateTime := pMessageProperty.Value.ft.dwLowDateTime;
        _Time.dwHighDateTime := pMessageProperty.Value.ft.dwHighDateTime;
        FileTimeToLocalFileTime(_Time, _Time2);
        FileTimeToSystemTime(_Time2, SysTime);
        MAPIFreeBuffer(pMessageProperty);
      end;

    GetOneMessageString8Property(SourceMessage, PR_BODY_HTML_A, HTML_Text);
    result := OMS_OK;
  end;
end;