function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JakesterJakester 

Email attachments to Salesforce, make them automatically go into SF Content

Hello,

 

I'm really excited about SF Content being free for all my users, and I think I have a great way to start using it. We have these PDF reports that go out to our customers, and I'd love it if we could bcc these emails to a Salesforce email address which would grab the attachments and stash them in a workplace (the same workplace for all attachments). I think this should be pretty easy, but I'm not sure where to begin.

 

I know that I'd create an email service, and I'd obviously add that email address to the emails being sent out, and create a new Apex class, but I looked through the Winter '10 API guide and didn't see what kind of calls I'd make - if anyone could give me an idea of what the code would look like, I'd really appreciate it!

 

Help?

Message Edited by Jakester on 12-16-2009 03:29 PM
jkucerajkucera

I'm pretty sure you can use ContentVersion to post new documents.  In the Email Service class you should be able to grab the attachment and then insert a new ContentVersion.

 

http://www.salesforce.com/us/developer/docs/api/index.htm

JakesterJakester

Here's the code that we ended up writing. For simplicity, it only allows 1 attachment per email, and we needed to put them in a specific workspace named "C6 Reports", so that's what we did - it would be easy to modify for your own workspace. Unit tests included! :-)

/**
 * Email services are automated processes that use Apex classes
 * to process the contents, headers, and attachments of inbound
 * email.
 */
global class AttachmentsToContentHandler implements Messaging.InboundEmailHandler {

    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
        Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();

    Messaging.InboundEmail.BinaryAttachment attachment; 

    if (email.binaryAttachments == null) {
      result.message = 'No attachments';  
      result.success = false;
      return result;
    }
    
    else if (email.binaryAttachments.size() != 1) {
      result.message = 'Too many attachments';
      result.success = false;
      return result;
    }
    
    ContentVersion doc = new ContentVersion();
    attachment = email.binaryAttachments.get(0);

    doc.Title = attachment.fileName;
    doc.PathOnClient = attachment.fileName;
    doc.VersionData = attachment.body;
    
    insert doc;

    // maybe 'doc' doesn't have the rest of it's fields filled out automatically after insert? 
    doc = [select ContentDocumentId from ContentVersion where id = :doc.id];

    ContentWorkspace c6Workspace = [select id from ContentWorkspace where name = 'C6 Reports' limit 1];
    // where ContentWorkspaceId = '058500000008Opk'; 

    ContentWorkspaceDoc docLink = new ContentWorkspaceDoc();
    docLink.ContentDocumentId = doc.ContentDocumentId;
    docLink.ContentWorkspaceId = c6Workspace.id;

    insert docLink;

    result.success = true;

        return result;
    }
    
    static testMethod void testHandleInboundEmail()
  {
    // Create a new email, envelope object and Attachment
    Messaging.InboundEmail email = new Messaging.InboundEmail();
       Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();
    Messaging.InboundEmail.BinaryAttachment inAtt = new Messaging.InboundEmail.BinaryAttachment();

    email.subject = 'test';
    env.fromAddress = 'user@acme.com';

    // set the body of the attachment
    inAtt.body = blob.valueOf('test');
    inAtt.fileName = 'Some File.txt';
    inAtt.mimeTypeSubType = 'text/plain';

    email.binaryAttachments = new Messaging.inboundEmail.BinaryAttachment[] {inAtt }; 

    // call the class and test it with the data in the testMethod
    AttachmentsToContentHandler handler = new AttachmentsToContentHandler();
    handler.handleInboundEmail(email, env );                      
  }
  
  static testMethod void testHandleInboundEmailNoAttachment()
  {
    // Create a new email, envelope object and Attachment
    Messaging.InboundEmail email = new Messaging.InboundEmail();
       Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();

    email.subject = 'test';
    env.fromAddress = 'user@acme.com';

    // call the class and test it with the data in the testMethod
    AttachmentsToContentHandler handler = new AttachmentsToContentHandler();
    handler.handleInboundEmail(email, env );                      
  }    
  
  static testMethod void testHandleInboundEmailMultipleAttachments()
  {
    // Create a new email, envelope object and Attachment
    Messaging.InboundEmail email = new Messaging.InboundEmail();
       Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();
    Messaging.InboundEmail.BinaryAttachment attachment1 = new Messaging.InboundEmail.BinaryAttachment();
    Messaging.InboundEmail.BinaryAttachment attachment2 = new Messaging.InboundEmail.BinaryAttachment();
    
    email.subject = 'test';
    env.fromAddress = 'user@acme.com';

    attachment1.body = blob.valueOf('test - attachment1');
    attachment1.fileName = 'Some File1.txt';
    attachment1.mimeTypeSubType = 'text/plain';
    attachment2.body = blob.valueOf('test - attachment2');
    attachment2.fileName = 'Some File2.txt';
    attachment2.mimeTypeSubType = 'text/plain';

    email.binaryAttachments = new Messaging.inboundEmail.BinaryAttachment[] {
      attachment1, attachment2 };

    // call the class and test it with the data in the testMethod
    AttachmentsToContentHandler handler = new AttachmentsToContentHandler();
    handler.handleInboundEmail(email, env );                      
  }    
  

}
 
jkucerajkucera
Thanks for the code!  I may use this in demo's as a good example of how to easily get started with content without the pain of manual upload.
JakesterJakester
Great! If you update it to allow more attachments in a single email, please re-share here :-)
Engine ForceEngine Force

Hi,

 

When I try to save the code, it complains sObject type 'ContentWorkspace' is not supported. I'm using the free enterprise edition.

 

 

Thanks in advance!

jkucerajkucera

You probably don't have Content enabled.  Setup-->Customize App-->Salesforce CRM Content-->Settings

Engine ForceEngine Force

Thanks very much for the quick reply! It does not seem to be enabled in the developer edition though.

Matt WhalleyMatt Whalley
Here is a code snippet for processing multiple attachments, and saving it to attachments:

// parentId is the Id of the record you want to attach it to
Id parentId; // Assign a value to this
list<Attachment> docs = new list<Attachment>();
    if(email.binaryAttachments != null)
    {
     for(Messaging.InboundEmail.BinaryAttachment attachment : email.binaryAttachments)
     {
      Attachment doc = new Attachment();
      doc.Name = attachment.fileName;
         doc.ContentType = attachment.mimeTypeSubType;
         doc.Body = attachment.body;
         doc.ParentId = parentId;
         docs.add(doc);
     }
    
     if(docs != null)
     {
      insert docs;
     }
    }