You can't do this out of the box with Flow Send Email action (or any declarative automation tool).
The best you can do within strictly Flow (no invocable apex), is add a public link within your email body. You'd do so by creating a ContentDistribution for your files - which would then allow you to retrieve the DistributionPublicURL
to include in the body of the email.
(Note: this is assuming these are all new files uploaded through your flow, if they're existing files you may want to check if a ContentDistribution
record exists for the file already if someone has generated a share link in the UI).
When creating a Content Delivery (ContentDistribution
) record, you'll want to pass the ContentVersionId
of the file, set a Name
, as well as set preferences on the behavior of the link to meet your needs
- PreferencesAllowOriginalDownload
- PreferencesAllowPDFDownload
- PreferencesAllowViewInBrowser
- PreferencesExpires
- PreferencesLinkLatestVersion
- PreferencesNotifyOnVisit
- PreferencesNotifyRndtnComplete
After creating it, you'll want to re-query it to get the generated URL in DistributionPublicURL
to add to the body of the email. In the Flow, it'd look something like this:
For doing this with attachments on the email, you'd have to use invocable apex to send the email.
If that's a blocker for you, unofficialsf has a Send Better Email Flow Action that has done the work above (apex invocable) already and adds lots of other features. Unlocked package install link is at the bottom of their page.
If you've used any of their packages before, you can simply follow the instructions. You'd just get any
ContentDocumentLink
records you uploaded and pass the collection of them into the relevant input of the flow action.
Note: It seems it's dependent on the following basepacks being installed beforehand if you've never used their packages
- Flow Actions BasePack
- Flow Screen Components Base Pack
If the above is too heavy for this (hesitation to install a lot of components) - you can take a look at their source code and just take the relevant pieces to do yourself. You can see the source code for the unlocked package. I've listed relevant apex classes below and all code snippets provided are copied from the source code:
If you're only interested in adding attachments to email, then you'd pay closer attention to how they do it in apex. The Ids you provide to their LWC action takes ContentDocumentIds
(a collection) in a variable called contentDocumentAttachments.
In SendBetterEmail, it simply loops through all the ContentDocumentLink
records to add the ContentDocument
Id to a set of Ids
if (curRequest.contentDocumentAttachments != null) {
for (ContentDocumentLink contentLink : curRequest.contentDocumentAttachments) {
contentDocumentIds.add(contentLink.ContentDocumentId);
}
}
It then uses sendBetterUtil.getMapContentDocumentIdByContentVersions()
to do as the method implies, get the relevant content version per ContentDocument Id
you provided.
public static Map<Id, List<ContentVersion>> getMapContentDocumentIdByContentVersions(
Set<Id> contentDocumentIds
) {
Map<Id, List<ContentVersion>> mapContentDocumentIdByContentVersion = new Map<Id, List<ContentVersion>>();
for (ContentVersion cv : [
SELECT
Id,
PathOnClient,
Title,
VersionData,
VersionNumber,
FileType,
ContentDocumentId,
FileExtension
FROM ContentVersion
WHERE ContentDocumentId IN :contentDocumentIds
]) {
if (
!mapContentDocumentIdByContentVersion.containsKey(cv.ContentDocumentId)
) {
mapContentDocumentIdByContentVersion.put(
cv.ContentDocumentId,
new List<ContentVersion>{ cv }
);
} else {
ContentVersion lastFound = mapContentDocumentIdByContentVersion.get(
cv.ContentDocumentId
)[0];
if (lastFound.VersionNumber < cv.VersionNumber) {
mapContentDocumentIdByContentVersion.get(
cv.ContentDocumentId
)[0] = cv;
}
}
}
return mapContentDocumentIdByContentVersion;
}
It then takes both the list of ContentDocumentLink
records provided and the map built above to add attachments to the SingleEmailMessage utilized in apex to send email. This is done through setEntityAttachments
public static Messaging.SingleEmailMessage addAttachments(
Messaging.SingleEmailMessage mail,
List<ContentDocumentLink> contentDocumentLinks,
Map<Id, List<ContentVersion>> mapContentDocumentIdByContentVersion
) {
Set<Id> contentVersionIds = new Set<Id>();
if (contentDocumentLinks != null && !contentDocumentLinks.isEmpty()) {
for (ContentDocumentLink cdl : contentDocumentLinks) {
Id contentDocumentId = cdl.ContentDocumentId;
if (
mapContentDocumentIdByContentVersion.get(contentDocumentId) != null &&
mapContentDocumentIdByContentVersion.get(contentDocumentId).size() > 0
) {
for (
ContentVersion cv : mapContentDocumentIdByContentVersion.get(
contentDocumentId
)
) {
contentVersionIds.add(cv.Id);
}
}
}
}
if (contentVersionIds.size() > 0) {
mail.setEntityAttachments(new List<Id>(contentVersionIds));
}
return mail;
}
It then takes the email message (and any other you want) in a list to be sent by Messaging.sendEmail