Jump to content

mvanrijnen

Members
  • Content Count

    487
  • Joined

  • Last visited

  • Days Won

    1

mvanrijnen last won the day on October 26 2023

mvanrijnen had the most liked content!

Community Reputation

128 Excellent

1 Follower

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. mvanrijnen

    A smart case statement in Delphi?

    there's also the old: IndexText or IndexStr method System.StrUtils.IndexText - RAD Studio API Documentation
  2. Anoyone an idea how to get this done? If i have a record/class as a return type for q request, i sometimes want to hide certain properties for the (de)serialization process. can not find what to use with the MARS framework for this?
  3. mvanrijnen

    Define conditional symbol in .dpr

    hm, does the ramdisk makes much difference with building?
  4. @Marco Cantu I'm glad to say that we did fix the problem ...
  5. mvanrijnen

    Connection Pooling

    If you create the datamodule per request, why not set the connection in the datamodule as a property (set it from within the request). I do that in some projects. (needs some work maybe on the setter of connection property in the datamodule) So you would get something like: function TMyResource.GetInfo(const APar1: string; const APar2: integer): TMyInfo; var ldm : TMyDataModule; begin ldm := TMyDataModule.Create(); try ldm.MyConnection := FD.Connection; ldm.DoMyMethod(APar1, APar2); finally ldm.Free; end; end; Maybe you have a (simple) example of your code?
  6. ??? The summit is held in Purmerend (a place near Amsterdam), but it's called Delphi Summit Amsterdam, don't know where you were thinking of, but if it was ment as a joke, it's not a funny joke?
  7. Most funny thing is that nobody can confirm this is fixed. Kind of confirmation of what a laugh the Delphi IDE is become .......................... Time to make a list of critical question for the next Summit in Purmerend (Amsterdam for the commercial guys&girls).
  8. Does someone ( @Marco Cantu) knows if this is solved in 12.3.x? We are sure gonna leave the whole RadServer concept because of the lack of support/maintenance. (probably going the MARS way) Who releases a software development product which can debug? (curious the way this went to production/release, Boss! We can not debug the radserver modules, oh, "nobody cares, just ship it,")
  9. mvanrijnen

    Connection Pooling

    You (as far as i know), need always to create (request for) a new FDConnection with each request, each request runs as it's own thread. At what "ServerConnectionPool data module" you are referring to ? (can not see somehting like this in the template folder? I have examples of how to use the FDConnection in a normal request/resource if you need that. uses MARS.Core.RequestAndResponse.Interfaces, MARS.Data.FireDAC, ..... TMyResource = class strict private protected // connection can be left away, when referring to MAIN_DB in the .ini [Context, Connection('MyDB', False)] FD: TMARSFireDAC; [Context] FRequest : IMARSRequest; public [Produces(TMediaType.APPLICATION_JSON)] function GetInfo([QueryParam('par1')] const APar1: string; const [QueryParam('par2')] APar2 : integer) : TMyInfo; end; function TMyResource.GetInfo(const APar1: string; const APar2: integer): TMyInfo; var fqry : TFDQuery; begin if not FD.Connection.NewQuery(fqry) then raise Exception.Create('Error bij aanmaken van query'); try fqry.sql.text := 'select * from ...........'; fqry.Open(); while not fqry.Eof do begin fqry.Next; ..... end; finally fqry.Free; end; end;
  10. So, here we are more than a year later, any news on this issue?
  11. Also the method of inline sending the attachments is limited to a size ( i believe 3MB), my code (i'm in a hurry, so just a dump), you can get the idea how to from this. const CNST_RESOURCE_CREATEUPLOADSESSION = 'users/{sendasemailaddress}/messages/{messageid}/attachments/createUploadSession'; CNST_RESOURCE_CREATEDRAFTMESSAGE = 'users/{sendasemailaddress}/mailFolders/drafts/messages'; CNST_RESOURCE_SENDCREATEDRAFT = 'users/{sendasemailaddress}/messages/{messageid}/send'; function THSMSGraphAPI.FetchUploadURL(const AUploadSize: integer; const AFileName, AMessageID, AContentID, AContentType : string; const AIsInline : Boolean): string; var fuploadRequest : TRESTRequest; fuploadResponse : TMSGraphUploadSessionResponse; attreq : TMSGraphUploadSessionRequest; begin Result := ''; fuploadRequest := TRESTRequest.Create(nil); try fuploadRequest.Client := FRestClient; fuploadRequest.Method := TRESTRequestMethod.rmPOST; fuploadRequest.Resource := CNST_RESOURCE_CREATEUPLOADSESSION.Replace('{sendasemailaddress}', AccountEmailAddress, [rfReplaceAll, rfIgnoreCase]).Replace('{messageid}', AMessageID, [rfReplaceAll, rfIgnoreCase]); attreq.AttachmentItem.attachmentType := 'file'; attreq.AttachmentItem.name := ExtractFileName(AFileName); attreq.AttachmentItem.size := AUploadSize; attreq.AttachmentItem.isInline := (AIsInline) or (not AContentID.IsEmpty); attreq.AttachmentItem.contentID := AContentID; attreq.AttachmentItem.contentType := AContentType; fuploadRequest.AddBody(attreq.AsJSON, TRESTContentType.ctAPPLICATION_JSON); fuploadRequest.Execute(); if not LogInvalidResponse(fuploadRequest.Response, True, 'THSMSGraphAPI.FetchUploadURL') then begin fuploadResponse := TMSGraphUploadSessionResponse.FromJSON(fuploadRequest.Response.Content); Result := fuploadResponse.uploadUrl; end; finally fuploadRequest.Free; end; end; procedure THSMSGraphAPI.AddLargeAttachments(const AEmailMessageAttachments : TMvREMailAttachments; const AMessageID : string); function CreateSourceStream(const AAttachment : TMvREMailAttachment) : TStream; begin Result := nil; if AAttachment.IsFile then Result := TFileStream.Create(AAttachment.FileName, fmOpenRead or fmShareDenyWrite) else Result := TStringStream.Create(AAttachment.PayLoad); end; procedure UploadParts(const AUploadUrl : string; const ASourceStream : TStream; const AContentType : string); var memStream : TMemoryStream; fuploadPartRequest : TRESTRequest; hdr : string; size, done, todo : integer; begin fuploadPartRequest := TRESTRequest.Create(nil); memStream := TMemoryStream.Create; try fuploadPartRequest.URLAlreadyEncoded := True; fuploadPartRequest.Client := FUplClient; fuploadPartRequest.Method := TRESTRequestMethod.rmPUT; FUplClient.BaseURL := AUploadUrl; size := ASourceStream.Size; done := 0; todo := 0; ASourceStream.Position := 0; while (done<size) do begin todo := Min(CNST_MAXATTSIZE, size-done); memStream.Clear; ASourceStream.Position := done; memStream.CopyFrom(ASourceStream, todo); memStream.Position := 0; hdr := 'bytes ' + (done).ToString + '-' + (done+todo-1).ToString + '/' + size.ToString; fuploadPartRequest.ClearBody; fuploadPartRequest.Params.Clear; fuploadPartRequest.AddParameter('Content-Length', todo.ToString, TRESTRequestParameterKind.pkHTTPHEADER); fuploadPartRequest.AddParameter('Content-Range', hdr, TRESTRequestParameterKind.pkHTTPHEADER, [TRESTRequestParameterOption.poDoNotEncode]); if not AContentType.IsEmpty then fuploadPartRequest.AddParameter('Content-Type', AContentType, TRESTRequestParameterKind.pkHTTPHEADER, [TRESTRequestParameterOption.poDoNotEncode]); fuploadPartRequest.AddBody(memStream, TRESTContentType.ctAPPLICATION_OCTET_STREAM); ExecuteRequest(fuploadPartRequest, 'THSMSGraphAPI.AddLargeAttachments.UploadParts', True); LogInvalidResponse(fuploadPartRequest.Response, True, 'UploadParts'); done := done + todo; end; finally memStream.Free; fuploadPartRequest.Free; end; end; var att : TMvREMailAttachment; url : string; stream : TStream; begin for att in AEmailMessageAttachments do //if att.IsLargeAttachment then begin stream := CreateSourceStream(att); try // url := FetchUploadURL(stream.Size, att.FileName, AMessageID); url := FetchUploadURL(stream.Size, att.FileName, AMessageID, att.ContentID, att.ContentType, att.IsInline); UploadParts(url, stream, att.ContentType); finally stream.Free; end; end; end; function THSMSGraphAPI.SendEmailWithLargeAttachments(const AEmailMessage: TMvREMailMessage; AAPIMessage: TMSGraphSendEmailMessageBody): Boolean; function FetchImmutableID(const AID : string) : string; var req : TRESTRequest; request : TMSGraphTranslateExchangeIdsRequest; responseJSON, requestJSON : string; response : TMSGraphTranslateExchangeIdsResponse; begin Result := ''; req := TRESTRequest.Create(nil); try try req.Client := FRestClient; req.Method := TRESTRequestMethod.rmPOST; req.Resource := 'users/{sendasemailaddress}/translateExchangeIds'.Replace('{sendasemailaddress}', AccountEmailAddress, [rfReplaceAll, rfIgnoreCase]); SetLength(request.inputIds, 1); request.inputIds[0] := AID; request.targetIdType := 'restImmutableEntryId'; request.sourceIdType := 'restId'; TgoBsonSerializer.Serialize( request, requestJSON); req.AddBody(requestJSON, TRESTContentType.ctAPPLICATION_JSON); req.Execute(); responseJSON := req.Response.Content; TgoBsonSerializer.Deserialize(responseJSON, response); if length(response.value)>0 then Result := response.value[0].targetId; except on e: exception do begin Result := ''; raise Exception.CreateFmt('[THSMSGraphAPI.SendEmailWithLargeAttachments.FetchImmutableId]: %s\n%s', [e.ClassName, e.Message]); end; end; finally req.Free; end; end; function FetchMessagesForInternetMessageID(const AInternetMessageID : string) : TArray<string>; var req : TRESTRequest; request : TMSGraphTranslateExchangeIdsRequest; responseJSON, requestJSON : string; response : TMSGraphTranslateExchangeIdsResponse; begin SetLength(Result, 0); req := TRESTRequest.Create(nil); try try req.Client := FRestClient; req.Method := TRESTRequestMethod.rmGET; req.Resource := 'users/{sendasemailaddress}/messages?$filter=internetMessageId eq ''{internetmessageid}''' .Replace('{sendasemailaddress}', AccountEmailAddress, [rfReplaceAll, rfIgnoreCase]) .Replace('{internetmessageid}', TidUri.ParamsEncode(AInternetMessageID), [rfReplaceAll, rfIgnoreCase]); req.Execute(); except on e: exception do begin raise Exception.CreateFmt('[THSMSGraphAPI.SendEmailWithLargeAttachments.FetchMessagesForInternetMessageID]: %s\n%s', [e.ClassName, e.Message]); end; end; finally req.Free; end; end; var req1, req2 : TRESTRequest; draft : TMSGraphDraftResponse; draftremoved, step1done : boolean; removemsgid, immid : string; begin Result := False; immid := ''; removemsgid := ''; step1done := False; draftremoved := False; req1 := TRESTRequest.Create(nil); req2 := TRESTRequest.Create(nil); try try req1.Client := FRestClient; req1.Method := TRESTRequestMethod.rmPOST; req2.Client := FRestClient; req2.Method := TRESTRequestMethod.rmPOST; req1.Resource := CNST_RESOURCE_CREATEDRAFTMESSAGE.Replace('{sendasemailaddress}', AccountEmailAddress, [rfReplaceAll, rfIgnoreCase]); req1.AddBody(AAPIMessage.message.AsJson(), TRESTContentType.ctAPPLICATION_JSON); try req1.Execute(); except on e: exception do begin raise Exception.CreateFmt('[THSMSGraphAPI.SendEmailWithLargeAttachments.Req1]: %s\n%s', [e.ClassName, e.Message]); end; end; if not LogInvalidResponse(req1.Response, True, 'THSMSGraphAPI.SendEmailWithLargeAttachments.1') then begin draft := TMSGraphDraftResponse.FromJSON(req1.Response.Content); removemsgid := draft.id; step1done := IsValidResponse(req1.Response); if not (AEmailMessage.SaveOnSend) then begin immid := FetchImmutableID(draft.id); removemsgid := immid; end; {$ifdef debug} if not immid.IsEmpty then LogExInfo('ImmutableID: %s', [immid], 'THSMSGraphAPI.SendEmailWithLargeAttachments'); {$endif} //raise Exception.Create('TEST Error Message'); try AddLargeAttachments(AEmailMessage.Attachments, draft.id); except on e: exception do begin raise Exception.CreateFmt('[THSMSGraphAPI.SendEmailWithLargeAttachments.AddLargeAttachments]: %s\n%s', [e.ClassName, e.Message]); end; end; end; req2.Resource := CNST_RESOURCE_SENDCREATEDRAFT.Replace('{sendasemailaddress}', AccountEmailAddress, [rfReplaceAll, rfIgnoreCase]).Replace('{messageid}', draft.id, [rfReplaceAll, rfIgnoreCase]); try req2.Execute(); except on e: exception do begin raise Exception.CreateFmt('[THSMSGraphAPI.SendEmailWithLargeAttachments.Req2]: %s\n%s', [e.ClassName, e.Message]); end; end; if not LogInvalidResponse(req2.Response, True, 'SendWithLargeAttachments.2') then begin Result := True; if not (AEmailMessage.SaveOnSend) then begin if not immid.IsEmpty then draftremoved := TryRemoveEmailMessage(immid) else LogExWarn('Could not remove draft sendmessage because empty immutableid', 'THSMSGraphAPI.SendEmailWithLargeAttachments'); end; end; except on e: exception do begin Result := False; if (not draftremoved) and (step1done) and (not removemsgid.IsEmpty) then begin Sleep(1000); draftremoved := TryRemoveEmailMessage(removemsgid); if draftremoved then LogExWarn('Draft message with id: %s removed.', [removemsgid], 'THSMSGraphAPI.SendEmailWithLargeAttachments') else LogExError('Draft message with id: %s was not removed!', [removemsgid], 'THSMSGraphAPI.SendEmailWithLargeAttachments') end; raise; end; end; finally req2.Free; req1.Free; end; end;
  12. mvanrijnen

    Help with Interbase

    strange way of looking to solve a problem, if you don't bother, than do no ask....
  13. mvanrijnen

    Help with Interbase

    From Delphi to Interbase, over localnetwork/internet ? Which database component set your are using (e.g. FireDac) ?
  14. mvanrijnen

    SMTP Server -> Client

    i've build a service (called ProtoBridge, not public available), which does just this. But more 😉 It can act as a simple bridge between older machines/services to forward emails to o365/gmail (oauth2) etc etc. It can also serve as a ftp server, and you can configure different virtual ftp folders which direct the incoming file(s) to a specific email adress so you can "bridge" protocols it can act as server for: * simple smtp * ftp * local folders * smb folders and forward to: * simple smtp * smtp (oauth2 etc) * O365 (MS Graph API) * Exchange EWS * ftp * local folder * smb folder It's using INDY for all the protocols (except MS Graph API & EWS), off course is this a service which is not intended to use on a public server. (there is a white & blacklist on IP numbers available)
  15. mvanrijnen

    My app dies in Server 2019

    A specific version?
×