Attach a File to an Email in Flow
- Michael Kolodner
- 6 minutes ago
- 3 min read
A while back I wrote about a solution I built, using Flow, to solve the annoyance around user ownership of a File when you want to delete it.

You probably won't be surprised that's not the last time Files have given me a headache. (Same client, in fact: For Pete's Sake, a great little organization.) As usual, this was a totally reasonable request. They wanted to include a scan of a lovely handwritten Thank You Note created by the family on respite and send it to the doctor that nominated them. Hat Tip to Andy Utkan for this blog post on Salesforce Break that helped me understand how to make this happen.
Hide and Seek
First step: I have to find the file in question. Good news, I know where it will be! It's uploaded as a File attached to the triggering record (of a custom object called Respite) that fires our record-triggered flow. We even have an agreed-upon naming convention to ensure that the thank you note is distinguishable should there be other attached files: the staff upload with "TYN" in the name. Shouldn't be too hard, right?
Nope. Guess again.
We're talking about Files in Salesforce, or, as I think of it, the ContentWhatever architecture. There always seem to be at least four objects involved! Plus there are special [Specially annoying!] ways you can't work with ContentWhatever in SOQL. To add insult to injury, for some unfathomable reason, I can't even find an ERD (entity relationship diagram) to try to understand the ContentWhatever system visually. Poke around the developer documentation for a bit and you learn that ContentDocumentLink is what attaches a record to a ContentDocument. But don't forget about ContentVersion! I know you care deeply that Salesforce handle file versioning for you. And while we're at it, notice the special note on that page about how queries won't return all files a user has access to. See what I mean about SOQL for ContentWhatever?
Add in some trial-and-error and I confirmed that the Send Email action is going to need the Id of a ContentVersion to use as an attachment, not a ContentDocumentLink, not a ContentDocument. So we have to find:
A ContentVersion
of a ContentDocument,
whose name contains "TYN,"
that is connected via a ContentDocumentLink
to our triggering record.
Thankfully, it's safe to assume there will be one and only one. (Or at least we can just use the most recently created one.)
But we can't just do a Get Records with anything like that list for filters—oh, no, that's not how ContentWhatevers roll. Can't do it with a simple SOQL query either, so UnofficialSF's Execute SOQL action for Flow won't save us.
How To Solve It
Taking basically all the steps in Andy's blog post, I had to:
Get all the ContentDocumentLinks where the LinkedEntityId = our triggering record.

Transform that collection into a list of ContentDocumentIds.

Get the the ContentDocument whose Id is IN the list of ContentDocumentIds AND whose Title CONTAINS "TYN". (We narrow it down to only one by sorting by created date and taking only the newest.)

Check to ensure that a ContentDocument was found. (Because your email will error if you try to send with an attachment but have none to attach.)
Use the LatestPublishedVersionId from the found ContentDocument. {!SecondGetRecordsStep.LatestPublishedVersionId}

Yes, that's a surprising number of steps. It looks like this in the relevant section of the flow:

Then on the branches after the decision we either send an email with an attachment and language about it or a version that has neither.

