Sunday, November 9, 2014

Force.com Inbound Email Services



Email services are there for special purposes in the Force.com platform which uses Apex class to process the incoming email messages. All the attributes in the email message are accessible inside this APEX class and you can easily start using these attributes anywhere in your apex code.
You need to generate a special email address in order to receive email messages, and the Apex class should implement the Messaging.InboundEmailHandler interface and this particular interface defines a single method;

Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, Messaging.InboundEnvelope envelope)

Unlike structured web services, Email services open up the possibility of interacting with any email client with using simple text. When the apex logic is being executed it is capable of executing any number of actions/logics.
As inbound emails can cause material business changes, Force.com allows you to enforce additional security:
  •    You can limit the email senders to specific addresses or domains – Force.com will reject emails from other addresses/domains.
  •    You can enable advanced security if the sender domain(s) support one or more of the protocols SPF, Sender ID, and DomainKeys. This ensures that spoofed emails do not get through.

The rest of this section shows how to set up your inbound email service and write a simple Apex class to react to incoming email. Setting up an email service is simple:

1.     Build an inbound email handler Apex class for processing the email

2.     Configure the email service, binding it to the Apex class


Email Receiver Class 


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
 * 11/09/2014
 * Hasantha Liyanage
 * Read Inbound Mail example code 
 * https://developer.salesforce.com/page/An_Introduction_To_Email_Services_on_Force.com
 */
global class EmailDemoReceive implements Messaging.InboundEmailHandler{
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.Inboundenvelope envelope) {
        Account account;
  Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();     
  
  try {
   
   // Look for account whose name is the subject and create it if necessary
   if ([select count() from Account where Name = :email.subject] == 0) {
     account = new Account();
     account.Name = email.subject;
     insert account;
   } else {
     account = [select Id from Account where Name = :email.subject];
   }
   
   // Convert cc'd addresses to contacts
   if(email.ccAddresses != null){
    for (String address : email.ccAddresses) {
      Contact contact = new Contact();
      Matcher matcher = Pattern.compile('<.+>').matcher(address); 
      // Parse addresses to names and emails
      if (matcher.find()) {
        String[] nameParts = address.split('[ ]*<.+>')[0].replace('"', '').split('[ ]+');
        contact.FirstName = nameParts.size() > 1 ? nameParts[0] : '';
        contact.LastName = nameParts.size() > 1 ? nameParts[nameParts.size()-1] : nameParts[0];
        contact.Email = matcher.group().replaceAll('[<>]', '');
      } else {
        contact.LastName = address;
        contact.Email = address;
      }
      // Add if new
      if ([select count() from Contact where Email = :contact.Email] == 0) {
        contact.AccountId = account.Id;
        insert contact;
      } 
    }
   }
   
   
   // Save binary attachments, if any
   if(email.binaryAttachments !=null){
    for (Messaging.Inboundemail.TextAttachment tAttachment : email.textAttachments) {
      Attachment attachment = new Attachment();
     
      attachment.Name = tAttachment.fileName;
      attachment.Body = Blob.valueOf(tAttachment.body);
      attachment.ParentId = account.Id;
      insert attachment;
    }
   }
   
   // Save text attachments, if any
   if(email.binaryAttachments !=null){
    for (Messaging.Inboundemail.BinaryAttachment bAttachment : email.binaryAttachments) {
      Attachment attachment = new Attachment();
     
      attachment.Name = bAttachment.fileName;
      attachment.Body = bAttachment.body;
      attachment.ParentId = account.Id;
      insert attachment;
    }
   }
   
   // Turn email body into note
   Note note = new Note();
   note.Title = email.fromName + ' (' + DateTime.now() + ')';
   note.Body = email.plainTextBody;
   note.ParentId = account.Id;
    
   insert note;
   result.success = true;
  }catch(Exception e){
   result.success = false;
        result.message = e.getMessage();
  }
    
  return  result;                                       
   }
}


Email Handler Test Class


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
 * 11/09/2014
 * Hasantha Liyanage
 * Read Inbound Mail example code test class
 * https://developer.salesforce.com/page/An_Introduction_To_Email_Services_on_Force.com
 */
@isTest
private class EmailDemoReceiveHandlerTests {
    static testMethod void testInboundEmail() {
    // Create a new email and envelope object
        Messaging.InboundEmail email  = new Messaging.InboundEmail();
        Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();
        
       
        // Set up your data if you need to
        
        // Create the email body
        email.plainTextBody = 'This is the body text which becomes the note';
        email.fromAddress ='hasanthaera@gmail.com';
        String contactEmail = 'hasan@salesforce.com';
        email.ccAddresses = new String[] {'Hasantha Liyanage <' + contactEmail + '>'};
        email.subject = 'Sample Account 0001';
        
        // set the body of the binary attachment
        Messaging.InboundEmail.BinaryAttachment binaryAttachment = new Messaging.InboundEmail.BinaryAttachment();
     binaryAttachment.body = blob.valueOf('test binary attachment');
     binaryAttachment.fileName = ' binary attachment attachment name';
     binaryAttachment.mimeTypeSubType = 'plain/txt';
     email.binaryAttachments = new Messaging.inboundEmail.BinaryAttachment[] {binaryAttachment};
     
     // set the body of the text attachment
     Messaging.InboundEmail.TextAttachment textAttachment = new Messaging.InboundEmail.TextAttachment();
     textAttachment.body = 'test text attachment';
     textAttachment.fileName = 'text attachment attachment name';
     textAttachment.mimeTypeSubType = 'texttwo/plain';
        email.textAttachments = new Messaging.InboundEmail.TextAttachment[] {textAttachment};
        
        EmailDemoReceive edr = new EmailDemoReceive();
        
        Test.startTest();
        Messaging.InboundEmailResult result = edr.handleInboundEmail(email, env);
        Test.stopTest();
        
        System.assert (result.success, 'InboundEmailResult returned a failure message');
        
        Account [] accDb = [select ID from Account where name=:email.subject];
        System.assertEquals (1, accDb.size(),'Account insertion failed!');
        Contact [] cDb = [select firstname,lastname from Contact where email=:contactEmail];
        System.assertEquals (1, cDb.size(),'Contact insertion failed!');
        Contact c = CDb[0];
        System.assertEquals ('Hasantha', c.firstName);
        System.assertEquals ('Liyanage', c.LastName);
        Note [] nDb = [select body from Note where ParentID=:accDb[0].id];
        System.assertEquals (1,nDb.size(), 'The new note should have been attached');
        System.assertEquals (email.plainTextBody, nDb[0].body);
        
    }
}

No comments:

Post a Comment