/*
  ICS SSL POP3 Excercizer - C++Builder translation of the Delphi demo OverbyteIcsSslMailRcv1.pas
  (demos-delphi-vcl), ICS V9.8.

  Shows how to use TSslPop3Cli: each button runs one asynchronous POP3 command, and the result
  arrives in OnRequestDone. TLS can be implicit (port 995) or explicit (STLS). XOAuth2 and
  OAuthBearer logins get their token from TIcsRestEmail; hardcode your Google or Microsoft client
  application account in SetupOAuth2 to use them. "Get All" chains Stat, Uidl and Retr through
  OnRequestDone to save every message to a file named after its UIDL.

  How this C++ version differs from the Delphi original, apart from syntax:
  - Exec takes the POP3 command as a lambda instead of a TPop3NextProc method pointer.
  - The empty OnSslVerifyPeer and OnSslHandshakeDone handlers (their bodies were commented out in
    V9.6, the work is now done in TWSocket) are not translated, so their .dfm bindings are removed
    and SetSslVerifyProps does not assign them.
  - Get All writes each message with a TFileStream (the raw bytes of each line plus CRLF) instead of
    a Pascal TextFile.
  - The header includes OverbyteIcsPop3Prot.hpp with the Windows GetUserName macro undefined:
    otherwise reading TPop3Cli::UserName calls GetUserNameW, which the library does not export
    (its #pragma alias uses the classic Win32 name mangling, which ld.lld ignores).
*/

#include <vcl.h>
#pragma hdrstop

#include <System.SysUtils.hpp>

#include "OverbyteIcsSslMailRcv1.h"
#include "OverbyteIcsSslMailRcv2.h"
#include "OverbyteIcsIniFiles.hpp"

#pragma package(smart_init)
#pragma link "OverbyteIcsOAuthFormVclE"
#pragma link "OverbyteIcsPop3Prot"
#pragma link "OverbyteIcsSslBase"
#pragma link "OverbyteIcsSslHttpOAuth"
#pragma link "OverbyteIcsTypes"
#pragma link "OverbyteIcsWndControl"
#pragma resource "*.dfm"

TPOP3ExcercizerForm *POP3ExcercizerForm;

namespace {
const wchar_t *const SectionWindow = L"Window";
const wchar_t *const KeyTop = L"Top";
const wchar_t *const KeyLeft = L"Left";
const wchar_t *const KeyWidth = L"Width";
const wchar_t *const KeyHeight = L"Height";
const wchar_t *const SectionData = L"Data";
const wchar_t *const KeyHost = L"Host";
const wchar_t *const KeyPort = L"Port";
const wchar_t *const KeyUserName = L"UserName";
const wchar_t *const KeyPassword = L"Password";
const wchar_t *const KeyAuth = L"Authentication";
const wchar_t *const SectionSsl = L"SSL";
const wchar_t *const KeySslType = L"SslType";
const wchar_t *const KeyCaFile = L"CAFile";
const wchar_t *const KeyCaPath = L"CAPath";
const wchar_t *const KeyVerify = L"VerifyCert";
const wchar_t *const KeyOAuth2ExtBrow = L"OAuth2ExtBrow";
const wchar_t *const KeyOAuth2UserAuth = L"OAuth2UserAuth";

// A UIDL may hold any printable ASCII character (RFC 1939), some of which Windows file names refuse.
String SafeFileName(const String &Name)
{
    String result = Name;
    for (int i = 1; i <= result.Length(); ++i) {
        if (String("\\/:*?\"<>|").Pos(result[i]) > 0)
            result[i] = L'_';
    }
    return result;
}
}

__fastcall TPOP3ExcercizerForm::TPOP3ExcercizerForm(TComponent *Owner)
    : TForm(Owner), FInitialized(false), FGetAllState(0)
{
}

void __fastcall TPOP3ExcercizerForm::FormCreate(TObject *Sender)
{
    Caption = Caption + IcsVerLitSample;   // common ICS sample caption: version and date
    FIniFileName = GetIcsIniFileName();
}

