//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/c5607871-120e-404c-9042-2603fb37af10/POP3/DELPHI20/MAIN.PAS

//Warning: This code has been marked up for HTML

{/***************************************************************************
$name: UNIT1.PAS 
$version: 1.0 
$date_modified: 121498 
$description: This example uses a modified version of the Delphi 2.01 POP3
              mail example to add POP3 mail messages to your GroupWise
              mailbox. It requires the following NetManage OCX class='delphiKeyword'>and dll's
              that are included with Delphi 2.01: NMOCOD.DLL, NMORENU.DLL,
              NMSCKN.DLL, POPCT.OCX.  Make sure NMOCOD.DLL class='delphiKeyword'>and the POPCT.OCX
              file are registered on the machine this app is on.
$owner: GroupWise SDK Team Lead
Copyright (c) 1998 Novell, Inc. All Rights Reserved.

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
CUSTOMERS WITH RESPECT TO THIS CODE.
****************************************************************************/}

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, Buttons, ExtCtrls, OleCtrls, ISP;

type
  TMainForm = class(TForm)
    POP1: TPOP;
    PageControl1: TPageControl;
    ConPage: TTabSheet;
    GroupBox1: TGroupBox;
    ePOPServer: TEdit;
    Label6: TLabel;
    Label5: TLabel;
    eUserName: TEdit;
    ePassword: TEdit;
    Label4: TLabel;
    Panel2: TPanel;
    ConnectStatus: TStatusBar;
    POPConnectBtn: TButton;
    CloseBtn: TButton;
    mReadMessage: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure POP1StateChanged(Sender: TObject; State: Smallint);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure POP1ProtocolStateChanged(Sender: TObject;
      ProtocolState: Smallint);
    procedure POP1Error(Sender: TObject; Number: Smallint;
      var Description: string; Scode: Integer; const Source,
      HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);
    procedure POPConnectBtnClick(Sender: TObject);
    procedure ePOPServerChange(Sender: TObject);
    procedure POP1DocOutput(Sender: TObject; const DocOutput: Variant);
    procedure udCurMessageClick(Sender: TObject; Button: TUDBtnType);
    procedure POP1RefreshMessageCount(Sender: TObject; Number: Integer);
    procedure FormActivate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Login;
    procedure Logout;
    procedure MakeMessage(popSubject, popBodyText, popFromText : string);
    procedure NextMessage;
    procedure CloseBtnClick(Sender: TObject);

  private
    RecvVerified,
    POPError: Boolean;
    FMessageCount, iMessage: Integer;
    popSubject, popBodyText, popFromText: string;
  end;

var
  MainForm: TMainForm;
  GWobj, RAobj : Variant;

implementation

{$R *.DFM}

uses OLEAuto;

const
  icDocBegin = 1;
  icDocHeaders = 2;
  icDocData = 3;
  icDocEnd = 5;

{When calling a component method which maps onto an OLE call, NoParam substitutes
for an optional parameter. As an alternative to calling the component method, you
may access the component's OLEObject directly -
i.e., Component.OLEObject.MethodName(,Foo,,Bar)}
function NoParam: Variant;
class='delphiKeyword'>begin
  TVarData(Result).VType := varError;
  TVarData(Result).VError := DISP_E_PARAMNOTFOUND;
end;

procedure TMainForm.FormCreate(Sender: TObject);
class='delphiKeyword'>begin
  POPError := False;
  FMessageCount := 0;
  iMessage := 1;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
class='delphiKeyword'>begin
  if POP1.State = prcConnected then POP1.Quit;
end;

procedure TMainForm.ePOPServerChange(Sender: TObject);
class='delphiKeyword'>begin
   POPConnectBtn.Enabled := (ePOPServer.Text <> '') class='delphiKeyword'>and (eUsername.Text <> '') class='delphiKeyword'>and
                            (ePassword.Text <> '');
end;

{Unlike SMTP, users must be authorized on the POP server. The component defines
a special protocol state, popAuthorization, when it requests authorization. If
authorization is successful, the protocol state changes to popTransaction class='delphiKeyword'>and
POP commands can be issued. Note that server connection is independent of the
authorization state.}
procedure TMainForm.POP1ProtocolStateChanged(Sender: TObject;
  ProtocolState: Smallint);
class='delphiKeyword'>begin
  class='delphiKeyword'>case ProtocolState of
    popAuthorization:
      POP1.Authenticate(POP1.UserID, POP1.Password);
    popTransaction:
      ConnectStatus.SimpleText := Format('User %s authorized on server %s', [eUsername.Text,
        ePOPServer.Text]);
  end;
end;

