Jump to content
mazluta

open mail online with office 365 graph api

Recommended Posts

Is there anyone that tried to open mail online with attachment?

 

1. get AccessToken from Graph API with clientID, ApplicationID +++ (that work)
2. upload file to onedrive. (that work)

3. get sharelink. (that work)

4. open /me/message  (that FAIL)

5. the subject will be empty, the body empty.

6. the user can add more files.

7. the user can add recipients, subject, body.....
8. click on send.

 

i have mange to get the AccessToken.

Upload the file to ondrive/temp folder

get the sharelink

but i can not draft the message.

 

CHATGPT - professional - did not help.

GIMINI - Advance - the same

 

MICROSOFT - like to make living harder

 

this is the log

============

CreateSharingLink - Response Status Code: 200
CreateSharingLink - Response Body: {"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.permission","id":"6977e500-5d45-47cc-82e8-d6ea3ceeef8d","roles":["read"],"shareId":"u!aHR0cHM6Ly9oYW5pYmFhbGNvaWwtbXkuc2hhcmVwb2ludC5jb20vOmI6L2cvcGVyc29uYWwvbWF6bHV0YV9oYW5pYmFhbF9jb19pbC9FVS1BSU1VOTU1UkJsX0RveDhrUlBUUUJGZDBXNmlOcVY3bEljQlVYcTMwME5R","hasPassword":false,"link":{"scope":"organization","type":"view","webUrl":"https://hanibaalcoil-my.sharepoint.com/:b:/g/personal/mazluta_hanibaal_co_il/EU-AIMU955RBl_Dox8kRPTQBFd0W6iNqV7lIcBUXq300NQ","preventsDownload":false}}
CreateSharingLink - HTTP Protocol version Version: 2
CreateSharingLink - Result.webUrl  = https://hanibaalcoil-my.sharepoint.com/:b:/g/personal/mazluta_hanibaal_co_il/EU-AIMU955RBl_Dox8kRPTQBFd0W6iNqV7lIcBUXq300NQ
CreateSharingLink - Result.shareId = u!aHR0cHM6Ly9oYW5pYmFhbGNvaWwtbXkuc2hhcmVwb2ludC5jb20vOmI6L2cvcGVyc29uYWwvbWF6bHV0YV9oYW5pYmFhbF9jb19pbC9FVS1BSU1VOTU1UkJsX0RveDhrUlBUUUJGZDBXNmlOcVY3bEljQlVYcTMwME5R
UploadAndOpenMailWithAttachment - Share URL created: https://hanibaalcoil-my.sharepoint.com/:b:/g/personal/mazluta_hanibaal_co_il/EU-AIMU955RBl_Dox8kRPTQBFd0W6iNqV7lIcBUXq300NQ
UploadAndOpenMailWithAttachment - Share ID: u!aHR0cHM6Ly9oYW5pYmFhbGNvaWwtbXkuc2hhcmVwb2ludC5jb20vOmI6L2cvcGVyc29uYWwvbWF6bHV0YV9oYW5pYmFhbF9jb19pbC9FVS1BSU1VOTU1UkJsX0RveDhrUlBUUUJGZDBXNmlOcVY3bEljQlVYcTMwME5R
UploadAndOpenMailWithAttachment - JSON Request: {  "subject": "Document from DMS",  "body": {    "contentType": "HTML",    "content": "Please review the attached file."  },  "attachments": [    {      "@odata.type": "#microsoft.graph.referenceAttachment",      "name": "GettingStarted.pdf",      "sourceUrl": "https://graph.microsoft.com/v1.0/shares/u!aHR0cHM6Ly9oYW5pYmFhbGNvaWwtbXkuc2hhcmVwb2ludC5jb20vOmI6L2cvcGVyc29uYWwvbWF6bHV0YV9oYW5pYmFhbF9jb19pbC9FVS1BSU1VOTU1UkJsX0RveDhrUlBUUUJGZDBXNmlOcVY3bEljQlVYcTMwME5R/root/content",      "isInline": false    }  ]}
UploadAndOpenMailWithAttachment - Create Draft Response Code: 400
UploadAndOpenMailWithAttachment - Create Draft Response Body: {"error":{"code":"UnableToDeserializePostBody","message":"were unable to deserialize "}}
UploadAndOpenMailWithAttachment - Error creating draft.
UploadAndOpenMailWithAttachment - Finished

 

 

the main procedure :

============

procedure TMainForm.UploadAndOpenMailWithAttachment(const LocalFilePath: string);
var
  HttpClient: THttpClient;
  OneDriveWebURL: string;
  AttachFileId: string;
  SharingLinkRec: TSharingLinkRec;
  DraftId: string;
  JSONRequestDraft: string;
  DraftResponse: IHTTPResponse;
  Headers: TNetHeaders;
  RequestContent: TStringStream;