void __fastcall TPOP3ExcercizerForm::FormShow(TObject *Sender)
{
    if (FInitialized)
        return;
    FInitialized = true;

    std::unique_ptr<TIcsIniFile> ini(new TIcsIniFile(FIniFileName, true));
    Top = ini->ReadInteger(SectionWindow, KeyTop, (Screen->Height - Height) / 2);
    Left = ini->ReadInteger(SectionWindow, KeyLeft, (Screen->Width - Width) / 2);
    Width = ini->ReadInteger(SectionWindow, KeyWidth, Width);
    Height = ini->ReadInteger(SectionWindow, KeyHeight, Height);
    HostEdit->Text = ini->ReadString(SectionData, KeyHost, "pop.hostname.com");
    PortEdit->Text = ini->ReadString(SectionData, KeyPort, "995");
    UserNameEdit->Text = ini->ReadString(SectionData, KeyUserName, "");
    PassWordEdit->Text = ini->ReadString(SectionData, KeyPassword, "");
    AuthComboBox->ItemIndex = ini->ReadInteger(SectionData, KeyAuth, static_cast<int>(popAuthLogin));
    SslTypeComboBox->ItemIndex = ini->ReadInteger(SectionSsl, KeySslType, static_cast<int>(pop3TlsImplicit));
    OAuth2UserAuth->Text = ini->ReadString(SectionData, KeyOAuth2UserAuth, "");
    OAuth2ExtBrow->Checked = ini->ReadBool(SectionData, KeyOAuth2ExtBrow, false);
    VerifyCheckBox->Checked = ini->ReadBool(SectionSsl, KeyVerify, false);
    CAFileEdit->Text = ini->ReadString(SectionSsl, KeyCaFile, "TrustedCABundle.pem");
    CAPathEdit->Text = ini->ReadString(SectionSsl, KeyCaPath, "TrustedCaStore");
    if (OAuth2UserAuth->Text == "")
        OAuth2UserAuth->Text = OAuthMsUserAuthDef;

    InfoLabel->Caption = "";
    SubjectEdit->Text = "";
    FromEdit->Text = "";
    ToEdit->Text = "";
    DisplayMemo->Clear();
}

void __fastcall TPOP3ExcercizerForm::FormClose(TObject *Sender, TCloseAction &Action)
{
    std::unique_ptr<TIcsIniFile> ini(new TIcsIniFile(FIniFileName, true));
    ini->WriteInteger(SectionWindow, KeyTop, Top);
    ini->WriteInteger(SectionWindow, KeyLeft, Left);
    ini->WriteInteger(SectionWindow, KeyWidth, Width);
    ini->WriteInteger(SectionWindow, KeyHeight, Height);
    ini->WriteString(SectionData, KeyHost, HostEdit->Text);
    ini->WriteString(SectionData, KeyPort, PortEdit->Text);
    ini->WriteString(SectionData, KeyUserName, UserNameEdit->Text);
    ini->WriteString(SectionData, KeyPassword, PassWordEdit->Text);
    ini->WriteInteger(SectionData, KeyAuth, AuthComboBox->ItemIndex);
    ini->WriteInteger(SectionSsl, KeySslType, SslTypeComboBox->ItemIndex);
    ini->WriteBool(SectionSsl, KeyVerify, VerifyCheckBox->Checked);
    ini->WriteString(SectionSsl, KeyCaFile, CAFileEdit->Text);
    ini->WriteString(SectionSsl, KeyCaPath, CAPathEdit->Text);
    ini->WriteString(SectionData, KeyOAuth2UserAuth, OAuth2UserAuth->Text);
    ini->WriteBool(SectionData, KeyOAuth2ExtBrow, OAuth2ExtBrow->Checked);
    ini->UpdateFile();
}

// Connection progress and errors reported by the POP3 component.
void __fastcall TPOP3ExcercizerForm::SslPop3ClientDisplay(TObject *Sender, const String Msg)
{
    DisplayMemo->Lines->Add(Msg);
}

void __fastcall TPOP3ExcercizerForm::SetSslVerifyProps()
{
    SslContext1->SslVerifyPeer = VerifyCheckBox->Checked;
    if (SslContext1->SslVerifyPeer) {
        SslContext1->SslCAFile = CAFileEdit->Text;   // no longer needed since V9.6 (shared CA store)
        SslContext1->SslCAPath = CAPathEdit->Text;
        SslPop3Client->SslCertVerMethod = CertVerBundle;
    }
    else {
        SslContext1->SslCAFile = "";
        SslContext1->SslCAPath = "";
        SslPop3Client->SslCertVerMethod = CertVerNone;
    }
}