{This event is called every time the connection status of the POP server changes}
procedure TMainForm.POP1StateChanged(Sender: TObject; State: Smallint);
class='delphiKeyword'>begin
  class='delphiKeyword'>case State of
    prcConnecting:
      ConnectStatus.SimpleText := 'Connecting to POP server: '+POP1.RemoteHost+'...';
    prcResolvingHost:
      ConnectStatus.SimpleText := 'Resolving Host';
    prcHostResolved:
      ConnectStatus.SimpleText := 'Host Resolved';
    prcConnected:
      class='delphiKeyword'>begin
        ConnectStatus.SimpleText := 'Connected to POP server: '+POP1.RemoteHost;
        POPConnectBtn.Caption := '&Disconnect';
      end;
    prcDisconnecting:
      ConnectStatus.SimpleText := 'Disconnecting from POP server: '+POP1.RemoteHost+'...';
    prcDisconnected:
      class='delphiKeyword'>begin
        ConnectStatus.SimpleText := 'Disconnected from POP server: '+POP1.RemoteHost;
        POPConnectBtn.Caption := 'Get Mail';
      end;
   end;
   ePOPServer.Enabled := not (State = prcConnected);
   eUsername.Enabled := not (State = prcConnected);
   ePassword.Enabled := not (State = prcConnected);
end;

{The Error event is called whenever an error occurs in the background processing. In
addition to providing an error code class='delphiKeyword'>and brief description, you can also access the POP
component's Errors property (of type icErrors, an OLE object) to get more detailed
information}
procedure TMainForm.POP1Error(Sender: TObject; Number: Smallint;
  var Description: string; Scode: Integer; const Source, HelpFile: string;
  HelpContext: Integer; var CancelDisplay: Wordbool);
  var
  I: Integer;
  ErrorStr: string;
