You need to sign in to do that
Don't have an account?
Attach email attachment to other records via trigger
Hi experts,
I have the following challenge I'm struggling with. The requested functionality is when saving an email with attachment from (e.g.) Salesforce App for Outlook to Salesforce and attaching the email to the opportunity, the attachment itself (not only the email) should additionally be attached to the opportunity.
So far, I figured out that
The problem is - at least that's what I'm thinking - that the entry in the ContentDocumentLink table is created in a separate transaction on the DB. The (after insert) trigger on the task cannot find any entries in the ContentDocumentLink table. If I check via workbench the entry is there.
Here is the trigger (probably not the best code since I'm not a developer - apologies for that :-)):
The message in the Debug log is as follows:
I have the following challenge I'm struggling with. The requested functionality is when saving an email with attachment from (e.g.) Salesforce App for Outlook to Salesforce and attaching the email to the opportunity, the attachment itself (not only the email) should additionally be attached to the opportunity.
So far, I figured out that
- (of course) the email is saved as a task
- the attachment is saved in the ContentDocument table
- the link between the email and the attachment is saved in the ContentDocumentLink table (plus the permissions that are applied)
- additionally the link between the attachment and the opportunity's account (in the task's WhatId) is also saved as an additional entry in the ContentDocumentLink table
The problem is - at least that's what I'm thinking - that the entry in the ContentDocumentLink table is created in a separate transaction on the DB. The (after insert) trigger on the task cannot find any entries in the ContentDocumentLink table. If I check via workbench the entry is there.
Here is the trigger (probably not the best code since I'm not a developer - apologies for that :-)):
trigger addEmailAttachToWhatId on Task (after insert) { ContentDocumentLink doclink= new ContentDocumentLink (); ContentDocumentLink doclinkold= new ContentDocumentLink (); List<Id> tskL = new List<Id>(); List<ContentDocumentLink> doclinkL = new List<ContentDocumentLink>(); List<ContentDocumentLink> doclinks = new List<ContentDocumentLink>(); try{ for(Task t : Trigger.new){ tskL.add(t.Id); } doclinks= [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE LinkedEntityId in :tskL]; }catch(Exception e){ } for(Task task : Trigger.new){ if(task.whatId != null){ for (ContentDocumentLink dlink : doclinks){ if (dlink.LinkedEntityId == task.Id){ doclink.ContentDocumentId= dlink.ContentDocumentId; doclink.LinkedEntityId = task.WhatId; doclink.ShareType = 'V'; doclink.Visibility = 'InternalUsers'; doclinkL.add(doclink); } } } } insert doclinkL; }
The message in the Debug log is as follows:
36.0 APEX_CODE,DEBUG;APEX_PROFILING,DEBUG;CALLOUT,INFO;DB,DEBUG;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,DEBUG;WORKFLOW,DEBUG 12:26:48.0 (585253)|EXECUTION_STARTED 12:26:48.0 (615652)|CODE_UNIT_STARTED|[EXTERNAL]|01q24000000TjWc|addEmailAttachToWhatId on Task trigger event AfterInsert for [00T2400000cMmED] 12:26:48.0 (15796812)|SOQL_EXECUTE_BEGIN|[28]|Aggregations:0|SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE LinkedEntityId IN :tmpVar1 12:26:48.0 (43505087)|SOQL_EXECUTE_END|[28]|Rows:0 12:26:48.44 (44045805)|CUMULATIVE_LIMIT_USAGE 12:26:48.44 (44045805)|LIMIT_USAGE_FOR_NS|(default)| Number of SOQL queries: 1 out of 100 Number of query rows: 0 out of 50000 Number of SOSL queries: 0 out of 20 Number of DML statements: 0 out of 150 Number of DML rows: 0 out of 10000 Maximum CPU time: 0 out of 10000 Maximum heap size: 0 out of 6000000 Number of callouts: 0 out of 100 Number of Email Invocations: 0 out of 10 Number of future calls: 0 out of 50 Number of queueable jobs added to the queue: 0 out of 50 Number of Mobile Apex push calls: 0 out of 10 12:26:48.44 (44045805)|CUMULATIVE_LIMIT_USAGE_END 12:26:48.0 (45844070)|CODE_UNIT_FINISHED|addEmailAttachToWhatId on Task trigger event AfterInsert for [00T2400000cMmED] 12:26:48.0 (47962053)|EXECUTION_FINISHED 12:26:48.53 (53178488)|EXECUTION_STARTED 12:26:48.53 (53192920)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:Task 12:26:48.53 (68766665)|WF_RULE_EVAL_BEGIN|Workflow 12:26:48.53 (68822118)|WF_CRITERIA_BEGIN|[Aufgabe: 00T2400000cMmED]|Email in Subject Line|01Q24000000Upow|ON_CREATE_OR_TRIGGERING_UPDATE|0 12:26:48.53 (73895645)|WF_RULE_FILTER|[Aufgabe : Thema beginnt mit Email] 12:26:48.53 (73924226)|WF_RULE_EVAL_VALUE|E-Mail:Test Email mit Attachment 12:26:48.53 (73931095)|WF_CRITERIA_END|false 12:26:48.53 (73962473)|WF_SPOOL_ACTION_BEGIN|Workflow 12:26:48.53 (73971008)|WF_ACTION| None 12:26:48.53 (73974685)|WF_RULE_EVAL_END 12:26:48.53 (74027751)|WF_ACTIONS_END| None 12:26:48.53 (74035366)|CODE_UNIT_FINISHED|Workflow:Task 12:26:48.53 (75452920)|EXECUTION_FINISHED
It seems it takes some time for creation of the ContentDocumentLink records. You will have to use future method to achieve this. Just create a class and place future method in it. Call this future method from the trigger. I have shared the modified code below:
doclinkL.add(new ContentDocumentLink(ContentDocumentId = dlink.ContentDocumentId, LinkedEntityId = task.WhatId, ShareType = 'V', Visibility = 'InternalUsers'));
Working Log:
Not working log:
Any ideas?
You cannot call Future method from inside another future method or batch process. We will have to go with some different approach. Will explain you in some time.
Thanks,
Pankaj
The only solution which I can think of to go with the batch approach which will run nightly on daily basis. Just create a custom Boolean field on Activity(Task) named as isProcessed. The Batch will fetch all the records where isProcessed = false and process them i.e. ContentDocumentLink records will be created in the same manner as you are doing in the trigger.
Please let me know if this makes sense to you. I will share the Batch code once I get consent from your end.
Thanks,
Pankaj
Thanks,
Stefanie
One of my clients uses Outlook to attach emails to a custom object. We want the attachment to relate to the custom object as well (a very similiar use case to your problem).
Here's the code to do just that.
http://zydecodigital.com/wordpress/2019/05/24/salesforce-auto-relate-email-message-attachment/ (http://zydecodigital.com/wordpress/2019/05/24/salesforce-auto-relate-email-message-attachment)
You were on the right direction but had the trigger on the task instead of the ContentDocumentLink.
Randall