void __fastcall TPOP3ExcercizerForm::SetupOAuth2()
{
    // Hardcode your Google or Microsoft client application account details here.
    IcsRestEmail1->RestEmailType = RestEmailMSSmtp;
    IcsRestEmail1->ClientId = "";
    IcsRestEmail1->ClientSecret = "";

    if (IcsRestEmail1->ClientId == "") {
        DisplayMemo->Lines->Add("OAuth2 authentication requires an client application account");
        return;
    }
    IcsRestEmail1->Clear();
    if (PassWordEdit->Text.Length() > 32)
        IcsRestEmail1->RefrToken = PassWordEdit->Text;   // ideally the refresh token is saved separately

    IcsRestEmail1->AccountHint = UserNameEdit->Text;
    IcsRestEmail1->MsUserAuth = OAuth2UserAuth->Text;
    IcsRestEmail1->OAAuthType = OAuth2ExtBrow->Checked ? OAuthTypeWeb : OAuthTypeEmbed;

    const String host = SslPop3Client->Host;
    if (host.Pos("gmail") > 0)
        IcsRestEmail1->RestEmailType = RestEmailGoogle;
    else if (host.Pos("office365") > 0 || host.Pos("outlook") > 0)
        IcsRestEmail1->RestEmailType = RestEmailMSSmtp;
    else
        DisplayMemo->Lines->Add("Can not use OAuth2 Authentication with this POP3 Server");
}

// Every POP3 command has the same shape: copy the edit boxes into the component, start the
// command (asynchronous, the result arrives in OnRequestDone) and show the outcome in InfoLabel.
void __fastcall TPOP3ExcercizerForm::Exec(const std::function<void()> &Method, const String &MethodName)
{
    SubjectEdit->Text = "";
    FromEdit->Text = "";
    ToEdit->Text = "";
    SslPop3Client->Host = HostEdit->Text;
    SslPop3Client->Port = PortEdit->Text;
    SslPop3Client->WSDebugOptions = DefWSDebugClient;   // what TWSocket logs through OnDisplay
    SslPop3Client->SslType = static_cast<TPop3SslType>(SslTypeComboBox->ItemIndex);

    const bool opening = MethodName == "Open" || MethodName == "Connect";
    if ((SslPop3Client->SslType == pop3TlsImplicit && opening) ||
        (SslPop3Client->SslType == pop3TlsExplicit && (MethodName == "STLS" || MethodName == "Open"))) {
        // The context properties are applied when the context is initialised.
        SetSslVerifyProps();
        SslContext1->UseSharedCAStore = true;
    }
    SslPop3Client->AuthType = static_cast<TPop3AuthType>(AuthComboBox->ItemIndex);
    SslPop3Client->UserName = UserNameEdit->Text;
    SslPop3Client->PassWord = PassWordEdit->Text;
    if (opening && (SslPop3Client->AuthType == popAuthXOAuth2 || SslPop3Client->AuthType == popAuthOAuthBearer))
        SetupOAuth2();
    SslPop3Client->MsgNum = StrToInt(MsgNumEdit->Text);
    SslPop3Client->MsgLines = StrToInt(MsgLinesEdit->Text);

    // Reassign the handlers: Get All and Next replace them.
    SslPop3Client->OnRequestDone = SslPop3ClientRequestDone;
    SslPop3Client->OnMessageBegin = SslPop3ClientMessageBegin;
    SslPop3Client->OnMessageEnd = SslPop3ClientMessageEnd;
    SslPop3Client->OnMessageLine = SslPop3ClientMessageLine;
    InfoLabel->Caption = MethodName + " starting";
    try {
        Method();
        InfoLabel->Caption = MethodName + " started async ok";
    }
    catch (Exception &E) {
        MessageBeep(MB_OK);
        InfoLabel->Caption = MethodName + " failed (" + E.Message + ")";
    }
}

void __fastcall TPOP3ExcercizerForm::ConnectButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Connect(); }, "Connect");
}

void __fastcall TPOP3ExcercizerForm::STlsButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Stls(); }, "STLS");
}

void __fastcall TPOP3ExcercizerForm::OpenButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Open(); }, "Open");
}

void __fastcall TPOP3ExcercizerForm::UserButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->User(); }, "User");
}

