FastReport_2022_VCL/LibD28x64/frxIOTransportGMailBase.pas
2024-01-01 16:13:08 +01:00

413 lines
11 KiB
ObjectPascal

{******************************************}
{ }
{ FastReport v6.0 }
{ GMail base Filter }
{ }
{ Copyright (c) 1998-2021 }
{ by Fast Reports Inc. }
{ }
{******************************************}
unit frxIOTransportGMailBase;
interface
{$I frx.inc}
uses
Classes, Forms, Controls, StdCtrls, ComCtrls,
frxIOTransportHelpers, frxBaseTransportConnection, frxIOTransportOAuthDialog,
frxBaseMailApi;
const
frx_GMail_GetToken_URL = 'https://www.googleapis.com/oauth2/v4/token';
frx_GMail_ListLabels_URL = 'https://gmail.googleapis.com/gmail/v1/users/me/labels';
frx_GMail_ListMessagesBase_URL = 'https://gmail.googleapis.com/gmail/v1/users/me/messages';
frx_GMail_Upload_URL = 'https://gmail.googleapis.com/gmail/v1/users/me/messages/send';
frx_GMail_Test = 'https://gmail.googleapis.com/gmail/v1/users/me/profile';
type
TfrxGMailIOTransportForm = class(TfrxOAuthTransportDialog)
protected
function GetHelpLink: String; override;
public
procedure UpdateResouces; override;
end;
{$IFDEF DELPHI16}
[ComponentPlatformsAttribute(pidWin32 or pidWin64)]
{$ENDIF}
TfrxBaseGMailIOTransport = class(TfrxBaseMailIOTransport)
protected
function FilterSection: String; override;
function GetListLabels(aFilter: String = ''): String; virtual; abstract;
function GetListMessages(aFilter: String = ''): String; virtual; abstract;
function GetListMessagesContinue(NextPageToken: String; aFilter: String = ''): String; virtual; abstract;
function GetMessageInfo(id: String; aFilter: String = ''): String; virtual; abstract;
function GetListAttachments(aFilter: String = ''): String; virtual;
function GetListDownloads(frxMessageStack: TfrxMessageStack; Id: String; aFilter: String = ''): String; virtual; abstract;
function GetSomethingById(id: String): String;
function PrepareName(const Name: String): String;
function PrepareUploadStream(const Source: TStream; CT: AnsiString; DestFileName: String): AnsiString;
procedure Download(const SourceFileName: String; const Source: TStream); override;
public
class function TransportDialogClass: TfrxBaseTransportDialogClass; override;
class function GetDescription: String; override;
procedure GetDirItems(DirItems: TStrings; aFilter: String = ''); override;
function GetOAuthURI: String; override;
end;
function frx_GMail_ListMessages_URL(frxLabel: TfrxLabel; q: String = ''): String;
function frx_GMail_ListMessagesContinue_URL(frxLabel: TfrxLabel; q: String = ''; pt: String = ''): String;
function frx_GMail_ListAttachments_URL(id: String): String;
function frx_GMail_Download_URL(frxMessage: TfrxMessage; Id: String): String;
const
GMailBoundary = '560310243403';
implementation
uses
Windows, SysUtils, Graphics,
frxMapHelpers, frxRes, frxSaveFilterBrowser, frxUtils, frxNetUtils,
frxJSON;
{ TfrxBaseGMailIOTransport }
function TfrxBaseGMailIOTransport.FilterSection: String;
begin
Result := 'GMailFilter';
end;
class function TfrxBaseGMailIOTransport.GetDescription: String;
begin
Result := frxResources.Get('GMailIOTransport');
end;
procedure TfrxBaseGMailIOTransport.GetDirItems(DirItems: TStrings; aFilter: String);
var
HasMore: Boolean;
NextPageToken: String;
procedure AddRevert;
begin
AddToDirItems(DirItems, True, False, '..', '..');
end;
procedure GetJSONMessagesList(frxJSON: TfrxJSON);
procedure FillMessages(frxJSONArray: TfrxJSONArray);
var
i: Integer;
begin
for i := 0 to frxJSONArray.Count - 1 do
with frxJSONArray.Get(i) do
try
AddToDirItems(DirItems, True, False, GetSomethingById(ValueByName('id')), ValueByName('id'));
finally
Free;
end;
frxJSONArray.Free;
end;
begin
if not Assigned(frxJSON) then
raise Exception.Create('Non valid JSON data');
FillMessages(TfrxJSONArray.Create(frxJSON.ObjectByName('messages')));
HasMore := frxJSON.IsNameExists('nextPageToken');
if HasMore then
NextPageToken := frxJSON.ValueByName('nextPageToken');
frxJSON.Free;
end;
procedure GetJSONLabelsList(frxJSON: TfrxJSON);
procedure FillLabels(frxJSONArray: TfrxJSONArray);
var
i: Integer;
begin
for i := 0 to frxJSONArray.Count - 1 do
with frxJSONArray.Get(i) do
try
AddToDirItems(DirItems, True, False, ValueByName('name'), ValueByName('id'));
finally
Free;
end;
frxJSONArray.Free;
end;
begin
if not Assigned(frxJSON) then
raise Exception.Create('Non valid JSON data');
FillLabels(TfrxJSONArray.Create(frxJSON.ObjectByName('labels')));
frxJSON.Free;
end;
procedure GetJSONAttachmentsList(frxJSON: TfrxJSON);
var
PLD: TfrxJSON;
procedure FillAttachments(frxJSONArray: TfrxJSONArray);
var
i: Integer;
Body: TfrxJSON;
begin
for i := 0 to frxJSONArray.Count - 1 do
with frxJSONArray.Get(i) do
try
if (ValueByName('filename') <> '') then
begin
Body := TfrxJSON.CreateWeek(ObjectByName('body'));
try
AddToDirItems(DirItems, False, True, ValueByName('filename'), Body.ValueByName('attachmentId'));
finally
Body.Free;
end;
end;
finally
Free;
end;
frxJSONArray.Free;
end;
begin
if not Assigned(frxJSON) then
raise Exception.Create('Non valid JSON data');
try
PLD := TfrxJSON.CreateWeek(frxJSON.ObjectByName('payload'));
try
FillAttachments(TfrxJSONArray.Create(PLD.ObjectByName('parts')));
finally
PLD.Free;
end;
finally
frxJSON.Free;
end;
end;
begin
DirItems.BeginUpdate;
ClearWithObjects(DirItems);
aFilter := PrepareName(aFilter);
if (FfrxMessageStack.frxLabel.Id = '') then
begin
GetJSONLabelsList(TfrxJSON.Create(GetListLabels(aFilter)));
end
else
if (FfrxMessageStack.frxMessage.Id = '') then
begin
AddRevert;
GetJSONMessagesList(TfrxJSON.Create(GetListMessages(aFilter)));
while HasMore do
GetJSONMessagesList(TfrxJSON.Create(GetListMessagesContinue(NextPageToken, aFilter)));
end
else
begin
AddRevert;
GetJSONAttachmentsList(TfrxJSON.Create(GetListAttachments(aFilter)));
end;
DirItems.EndUpdate;
end;
function TfrxBaseGMailIOTransport.GetOAuthURI: String;
begin
Result := 'https://accounts.google.com/o/oauth2/v2/auth?' +
'client_id=' + ClientID + '&' +
'redirect_uri=' + GetRedirectURI + '&' +
'response_type=code&' +
'scope=https://mail.google.com';
end;
function TfrxBaseGMailIOTransport.GetListAttachments(aFilter: String = ''): String;
begin
Result := GetMessageInfo(FfrxMessageStack.frxMessage.Id, aFilter);
end;
function TfrxBaseGMailIOTransport.GetSomethingById(id: String): String;
var
Date: String;
Subject: String;
procedure FillMessageInfo(frxJSON: TfrxJSON);
var
PLD: TfrxJSON;
procedure FillInfo(frxJSONArray: TfrxJSONArray);
var
i: Integer;
begin
for i := 0 to frxJSONArray.Count - 1 do
with frxJSONArray.Get(i) do
try
if (ValueByName('name') = 'Date') then
Date := ValueByName('value')
else
if (ValueByName('name') = 'Subject') then
Subject := ValueByName('value');
finally
Free;
end;
frxJSONArray.Free;
end;
begin
if not Assigned(frxJSON) then
raise Exception.Create('Non valid JSON data');
try
PLD := TfrxJSON.CreateWeek(frxJSON.ObjectByName('payload'));
try
FillInfo(TfrxJSONArray.Create(PLD.ObjectByName('headers')));
finally
PLD.Free;
end;
finally
frxJSON.Free;
end;
end;
begin
FillMessageInfo(TfrxJSON.Create(GetMessageInfo(id)));
Result := FormatMailName(Subject, Date, id);
end;
function TfrxBaseGMailIOTransport.PrepareName(const Name: String): String;
begin
Result := StringReplace(Name, ' ', '+', [rfReplaceAll]);
end;
function TfrxBaseGMailIOTransport.PrepareUploadStream(const Source: TStream;
CT: AnsiString; DestFileName: String): AnsiString;
procedure Put(str: AnsiString);
begin
Result := Result + str;
end;
procedure PutLn(str: AnsiString = '');
begin
Put(str + #13#10);
end;
begin
Result := '';
PutLn('Content-Type: ' + CT);
PutLn('MIME-Version: 1.0');
//PutLn('From: John Doe <test@gmail.com>');
PutLn('To: ' + AnsiString(Address));
PutLn('Subject: =?utf-8?b?' + Base64Encode(UTF8Encode(Subject)) + '?=');
//PutLn('Date: Fri, 21 Nov 1997 09:55:06 -0600');
//PutLn('Message-ID: <1234@local.machine.example>');
PutLn('');
PutLn('--' + GMailBoundary);
PutLn('Content-Type: text/plain; charset="utf-8"');
PutLn('MIME-Version: 1.0');
PutLn('Content-Transfer-Encoding: 7bit');
PutLn('');
PutLn(AnsiString(MessageText.Text));
PutLn('--' + GMailBoundary);
PutLn('Content-Type: text/plain');//application/json
PutLn('MIME-Version: 1.0');
PutLn('Content-Disposition: attachment; filename="' + AnsiString(DestFileName) + '"');
PutLn('');
PutLn(AnsiString(LoadStringFromStream(Source)));
PutLn;
Put('--' + GMailBoundary + '--');
Result := Base64Encode(Result);
Result := '{"raw": "' + Result + '"}';
end;
procedure TfrxBaseGMailIOTransport.Download(const SourceFileName: String; const Source: TStream);
var
sList: TStringList;
sID: String;
Index: Integer;
procedure ParseRes(frxJSON: TfrxJSON);
var
buf: AnsiString;
begin
if not Assigned(frxJSON) then
raise Exception.Create('Non valid JSON data');
buf := Base64URLDecode(AnsiString(frxJSON.ValueByName('data')));
Source.Write(buf[1], Length(buf));
frxJSON.Free;
end;
begin
inherited;
sID := '';
SList := TStringList.Create;
GetDirItems(SList, SourceFileName);
Index := sList.IndexOf(SourceFileName);
if Index = -1 then Exit;
sID := TIdObject(sList.Objects[Index]).Id;
try
ParseRes(TfrxJSON.Create(GetListDownloads(FfrxMessageStack, sID)));
finally
ClearWithObjects(SList);
SList.Free;
end;
end;
class function TfrxBaseGMailIOTransport.TransportDialogClass: TfrxBaseTransportDialogClass;
begin
Result := TfrxGMailIOTransportForm;
end;
{ TfrxGMailIOTransportForm }
function TfrxGMailIOTransportForm.GetHelpLink: String;
begin
Result := 'https://console.cloud.google.com/apis/api/gmail.googleapis.com/credentials';
end;
procedure TfrxGMailIOTransportForm.UpdateResouces;
begin
Tag := 6522;
ClientIDLabel.Tag := 6511;
ClientSecLabel.Tag := 6512;
RemoteDirLabel.Visible := False;
RemoteDirComboBox.Visible := False;
inherited;
end;
{ support }
function frx_GMail_ListMessages_URL(frxLabel: TfrxLabel; q: String = ''): String;
begin
Result := frx_GMail_ListMessagesBase_URL + '?labelIds=' + frxLabel.Id + '&q=has:attachment';
if q <> '' then
Result := Result + ' ' + q;
end;
function frx_GMail_ListMessagesContinue_URL(frxLabel: TfrxLabel; q: String = ''; pt: String = ''): String;
begin
Result := frx_GMail_ListMessages_URL(frxLabel, q) + '&pageToken=' + pt;
end;
function frx_GMail_ListAttachments_URL(id: String): String;
begin
Result := frx_GMail_ListMessagesBase_URL + '/' + id;
end;
function frx_GMail_Download_URL(frxMessage: TfrxMessage; Id: String): String;
begin
Result := frx_GMail_ListAttachments_URL(frxMessage.Id) + '/attachments/' + Id;
end;
end.