class='delphiKeyword'>begin
  POPError := True;
  CancelDisplay := True;
  if POP1.ProtocolState = popAuthorization then
    ConnectStatus.SimpleText := 'Authorization error';
  {Get extended error information}
  for I := 1 to POP1.Errors.Count do
    ErrorStr := Format(#13'(%s)', [POP1.Errors.Item(I).Description]);
  {Display error code, short class='delphiKeyword'>and long error description}
  MessageDlg(Format('%d - %s%s', [Number, Description, Trim(ErrorStr)]), mtError, [mbOK], 0);
end;

{POP requires a valid user account on the host machine}
procedure TMainForm.POPConnectBtnClick(Sender: TObject);
class='delphiKeyword'>begin
  if (POP1.State = prcConnected) class='delphiKeyword'>and (POP1.ProtocolState = popTransaction)
  class='delphiKeyword'>and not POP1.Busy then
  class='delphiKeyword'>begin
    mReadMessage.Lines.Clear;
    POP1.Quit;
  end
  else
    if POP1.State = prcDisconnected then
    class='delphiKeyword'>begin
      POP1.RemoteHost := ePOPServer.Text;
      POP1.UserID := eUserName.Text;
      POP1.Password := ePassword.Text;
      POP1.Connect(NoParam, NoParam);
    end;
end;

{The DocOutput event is the just like the DocInput event in 'reverse'. It is called each time
the component's DocOutput state changes during retrieval of mail from the server. When the
state = icDocData, you can call DocOutput.GetData to decode each data block based on the MIME
content type specified in the headers.}
procedure TMainForm.POP1DocOutput(Sender: TObject;
  const DocOutput: Variant);
var
  Buffer: Variant;
  I: Integer;
class='delphiKeyword'>begin
  class='delphiKeyword'>case DocOutput.State of
    icDocBegin:
      ConnectStatus.SimpleText := 'Initiating document transfer';
    icDocHeaders:
      class='delphiKeyword'>begin
        ConnectStatus.SimpleText := 'Retrieving headers';
        for I := 1 to DocOutput.Headers.Count do
         class='delphiKeyword'>begin
          //mReadMessage.Lines.Add(DocOutput.Headers.Item(I).Name+': '+

                                 //DocOutput.Headers.Item(I).Value);

          if DocOutput.Headers.Item(I).Name = 'Subject' then
             popSubject := DocOutput.Headers.Item(I).Value;
          if DocOutput.Headers.Item(I).Name = 'From' then
             popFromText := DocOutput.Headers.Item(I).Value;
         end;
      end;
    icDocData:
      class='delphiKeyword'>begin
        ConnectStatus.SimpleText := Format('Message: '+ intToStr(iMessage) + ' of ' + inttostr(fMessageCount) + '   Retrieving data - %d bytes',
            [Trunc(DocOutput.BytesTransferred)]);
        DocOutput.GetData(Buffer);
        mReadMessage.Text := mReadMessage.Text + Buffer;
        popBodyText := mReadMessage.Text;
      end;
    icDocEnd:
      if POPError then
        ConnectStatus.SimpleText := 'Transfer aborted'
      else
       class='delphiKeyword'>begin
        ConnectStatus.SimpleText := Format('Message: '+ intToStr(iMessage) + ' of ' + inttostr(fMessageCount) + '   Retrieval complete (%d bytes data)',
          [Trunc(DocOutput.BytesTransferred)]);
        MakeMessage(popSubject, popBodyText, popFromText);
        NextMessage;
       end;
  end;
  ConnectStatus.Update;
end;

{Retrieve message from the server}
procedure TMainForm.udCurMessageClick(Sender: TObject; Button: TUDBtnType);
class='delphiKeyword'>begin
  if (POP1.State = prcConnected) class='delphiKeyword'>and (POP1.ProtocolState = popTransaction) then
  class='delphiKeyword'>begin
    POPError := False;
    mReadMessage.Lines.Clear;
  end;
end;

{The RefreshMessageCount event is called whenever the RefreshMessageCount method is
called, class='delphiKeyword'>and also when a connection to the POP server is first made}
procedure TMainForm.POP1RefreshMessageCount(Sender: TObject; Number: Integer);
class='delphiKeyword'>begin
  FMessageCount := Number;
  if Number > 0 then
  class='delphiKeyword'>begin
    POP1.RetrieveMessage(iMessage);
  end;
end;

{This is the only procedure besides logging in that deals with the GroupWise ObjectAPI
It uses the current logged in user class='delphiKeyword'>as the recipient class='delphiKeyword'>and adds all messages to that users
mailbox.  So all mail in the GroupWise mailbox is to RootAccount.Owner.EmailAddress class='delphiKeyword'>and
any "reply" made to a message added by this procedure would also be to the same user not
to the "FromText" user name.}
procedure TMainForm.MakeMessage(popSubject, popBodyText, popFromText : string);
var
   Msg, Recpt, MailMsg : Variant;
class='delphiKeyword'>begin
   MailMsg := RAobj.MailBox.Messages.Add('GW.MESSAGE.MAIL.Internet'); {Add message subtype "internet" to match the GroupWise SMTP gateway}
   MailMsg.Subject := popSubject;
   MailMsg.BodyText := popBodyText;
   MailMsg.ViewName := 'Internet';  {Changed the viewname to match the GroupWise SMTP gateway viewname}
   MailMsg.FromText := popFromText + '                                                                             ';
   Recpt := MailMsg.Recipients.Add(RAobj.Owner.EmailAddress); {Send message to owner}
   Recpt.Resolve;
   Msg := MailMsg.Send;
   Msg.Delete; {Delete outbox message item}
end;

procedure TMainForm.NextMessage;
class='delphiKeyword'>begin
  if (POP1.State = prcConnected) class='delphiKeyword'>and (POP1.ProtocolState = popTransaction) then
   class='delphiKeyword'>begin
    POPError := False;
    mReadMessage.Lines.Clear;
    if iMessage < FMessageCount then
      class='delphiKeyword'>begin
       iMessage := iMessage + 1;
       POP1.RetrieveMessage(iMessage);
      end
    else
      if (POP1.State = prcConnected) class='delphiKeyword'>and (POP1.ProtocolState = popTransaction)
         class='delphiKeyword'>and not POP1.Busy then
         class='delphiKeyword'>begin
            mReadMessage.Lines.Clear;
            POP1.Quit;
         end;
   end;
end;

procedure TMainForm.FormActivate(Sender: TObject);
class='delphiKeyword'>begin
   ePOPServer.SetFocus;
   POPConnectBtn.Enabled := (ePOPServer.Text <> '') class='delphiKeyword'>and (eUsername.Text <> '') class='delphiKeyword'>and
                            (ePassword.Text <> '');
end;

procedure TMainForm.FormShow(Sender: TObject);
class='delphiKeyword'>begin
      Login;
end;

{Login}
procedure TMainForm.Login;
class='delphiKeyword'>begin
      GWobj := CreateOleObject('NovellGroupWareSession');
      RAobj := GWobj.Login('','/ph-?');
end;

{Logout}
procedure TMainForm.Logout;
class='delphiKeyword'>begin
   GWobj := Unassigned;
   RAobj := Unassigned;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
class='delphiKeyword'>begin
   Logout;
end;

procedure TMainForm.CloseBtnClick(Sender: TObject);
class='delphiKeyword'>begin
  Application.Terminate;
end;

end.