[SalesForce] Email Body Text capture in Email Service

Within an email-service apex class, I am trying to scan the body of an incoming email for the following text:

Name: James Johnson
Email Address: jamesjohnson@gmail.com

How would I use my apex class to capture "James Johnson" from the body of the email, and insert it into the Account's "Name" field? Likewise I would like to capture "jamesjohnson@gmail.com" and insert it into the "Email" field.

global class EmailDemoReceive implements Messaging.InboundEmailHandler {
global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, 
                                                     Messaging.Inboundenvelope envelope) {
Account account;
Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
System.debug('############'+result);

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;
         System.debug('############'+account.Name );
         insert account;
         System.debug('account inserted');
    } 
    else 
    {
        account = [select Id from Account where Name = :email.subject];
    }
    // Convert cc'd addresses to contacts
    for (String address : email.ccAddresses) 
    {
         System.debug('for loop activated');
         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 attachments, if any
    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;
    }

    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 = "Oops, I failed";
  System.debug('Oops I failed');
}

return result;
 }
 }

Best Answer

You will need to determine if the inbound email has a plain text body. If it doesn't then you need to convert the html to plain text.

string bodyText;
if (string.isEmpty(email.plainTextBody)
   bodyText = HtmlToText(email.htmlBody);
else
   bodyText = email.plainTextBody;

public static string HtmlToText(string html){
   //replace all <BR> tags with \n to support new lines
   string result = html.replaceAll('<br/>', '\n');
   result = result.replaceAll('<br />', '\n');

   //all HTML/XML tags
   string HtmlPattern = '<.*?>';

   Matcher match =  Pattern.compile(HtmlPattern).matcher(result);

   //remove the tags and return string     
   return match.replaceAll('');
}

Next, use a Matcher to search for 'Name:' and 'Email Address:'. These are two possible regular expressions that will return a line of text that starts with 'Name:' and 'Email Address:'

(?m)(?i)^name:.*

(?m)(?i)^email address:.*

These are multiline (?m) case-insensitive (?i) patterns that will match lines starting with Name: and Email Address:

Once you have the name and email address lines you can parse again to get the values you need to update the Account or Contact object.

The regular expressions above are based on my limited knowledge of what the actually email looks like. Be sure to test thoroughly in your unit test.