void __fastcall TPOP3ExcercizerForm::PassButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Pass(); }, "Pass");
}

void __fastcall TPOP3ExcercizerForm::QuittButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Quit(); }, "Quit");
}

void __fastcall TPOP3ExcercizerForm::AbortButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Abort(); }, "Abort");
}

void __fastcall TPOP3ExcercizerForm::RetrButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Retr(); }, "Retr");
}

void __fastcall TPOP3ExcercizerForm::StatButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Stat(); }, "Stat");
}

void __fastcall TPOP3ExcercizerForm::ListAllButtonClick(TObject *Sender)
{
    MsgNumEdit->Text = "0";
    Exec([this] { SslPop3Client->List(); }, "List All");
}

void __fastcall TPOP3ExcercizerForm::ListButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->List(); }, "List");
}

void __fastcall TPOP3ExcercizerForm::DeleteButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Dele(); }, "Delete");
}

void __fastcall TPOP3ExcercizerForm::NoopButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Noop(); }, "Noop");
}

void __fastcall TPOP3ExcercizerForm::LastButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Last(); }, "Last");
}

void __fastcall TPOP3ExcercizerForm::ResetButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->RSet(); }, "Rset");
}

void __fastcall TPOP3ExcercizerForm::TopButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Top(); }, "Top");
}

void __fastcall TPOP3ExcercizerForm::RpopButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->RPop(); }, "Rpop");
}

void __fastcall TPOP3ExcercizerForm::UidlButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Uidl(); }, "Uidl");
}

void __fastcall TPOP3ExcercizerForm::ApopButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->APop(); }, "Apop");
}

void __fastcall TPOP3ExcercizerForm::AuthButtonClick(TObject *Sender)
{
    Exec([this] { SslPop3Client->Auth(); }, "Auth");
}

// A message is about to arrive (MsgNum gives its number); a real application would open its file here.
void __fastcall TPOP3ExcercizerForm::SslPop3ClientMessageBegin(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** Message " + IntToStr(static_cast<TPop3Cli*>(Sender)->MsgNum) + " begin ***");
}

