From 35ce8facff405f9e5b11badfff598cfc184910b5 Mon Sep 17 00:00:00 2001 From: PointStar Date: Tue, 9 Jun 2026 12:28:05 +0300 Subject: [PATCH] fix(attachments): bind upload to Note.attachments to satisfy EspoCRM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EspoCRM tenant now rejects role=Attachment uploads that carry neither `field` nor `parentType` (400 "No `field` and `parentType`."), which broke the entire save-attachments flow on v1.2.13 — every file, including PDFs, failed at Step 1. Bind the upload to the documented Attachment-Multiple example parentType=Note, field=attachments. Note.attachments is a built-in field with no allowed-file-types restriction, so all types pass (including images) — unlike Document.file, which rejected images with 403. No parentId is set; the blob stays standalone and is still just pushed to the network share. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Services/EspoCrmClient.cs | 27 ++++++++++++------- src/OutlookAddin/Properties/AssemblyInfo.cs | 4 +-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/OutlookAddin.Core/Services/EspoCrmClient.cs b/src/OutlookAddin.Core/Services/EspoCrmClient.cs index a08ea98..20acebd 100644 --- a/src/OutlookAddin.Core/Services/EspoCrmClient.cs +++ b/src/OutlookAddin.Core/Services/EspoCrmClient.cs @@ -214,21 +214,28 @@ namespace MarcusLaw.OutlookAddin.Core.Services // "contents" alias was an undocumented legacy that strict tenants // reject with 400. // - // We deliberately DO NOT bind the upload to Document.file - // (relatedType=Document / field=file). EspoCRM only enforces the - // per-field "allowed file types" list when a field is supplied, and - // Marcus-Law's Document.file field is configured to accept document - // types only (PDF/Word) — images (JPEG/PNG) were rejected with - // 403 "Not allowed file type". This flow never creates a Document; - // the attachment is a standalone blob we immediately push to the - // network share, so an unbound role=Attachment upload is the - // correct shape and lets every file type through. (Server-side fix: - // widen Document.file's accepted types in the Entity Manager.) + // We bind the upload to Note.attachments (parentType=Note, + // field=attachments). EspoCRM's attachment access checker now + // REJECTS a role=Attachment upload that carries neither `field` + // nor `parentType` ("No `field` and `parentType`." → 400) — the + // earlier "unbound blob" shape no longer passes. Note.attachments + // is the documented Attachment-Multiple example and a built-in + // field that carries NO "allowed file types" restriction, so every + // file type (PDF, JPEG, PNG, …) passes — unlike Document.file, + // which Marcus-Law limits to PDF/Word and which rejected images + // with 403 "Not allowed file type". + // + // We never set parentId / create a Note: the attachment stays a + // standalone blob whose id we immediately push to the network + // share. The (parentType, field) pair only satisfies the access + // checker and selects an unrestricted file-type policy. var payload = new Dictionary { ["name"] = fileName, ["type"] = mime, ["role"] = "Attachment", + ["parentType"] = "Note", + ["field"] = "attachments", ["file"] = dataUri }; diff --git a/src/OutlookAddin/Properties/AssemblyInfo.cs b/src/OutlookAddin/Properties/AssemblyInfo.cs index 2815697..691307b 100644 --- a/src/OutlookAddin/Properties/AssemblyInfo.cs +++ b/src/OutlookAddin/Properties/AssemblyInfo.cs @@ -33,6 +33,6 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.13.0")] -[assembly: AssemblyFileVersion("1.2.13.0")] +[assembly: AssemblyVersion("1.2.14.0")] +[assembly: AssemblyFileVersion("1.2.14.0")]