Retrieve All Notes and Attachments From a Specified Timeframe
Below is some Apex that will hopefully get you started. I have tested this with a simpler SOQL query and it worked.
Depending on the number and size of the attachments you might run into issues here with the Heap size limits. In an email service context the heap size is 36 MB. Otherwise you will need to stay within 10MB, which isn't very large when dealing with multiple attachments.
// As Mohith suggests, try to avoid hardcording a recordTypeId here
// If you deploy the code between orgs the value can change
Id requiredRecordTypeId = '0000000000000';
List<Attachment> attachments =
[SELECT Id, Name, Body, ContentType FROM Attachment
WHERE Parentid IN
(Select Id from FF__Custom_Object__c
WHERE recordtypeid = :requiredRecordTypeId AND
Custom_Record_Age_Field_In_Days__c <= 31))];
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {'[email protected]'};
email.setToAddresses(toAddresses);
email.setSubject('Foo');
email.setPlainTextBody('Bar');
List<Messaging.EmailFileAttachment> emailAttachments = new List<Messaging.EmailFileAttachment>();
for(Attachment att : attachments) {
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
// You may need to do some work here to figure out the correct file extension
efa.setFileName(att.Name);
// Take the blob data from the Attachment and put it on the email.
efa.setBody(att.Body);
efa.setContentType(att.ContentType);
emailAttachments.add(efa);
}
email.setFileAttachments(emailAttachments);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
It will probably be beneficial for the heap size to express the SOQL query directly in the for loop rather than first assigning it to a list and then looping over the list.
SOQL For Loops Versus Standard SOQL Queries
SOQLfor
loops differ from standard SOQL statements because of the method they use to retrieve sObjects. While the standard queries discussed in SOQL and SOSL Queries can retrieve either thecount
of a query or a number of object records, SOQLfor
loops retrieve all sObjects, using efficient chunking with calls to thequery
andqueryMore
methods of the SOAP API. Developers should always use a SOQL for loop to process query results that return many records, to avoid the limit on heap size.
So rather than doing:
List<Attachment> attachments =
[SELECT Id, Name, Body, ContentType FROM Attachment
WHERE Parentid IN
(Select Id from FF__Custom_Object__c
WHERE recordtypeid = :requiredRecordTypeId AND
Custom_Record_Age_Field_In_Days__c <= 31))];
// ...
for(Attachment att : attachments) {
// ...
}
Try:
// ...
for(Attachment att : [SELECT Id, Name, Body, ContentType FROM Attachment
WHERE Parentid IN
(Select Id from FF__Custom_Object__c
WHERE recordtypeid = :requiredRecordTypeId AND
Custom_Record_Age_Field_In_Days__c <= 31))]) {
// ...
}
This answer relates to using the Apex Email API to send the email with your desired attachments. This API is described in the Apex Developers guide here. The following example uses the Single email approach, refer to the docs for the differences between this and the Mass email approach. I have used modified version of your SOQL to test my code, but the same approach applies.
List<Attachment> attachments =
[select Id, Name, Body, ContentType from Attachment
where Parentid IN (select Id from Test__c)];
String currentUserEmail =
[select Email from User
where Id = :UserInfo.getUserId()].Email;
Messaging.reserveSingleEmailCapacity(1);
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] { currentUserEmail });
mail.setReplyTo(currentUserEmail);
mail.setSenderDisplayName('Email Attachments Test');
mail.setSubject('Latest Attachments from Test__c');
mail.setBccSender(false);
mail.setUseSignature(false);
mail.setPlainTextBody('Attached are the latest attachments to the Test__c object, enjoy!.');
mail.setHtmlBody('Attached are the latest attachments to the Test__c object, enjoy!.');
List<Messaging.EmailFileAttachment> emailAttachments = new List<Messaging.EmailFileAttachment>();
for(Attachment attachment : attachments)
{
Messaging.EmailFileAttachment emailAttachment = new Messaging.EmailFileAttachment();
emailAttachment.setBody(attachment.Body);
emailAttachment.setContentType(attachment.ContentType);
emailAttachment.setFilename(attachment.Name);
emailAttachments.add(emailAttachment);
}
mail.setFileAttachments(emailAttachments);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
As per the documentation for the SingleEmailMessage.setFileAttachments method.
A list containing the file names of the binary and text files you want to attach to the email. You can attach multiple files as long as the total size of all attachments does not exceed 10 MB.
RE: Email Templates. I had a quick look at using Email Templates, but the messaging:attachment component does not appear to support bindings for the content and thus I was not sure how you would pass your Attachments into the template. That said I think you may be able to combine the following example with an email template for body via setTemplateId. Let me know if you want this and I'll update the answer.
Hope this helps and enjoy!