begin
  AppLog.Lines.Add('');
  AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Starting');

  HttpClient := THttpClient.Create;
  try
    if UploadFileToOneDrive(LocalFilePath, OneDriveWebURL, AttachFileId) then
    begin
      AppLog.Lines.Add('UploadAndOpenMailWithAttachment - File uploaded to OneDrive');
      SharingLinkRec := CreateSharingLink(AttachFileId);
      if SharingLinkRec.Found then
      begin
        AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Share URL created: ' + SharingLinkRec.webUrl);
        AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Share ID: ' + SharingLinkRec.shareId);

        JSONRequestDraft :=
          '{' +
          '  "subject": "Document from DMS",' +
          '  "body": {' +
          '    "contentType": "HTML",' +
          '    "content": "Please review the attached file."' +
          '  },' +
          '  "attachments": [' +
          '    {' +
          '      "@odata.type": "#microsoft.graph.referenceAttachment",' +
          //'      "name": "' + JsonEscape(j_FileName(LocalFilePath)) + '",' +
          '      "name": "' + j_FileName(LocalFilePath) + '",' +
          '      "sourceUrl": "https://graph.microsoft.com/v1.0/shares/' + SharingLinkRec.shareId + '/root/content",' + // **Corrected sourceUrl**
          '      "isInline": false' +
          '    }' +
          '  ]' +
          '}';

        AppLog.Lines.Add('UploadAndOpenMailWithAttachment - JSON Request: ' + JSONRequestDraft);

        SetLength(Headers, 2);
        Headers[0].Name := 'Authorization';
        Headers[0].Value := 'Bearer ' + FAccessToken;
        Headers[1].Name := 'Content-Type';
        Headers[1].Value := 'application/json';

        RequestContent := TStringStream.Create(JSONRequestDraft, TEncoding.UTF8);
        try
          DraftResponse := HttpClient.Post('https://graph.microsoft.com/v1.0/me/messages', RequestContent, nil, Headers);

          AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Create Draft Response Code: ' + IntToStr(DraftResponse.StatusCode));
          AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Create Draft Response Body: ' + DraftResponse.ContentAsString);

          if (DraftResponse.StatusCode = 200) or (DraftResponse.StatusCode = 201) then
          begin
            // Extract the draft ID (you already have this function)
            DraftId := ExtractDraftIdFromResponse(DraftResponse.ContentAsString);
            AppLog.Lines.Add('UploadAndOpenMailWithAttachment - DraftId: ' + DraftId);

            // Open the draft in Outlook
            UniSession.AddJS(Format('window.open("https://outlook.office.com/mail/deeplink/compose?itemid=%s&exvsurl=1", "_blank");', [DraftId]));
          end
          else
          begin
            AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Error creating draft.');
          end;
        finally
          RequestContent.Free;
        end;
      end
      else
      begin
        AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Failed to create shareable link.');
      end;
    end
    else
    begin
      AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Error uploading file to OneDrive.');
    end;
  finally
    HttpClient.Free;
  end;

  AppLog.Lines.Add('UploadAndOpenMailWithAttachment - Finished');
  AppLog.Lines.Add('');
end;

 

this is the upload

============

function TMainForm.UploadFileToOneDrive(const LocalFilePath: string;
                                        out OneDriveWebURL : string;
                                        out AttachFileId : string) : Boolean;
var
  HttpClient: THttpClient;
  FileStream: TFileStream;
  FileSize: Int64;
  UploadURL: string;
  Response: IHTTPResponse;
  Headers: TNetHeaders;
  OneDriveItemJSON: TJSONObject;
  Success: Boolean;
begin
  Success := False;
  Result := False;

  AppLog.Lines.Add('');
  AppLog.Lines.Add('');
  OneDriveWebURL := '';
  AttachFileId := '';
  Try
    HttpClient := THttpClient.Create;
    try
      FileStream := TFileStream.Create(LocalFilePath, fmOpenRead or fmShareDenyNone);
      try
        FileSize := FileStream.Size;
        UploadURL := 'https://graph.microsoft.com/v1.0/me/drive/root:/Temp/' + ExtractFileName(LocalFilePath) + ':/content';

        SetLength(Headers, 2);
        Headers[0].Name := 'Authorization';
        Headers[0].Value := 'Bearer ' + FAccessToken;
        Headers[1].Name := 'Content-Type';
        Headers[1].Value := 'application/octet-stream'; // Adjust if needed

        Response := HttpClient.Put(UploadURL, FileStream, nil, Headers);

        AppLog.Lines.Add('ResponseCode (Upload) := ' + IntToStr(Response.StatusCode));
        AppLog.Lines.Add('ResponseBody (Upload) := ' + Response.ContentAsString);

        if (Response.StatusCode = 200) or (Response.StatusCode = 201) then
        begin
          OneDriveItemJSON := TJSONObject.ParseJSONValue(Response.ContentAsString) as TJSONObject;
          try
            if Assigned(OneDriveItemJSON) then
            begin
              OneDriveWebURL := OneDriveItemJSON.GetValue('webUrl').Value;
              AttachFileId   := OneDriveItemJSON.GetValue('id').Value;
              AppLog.Lines.Add('');
              AppLog.Lines.Add('OneDrive Web URL: ' + OneDriveWebURL);
              AppLog.Lines.Add('');
              Success := True;
            end;
          finally
            OneDriveItemJSON.Free;
          end;
        end
        else
        begin
          AppLog.Lines.Add('Error uploading file to OneDrive. Status Code: ' + IntToStr(Response.StatusCode));
          // Optionally log the full error response
        end;

      finally
        FileStream.Free;
      end;
    finally
      HttpClient.Free;
    end;
    Result := Success;
    AppLog.Lines.Add('');
    AppLog.Lines.Add('');
  Except;
    Result := False;
  End;
end;

 

this is the createShareLink Proc

====================

 

function TMainForm.CreateSharingLink(const FileId: string):   TSharingLinkRec;
var
  HttpClient: THttpClient;
  Payload: TStringStream;
  Response: IHTTPResponse;
  JsonObj: TJSONObject;
begin
  Result.webUrl  := '';
  Result.shareId := '';
  Result.Found   := False;
  HttpClient := THttpClient.Create;
  try
    HttpClient.CustomHeaders['Authorization'] := 'Bearer ' + FAccessToken;
    HttpClient.ContentType := 'application/json';

    AppLog.Lines.Add('');
    AppLog.Lines.Add('HttpClient.CustomHeaders[Authorization] : ' + HttpClient.CustomHeaders['Authorization'] );
    AppLog.Lines.Add('HttpClient.ToString : ' + HttpClient.ToString );
    AppLog.Lines.Add('');

    Payload := TStringStream.Create('{"type":"view","scope":"organization"}', TEncoding.UTF8);
    try
      Response := HttpClient.Post(
        'https://graph.microsoft.com/v1.0/me/drive/items/' + FileId + '/createLink',
        Payload);

      AppLog.Lines.Add('CreateSharingLink - Response Status Code: ' + IntToStr(Response.StatusCode));
      AppLog.Lines.Add('CreateSharingLink - Response Body: ' + Response.ContentAsString);
      AppLog.Lines.Add('CreateSharingLink - HTTP Protocol version Version: ' + VarToStr(Response.Version));

      if (Response.StatusCode = 200) or (Response.StatusCode = 201) then
      begin
        JsonObj := TJSONObject.ParseJSONValue(Response.ContentAsString) as TJSONObject;
        try
          Result.webUrl  := JsonObj.GetValue<TJSONObject>('link').GetValue<string>('webUrl');
          Result.shareId := JsonObj.GetValue<string>('shareId');
        finally
          JsonObj.Free;
        end;
      end
      else
      begin
        AppLog.Lines.Add('Failed to create sharing link: ' + Response.StatusText);
        AppLog.Lines.Add('Response Content: ' + Response.ContentAsString);
      end;
    finally
      Payload.Free;
    end;
  finally
    HttpClient.Free;
  end;

  AppLog.Lines.Add('CreateSharingLink - Result.webUrl  = ' + Result.webUrl);
  AppLog.Lines.Add('CreateSharingLink - Result.shareId = ' + Result.shareId);
  Result.Found := (Trim(Result.webUrl) <> '') And (Trim(Result.shareId) <> '');
end;
 

Share this post


Link to post

I have no experience with Microsoft API, but that looks to me that you do not need to create a sharelink first, instead you can directly enter the file or folder as sourceUrl:

 

{
  "post": {
    "body": {
      "contentType": "text",
      "content": "I attached a reference to a file on OneDrive."
    },
    "attachments": [{
      "@odata.type": "#microsoft.graph.referenceAttachment", 
      "name": "Personal pictures", 
      "sourceUrl": "https://contoso.com/personal/mario_contoso_net/Documents/Pics", 
      "providerType": "oneDriveConsumer", 
      "permission": "Edit", 
      "isFolder": "True"
    } ]
  }
}

 

Share this post


Link to post

thanks for you replay. this is not the solution.
just to be clear.
if i send the POST without the Attachment, the mail online is open.


the problem is in the attachment array.


i tried to send full path (from onedrive upload), fileID, linkID, webURL....
dont no what to try more.
chatGPT and Gimini are looping over and over...
the Microsoft stuff send you to articles that send you to more articles...

 

Edited by mazluta

Share this post


Link to post

Have you also provided values for "providerType", "isFolder", ...?

 

See my JSON above.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×