// Called at the end of a message, even after an error or exception.
void __fastcall TPOP3ExcercizerForm::SslPop3ClientMessageEnd(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** Message " + IntToStr(static_cast<TPop3Cli*>(Sender)->MsgNum) + " end ***");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientMessageLine(TObject *Sender)
{
    DisplayMemo->Lines->Add(String(static_cast<TPop3Cli*>(Sender)->LastResponse));
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientListBegin(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** List begin ***");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientListEnd(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** List End ***");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientListLine(TObject *Sender)
{
    TPop3Cli *cli = static_cast<TPop3Cli*>(Sender);
    DisplayMemo->Lines->Add("MsgNum = " + IntToStr(cli->MsgNum) + " MsgSize = " + IntToStr(cli->MsgSize) +
        " Line = '" + String(cli->LastResponse) + "'");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientUidlBegin(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** Uidl begin ***");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientUidlEnd(TObject *Sender)
{
    DisplayMemo->Lines->Add("*** Uidl end ***");
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientUidlLine(TObject *Sender)
{
    TPop3Cli *cli = static_cast<TPop3Cli*>(Sender);
    // Delphi writes only the closing quote around the UIDL.
    DisplayMemo->Lines->Add("MsgNum = " + IntToStr(cli->MsgNum) + " MsgUidl = '" + String(cli->MsgUidl) + "'");
}

void __fastcall TPOP3ExcercizerForm::MessageBegin(TObject *Sender)
{
    MessageForm->Caption = "Message " + IntToStr(static_cast<TPop3Cli*>(Sender)->MsgNum);
    MessageForm->Show();
}

void __fastcall TPOP3ExcercizerForm::MessageLine(TObject *Sender)
{
    MessageForm->DisplayMemo->Lines->Add(String(static_cast<TPop3Cli*>(Sender)->LastResponse));
}

// Retrieves message MsgNum into the message window and, if that worked, moves MsgNum to the next one.
void __fastcall TPOP3ExcercizerForm::NextButtonClick(TObject *Sender)
{
    MessageForm->DisplayMemo->Clear();
    MessageForm->Caption = "Message";
    SslPop3Client->OnMessageBegin = MessageBegin;
    SslPop3Client->OnMessageEnd = nullptr;
    SslPop3Client->OnMessageLine = MessageLine;
    SslPop3Client->OnRequestDone = NextMessageRequestDone;
    SslPop3Client->MsgNum = StrToInt(MsgNumEdit->Text);
    SslPop3Client->Retr();
}

void __fastcall TPOP3ExcercizerForm::NextMessageRequestDone(TObject *Sender, TPop3Request RqType, System::Word ErrCode)
{
    if (ErrCode != 0)
        return;
    MsgNumEdit->Text = IntToStr(StrToInt(MsgNumEdit->Text) + 1);
}

void __fastcall TPOP3ExcercizerForm::GetAllMessageLine(TObject *Sender)
{
    // The raw bytes of the line, as Delphi's Writeln of an AnsiString.
    if (!FFile)
        return;
    const AnsiString line = static_cast<TPop3Cli*>(Sender)->LastResponse;
    if (!line.IsEmpty())
        FFile->Write(line.c_str(), line.Length());
    FFile->Write("\r\n", 2);
}

// Closes the Get All message file; DeletePartial removes a message whose Retr did not complete.
void __fastcall TPOP3ExcercizerForm::CloseGetAllFile(bool DeletePartial)
{
    if (!FFile)
        return;
    FFile.reset();
    // Delphi keeps the partial file, and the next Get All then reports that message as "already here".
    if (DeletePartial)
        DeleteFile(FFileName);
}

// Get All: the POP3 component is asynchronous, so the commands are chained through OnRequestDone,
// with FGetAllState saying which one finished. Stat gives the message count; then for each message
// Uidl gives a unique id that names the file (an existing file is skipped) and Retr fetches it.
// A real application would also run a timer to handle a timeout.
void __fastcall TPOP3ExcercizerForm::GetAllButtonClick(TObject *Sender)
{
    // Delphi resets its state and calls Stat even while a request runs, which corrupts the running chain.
    if (SslPop3Client->State != pop3Ready && SslPop3Client->State != pop3InternalReady) {
        DisplayMemo->Lines->Add("Get All: the POP3 component is busy, wait for the current request to finish.");
        return;
    }

    {
        std::unique_ptr<TIcsIniFile> ini(new TIcsIniFile(FIniFileName, true));
        FMsgPath = ini->ReadString("Data", "MsgPath", ExtractFilePath(Application->ExeName));
    }
    if (!FMsgPath.IsEmpty() && FMsgPath[FMsgPath.Length()] != L'\\')
        FMsgPath = FMsgPath + "\\";

    FGetAllState = 0;
    FFile.reset();
    SslPop3Client->OnRequestDone = GetAllRequestDone;
    SslPop3Client->OnMessageBegin = nullptr;
    SslPop3Client->OnMessageEnd = nullptr;
    SslPop3Client->OnMessageLine = GetAllMessageLine;
    SslPop3Client->Stat();
}

void __fastcall TPOP3ExcercizerForm::GetAllRequestDone(TObject *Sender, TPop3Request RqType, System::Word ErrCode)
{
    if (ErrCode != 0) {
        CloseGetAllFile(true);
        DisplayMemo->Lines->Add("Error " + SslPop3Client->ErrorMessage);
        return;
    }

    try {
        switch (FGetAllState) {
        case 0:   // Stat done
            if (SslPop3Client->MsgCount < 1) {
                DisplayMemo->Lines->Add("No message to download.");
                return;
            }
            SslPop3Client->MsgNum = 1;
            FGetAllState = 1;
            SslPop3Client->Uidl();
            break;

        case 1:   // Uidl done
            // Delphi uses the UIDL unchanged; characters a file name cannot hold are replaced with '_'.
            FFileName = FMsgPath + "Msg " + SafeFileName(String(SslPop3Client->MsgUidl)) + ".txt";
            if (FileExists(FFileName)) {
                DisplayMemo->Lines->Add("Message " + IntToStr(SslPop3Client->MsgNum) + " already here");
                if (SslPop3Client->MsgNum >= SslPop3Client->MsgCount) {
                    DisplayMemo->Lines->Add("Finished");
                    return;
                }
                SslPop3Client->MsgNum = SslPop3Client->MsgNum + 1;
                FGetAllState = 1;
                SslPop3Client->Uidl();
            }
            else {
                DisplayMemo->Lines->Add("Message " + IntToStr(SslPop3Client->MsgNum));
                FFile.reset(new TFileStream(FFileName, fmCreate));
                FGetAllState = 2;
                SslPop3Client->Retr();
            }
            break;

        case 2:   // Retr done
            CloseGetAllFile(false);
            if (SslPop3Client->MsgNum >= SslPop3Client->MsgCount) {
                DisplayMemo->Lines->Add("Finished");
                return;
            }
            SslPop3Client->MsgNum = SslPop3Client->MsgNum + 1;
            FGetAllState = 1;
            SslPop3Client->Uidl();
            break;

        default:
            DisplayMemo->Lines->Add("Invalid state");
            break;
        }
    }
    catch (Exception &E) {
        CloseGetAllFile(true);
        DisplayMemo->Lines->Add("Error: " + E.Message);
    }
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientRequestDone(TObject *Sender, TPop3Request RqType, System::Word ErrCode)
{
    DisplayMemo->Lines->Add("Request Done Rq=" + IntToStr(static_cast<int>(RqType)) +
        " Error=" + IntToStr(static_cast<int>(ErrCode)) +
        " LastResponse=\"" + String(SslPop3Client->LastResponse) +
        "\" ErrorMessage=\"" + SslPop3Client->ErrorMessage +
        "\" Connected=" + BoolToStr(SslPop3Client->Connected, true));

    if (RqType == pop3Stat)
        InfoLabel->Caption = "Stat ok, " + IntToStr(SslPop3Client->MsgCount) + " messages " +
            IntToStr(SslPop3Client->MsgSize) + " bytes";
    else if (RqType == pop3List)
        InfoLabel->Caption = "List ok, " + IntToStr(SslPop3Client->MsgNum) + " message " +
            IntToStr(SslPop3Client->MsgSize) + " bytes";
    else if (RqType == pop3Last)
        InfoLabel->Caption = "Last = " + IntToStr(SslPop3Client->MsgNum);
}

void __fastcall TPOP3ExcercizerForm::SslPop3ClientHeaderEnd(TObject *Sender)
{
    SubjectEdit->Text = String(SslPop3Client->HeaderSubject);
    FromEdit->Text = String(SslPop3Client->HeaderFrom);
    ToEdit->Text = String(SslPop3Client->HeaderTo);
}

// Called by the POP3 component when it needs an OAuth2 token.
void __fastcall TPOP3ExcercizerForm::SslPop3ClientGetNewToken(TObject *Sender)
{
    // Interactive: waits for the browser window to complete.
    if (!IcsRestEmail1->GetNewToken(true)) {
        DisplayMemo->Lines->Add("Failed to get OAuth2 Bearer Token");
        return;
    }
    const String account = IcsRestEmail1->NewAccEmail;
    if (SslPop3Client->UserName.Pos(account) == 0 && account != "")
        DisplayMemo->Lines->Add("OAuth2 Token for Wrong Account, Expected: " + SslPop3Client->UserName +
            ", Got: " + account);
    else {
        SslPop3Client->OAuthToken = IcsRestEmail1->AccToken;
        SslPop3Client->TokenExpireDT = IcsRestEmail1->AccExpireDT;
        DisplayMemo->Lines->Add("Got New OAuth2 Bearer Token OK");
    }
}

// Called by TIcsRestEmail when it has a new refresh token that should be saved.
void __fastcall TPOP3ExcercizerForm::IcsRestEmail1EmailNewToken(TObject *Sender)
{
    if (IcsRestEmail1->RefrToken != "") {
        PassWordEdit->Text = IcsRestEmail1->RefrToken;
        DisplayMemo->Lines->Add("Saved OAuth2 Refresh Token");
    }
}

void __fastcall TPOP3ExcercizerForm::IcsRestEmail1EmailProg(TObject *Sender, TLogOption LogOption, const String Msg)
{
    DisplayMemo->Lines->Add(Msg);
}

void __fastcall TPOP3ExcercizerForm::IcsRestEmail1OAEmbed(TObject *Sender, const String URL, bool &Success)
{
    Success = OAuthBrowser1->BrowserEmbedded(static_cast<TRestOAuth*>(Sender), this, URL);
}
