Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attachments on email templates #17

Open
charomps opened this issue Nov 22, 2018 · 3 comments
Open

Attachments on email templates #17

charomps opened this issue Nov 22, 2018 · 3 comments

Comments

@charomps
Copy link

When I create an email template with an attachment the plugin adds the attachment to azure fine but what it errors when using the email template to send to multiple contacts.

When sending the email it gets stuck in a pending state with an error on the attachment saying that it cannot find the specified attachment in azure.

Looking at the system jobs I can see that upon sending a quick campaign with an email template the BinaryStorageOptions.Plugin: Create of activitymimeattachment is triggering successfully, but the attachment is not appearing in azure causing the error to occur on sending the email.

If i send a single email with an attachment it works fine. Its just upon sending email templates.

Has anyone else come across this?

@DawidPotgieter
Copy link
Owner

DawidPotgieter commented Dec 2, 2018

Hi there,

I'm afraid I don't have time right now to test your scenario, but perhaps you can try this that I've got somewhere on the wiki :

Open the plugin registration tool and register a new step under BinaryStorageOptions.Plugin.
Message = Retrieve
Primary Entity = template
Post Operation / Synchronous

Remember to add the secure and unsecure config xml.

You can test with just this, and you can add one more for "RetrieveMultiple" with the same settings.

Basically, this will tell CRM to use the plugin when reading templates, which is where I can see the email templates are stored at. I'm not certain whether your problem is on the read or create message, but I'm guessing it will actually be on the read.

Let me know how that goes.

Cheers.

Update.

Had a very quick look at this, and it seems the system creates new emails when you run a campaign. Since there's no plugins associated with campaigns, doesn't look like the email attachments work. I will see what I can do about this, can't give you a timeframe atm though...

DawidPotgieter added a commit that referenced this issue Dec 3, 2018
…tachment, try to find the originating attachment and return that instead.
@DawidPotgieter
Copy link
Owner

Update 2.

If you look in the V5 branch here :

https://github.com/DawidPotgieter/Dynamics-CRM-Binary-Storage-Options/blob/V5/Source/BinaryStorageOptions/Plugin.Retrieve.cs

I've added a new method :

private Tuple<int, byte[]> SearchForAttachment(IOrganizationService service, Providers.IBinaryStorageProvider storageProvider, Entity entity, string documentBodyAttributeKey, string fileNameAttributeKey)
{
	//This is a little bit of a hack, but there really isn't very many good options.
	//When there's an error loading an email attachment, there's a good chance that crm is requesting a duplicate of an existing attachment, as that's how it seems to be stored.
	//So, go through the list of activitymimeattachments pointing to the same attachment id, and see if you can get the binary data using that.
	using (OrganizationServiceContext context = new OrganizationServiceContext(service))
	{
		var attachmentId = ((EntityReference)(from ama in context.CreateQuery(CrmConstants.AttachmentEntityName)
																					where ((EntityReference)ama[CrmConstants.AttachmentEntityId]).Id == entity.Id
																					select ama[CrmConstants.AttachmentId]).FirstOrDefault()).Id;
		var activitymimeattachmentIds = (from ama in context.CreateQuery(CrmConstants.AttachmentEntityName)
																			where (Guid)ama[CrmConstants.AttachmentId] == attachmentId
																			select ama[CrmConstants.AttachmentEntityId])
																			.ToList();

		foreach (Guid activitymimeattachmentId in activitymimeattachmentIds)
		{
			try
			{
				int fileSize = storageProvider.GetFileSize(activitymimeattachmentId, (string)entity.Attributes[fileNameAttributeKey]);
				byte[] data = storageProvider.Read(activitymimeattachmentId, (string)entity.Attributes[fileNameAttributeKey]);

				return new Tuple<int, byte[]>(fileSize, data);
			}
			catch { }
		}
	}
	return null;
}

And it's called in the catch block of the "HandleEntity" method above :

if (entity.LogicalName == CrmConstants.AttachmentEntityName)
{
	//Search for other attacments pointing to the same attachment id (not the activitymimeattachment).
	var otherData = SearchForAttachment(service, storageProvider, entity, documentBodyAttributeKey, fileNameAttributeKey);
	if (otherData != null && entity.Attributes.ContainsKey(fileNameAttributeKey))
	{
		if (entity.Attributes.ContainsKey(CrmConstants.FileSizeKey) &&
				(int)entity.Attributes[CrmConstants.FileSizeKey] == GenericConstants.EmptyBodyContentDataLength)
		{
			entity.Attributes[CrmConstants.FileSizeKey] = otherData.Item1;
		}

		if (entity.Attributes.ContainsKey(documentBodyAttributeKey) && 
				(string)entity.Attributes[documentBodyAttributeKey] == GenericConstants.EmptyBodyContent)
		{
			entity.Attributes[documentBodyAttributeKey] = Convert.ToBase64String(otherData.Item2);
		}
		return;
	}
}

You'll also need to add some constants in CrmConstants :

public const string AttachmentEntityId = "activitymimeattachmentid";
public const string AttachmentId = "attachmentid";

This seems to fix the reading issues I can see for campaign generated emails. It's a bit of a hack, but it seems to work.

Hope it helps.

@DawidPotgieter
Copy link
Owner

Hi there,

Did you try the fix? Can I close the ticket perhaps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants