More about Receiving Emails Through Apex

The post I wrote once about Receiving and Sending Emails through Apex two years ago has continued to be the most popular post on this blog. So, for all of you that are obviously very interested in this subject, here are some more tips about working with Inbound Emails. In a follow-up post to this one, I will write more about what to consider when sending Outbound Emails.

Creating the Inbound Email Service Handler Class

For starters, the Force.com IDE provides a neat little template for creating an inbound email service handler class. This gives you a head start on creating your inbound email service. To use it just create a new Apex class and select the template drop down box (see image below).

InboundEmailClassTemplate

Using the template will get you a class file that looks like the following. This is a good starting point.

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

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

          return result;
    }
}

As you are filling in the code for this template, you may want to keep the following things in mind:

  • Be careful about creating new records in the database. Many simple code samples I have seen out there automatically create new contact or lead records when an email is received, but if you set something like this up you will quickly end up with a messy database and a lot of redundant records. A better alternative to just blindly creating a new record for each email is to have the logic in the email handler try to match the incoming email sender to an existing record. For example, you could try matching on the name and email address. But be careful here too, because the name on the email header may not exactly match what you have in your database. Probably the best way to ensure that duplication does not occur is to consider creating a task for a user in your org that sends them the email sender info so they can decide whether a new record should be created. Just something that should be discussed with your orgs decision makers before you start blindly creating an automated code solution.
  • The email body can be either HTML or plain text and the results are stored as different properties, so your code should account for this. For example, the following code extracts the email body, no matter which type it is:
String emailBody;       
if (email.plainTextBody != null){
    emailBody = email.plainTextBody;
} else {
    emailBody = email.htmlBody;
}
  • You may want to parse the body of the email and try to extract meaningful information from it, but just keep in mind that this can be very tricky if you are not 100% sure where and how the email is being originated. Obviously HTML content will be more difficult to parse than plain text, but you also do not know if the email client used to submit the email has embedded additional information or special formatting. The solution will depend on your exact circumstances and I only bring this up to make you realize that it might not be as straightforward as you think. Be sure to think this through carefully when designing your solution and try to do testing with all potential email clients.
  • Email attachments could be text or binary and each is handled differently, so you want your code to be able to accept both. For example, you might want to include code similar to the following, which inserts attachments to the Salesforce record, in this case a contact record. Now, of course, this assumes that you do not configure your email service to only accept one form or to always convert Text attachments to Binary (which is an option we will show later on). Also note that the body of a text attachment must be converted into a blob before it can be assigned to the Attachments body field.
if (email.binaryAttachments != null && email.binaryAttachments.size() > 0) 
{
    for (integer i = 0 ; i < email.binaryAttachments.size() ; i++) {         
        Attachment attachment = new Attachment();         
        attachment.ParentId = contact.Id;         
        attachment.Name = email.binaryAttachments[i].filename;Attach         
        attachment.Body = email.binaryAttachments[i].body;         
        insert attachment;     
    } 
} 
if (email.textAttachments != null && email.textAttachments.size() > 0) {
    for (integer i = 0 ; i < email.textAttachments.size() ; i++) {
        Attachment attachment = new Attachment();
        attachment.ParentId = contact.Id;
        attachment.Name = blob.valueOf(email.textAttachments[i].filename);
        attachment.Body = email.textAttachments[i].body;
        insert attachment;
     }
}

Configuring the Email Service

Once you have the code for your email handler, you will need to define the Email Service in your Salesforce Setup. You do this by going to Setup | Develop | Email Services and clicking New Email Service.

At this point, you will need to configure how your email receives incoming messages (see image below).

EmailServiceConfig1

You will of course specify the class handler you just created, but you will also need to keep in mind the following:

  • Most services are configured to accept all attachments, but you can specifically have it accept no attachments or only binary or only text attachments.
  • The Advanced security settings will restrict what emails are accepted by your service according to whether the sender uses certain protocols (specifically SPF, SenderId and DomainKeys). If you do not know for sure what protocol the sender will be using, you do not want to check this.
  • You likely do not want to specify that you accept email from a certain email address, unless your solution is so specific that you know in advance what email address will be sending incoming emails. Leave this blank to accept emails from any address.
  • Don’t forget to check the Active switch for your service.
  • While testing, you will likely want to use Bounce Message as the setting for the failure response settings, but don’t forget to go back and possibly change this after moving to production.
  • I suggest you enable error routing and specify an email address to receive error emails (certainly while testing and maybe even after moving to production).

The next step is to configure the email address that will accept incoming emails (although you can specify more than one). This is the email address that outside users will send email to. Unfortunately, you have no control over the domain name part of this address.  You only get to control what the part before the @ sign looks like. A typical generated email address will look something like the following (where I only got to specify the recievecontactemail part):

receivecontactemail@2fiwoie9n02fazrqxzvaars35bdrih1hxlzg6ij79u66vorcd8.d-dxwdeae.na14.apex.salesforce.com

Ugly, right?

Yeah, I know. If you just can’t see yourself giving this address to people or posting it somewhere, you might want to consider creating a forwarding address (with a much prettier and easier to remember name, like receivecontactemail@yourdomain.com) and then have that email address just forward all emails to the ugly looking one that Salesforce creates for you.

Testing your Email Service

As of Spring 09, Salesforce provides access to Email Logs, which contain info about email sent and received over the last 30 days. You access them through Setup | Monitor | Logs | Email Log Files. You will need to go in and specifically request a new log before it is generated (see image below).

EmailLogRequest

 

You will have to specify a start and end time and the period can be no longer than 7 days. Doing so will generate a CSV file that tells you information such as the email address of each sender and recipient, along with the date and time and any error codes encountered.

You may want to also consider creating a custom error log object. This can be used to store any exceptions or debug statements. For example, you could create a custom object named ErrorLog with text fields used to store the message and other info you may want to capture. Then, in your email handler class, you add try..catch statements that write to the log when an exception is captured.

That’s it for now. More about Outbound Messaging in a later post.

 

 

 

Accessing Salesforce SOAP API through a Proxy Server with a .NET Service Reference

soap If you need to access the Salesforce SOAP API through a proxy server using a .NET Service Reference, you may be confused about how to do this exactly. This would be needed if your .NET application needed to access Salesforce through a firewall. Unfortunately, there is precious little info out there on the Internet (especially when it comes to accessing Salesforce specifically) about how to do this precise thing, hence why I am writing this post.

When adding a web reference (which by the way is considered outdated) you would accomplish this by creating a new WebProxy object, setting the host and port for this object, along with any network credentials that might be needed and then assigning this object to the services Proxy class. This is considered such an outdated method by Microsoft, that MSDN has retired the content that references how to do it.

Microsoft prefers that you use a Service Reference when accessing web services, yet the code to do this is not so easily found. Turns out the solution is pretty simple. Service References allow you to do more advanced configuration through the more easily accessed web.config or app.config files.

BTW, If you want to learn more about the differences between service and web references, check out my DeveloperForce article on this very subject.

The simplest way to configure your application is to add something like the following to your web.config or app.config file:

<system.net>
<defaultProxy useDefaultCredentials=”true”>
<proxy usesystemdefault=”True” proxyaddress=”http:\\Proxy IP Address:Proxy Port”/>
</defaultProxy>
</system.net>

You just need to replace the Proxy IP Address and Proxy Port placeholders with whatever values apply.

Hope this helps someone avoid a lot of wasted time searching the Internet.

Force.com Canvas and .NET Considerations

Introduced in Winter 2013, Force.com Canvas offers a way to host non-native (aka, non-force.com) web applications within Salesforce. Using a signed request, applications developed with your language of choice (including .NET) can connect to Salesforce and access data without requiring the authenticated Salesforce user to also log in to your web application.

I really like this technology because it opens up lots of opportunities for developers and allows shops with little Force.com experience another option. However, that does not mean that using it is all sunshine and butterflies. For one, it is very new and so there is not a lot of documentation out there (especially about .NET). The official developers guide is focused more towards Java developers, yet there are some very specific considerations that need to be made when working in the .NET environment. I recently had the opportunity to convert a Java Canvas app to an MVC Canvas app and this article highlights some of the main considerations you need to make when working in that environment.

MVC Project must use No Authentication

If you are creating a new MVC app, you will need to click “Change Authentication” when creating the project and select “No Authentication” (see NewMVCprojectImage). This will mean that the authentication scaffolding that ASP.NET adds to the project will not be included. I was not able to make a canvas app work with this scaffolding included. Perhaps, it can be done, but the only way I could make it work was to create a new project without the authentication (which makes sense since the authentication is being handled by the signed request and Force.com Canvas).

Must set SSL Enabled Property to True

Regardless of whether an ASP.NET Web forms or MVC application is used, you will need to set the site binding as HTTPS by setting the SSL Enabled property to True. You will also need to ensure that the Managed Pipeline Mode is set as Integrated. These properties can be CanvasMVCPropertiesaccessed by right-clicking the project in Solution Explorer and looking at the properties in the Properties window(see image). Also, note here that the SSL URL is the one you will want to use as the Canvas App URL when setting up the Connected App in Salesforce.

May want to consider using the following GitHub project to do handle the Server-side Authentication

In my project, I created a couple of class files to handle the server side validation of the signed request token passed in from Salesforce. However, to make your life easier and speed your time to development, you may want to consider downloading and using the following GitHub code to do the verification part. I did not find this code until after I had written mine and I thought mine was more streamlined, so I opted to go with it instead. But, looking at Shawn Blanchard’s code could give you a HUGE head start. If you don’t like that example, then you can check out the code that Paul Short posted here. It shows how to do the verification part for both a web form app and an MVC app.

 

 

 

 

 

 

Comparing the Force.com SOAP API to the New Salesforce Toolkit for .NET

Last week I sat in on a webinar titled, “Build Customer Centric Applications Using the Salesforce Toolkit for .NET“, presented Tools_ce2c5aby Wade Wegner and Richard Seroter. As a .NET developer, I was excited to see a new way of connecting Salesforce via .NET. But, I was REALLY excited when I heard that the new toolkit was open-source and provided native libraries that utilized the async and await model in .NET.

I instantly knew that this new method would provide a lightning fast, near real-time alternative for connecting to Salesforce. And, after a little effort putting together a benchmark application, I was able to prove it.

At first, I tried to create a web application using Visual Studio 2010 that would test both the Force.com SOAP API and the new Salesforce Toolkit for .NET. Unfortunately, since the new Salesforce toolkit depends on the Task object and the async and await keywords (which came about with .NET Framework 4.5), using Visual Studio 2010 was not an option.

So, I moved the code to a Visual Studio 2012 web application and added the new Salesforce Toolkit via NuGet Packet Manager (NOTE: that you will need to have NuGet client version 2.8.1 or above, so you may have to take an extra step of upgrading that as I did).

The test application was simple. For both tests, a connection to Salesforce was established and a new case was created. A StopWatch timer was used to measure the run time to the millisecond. The Results?

Well, you should not be surprised to learn that the async-based task using the new toolkit was so fast, it did not even register a single millisecond. That’s right, the time returned was 0.0.

Creating the case via the Force.com SOAP API took an average of 2.32 seconds. Now, you might think 2.32 seconds ain’t bad. But, that time will always vary and could be much longer depending on the process to perform, amount of data and connection speed. There is just no WAY a synchronous method will ever be able to compete with an asynchronous process in terms of processing speed. PERIOD!!!

Now, that also does not mean that the new toolkit does not have it’s issues to consider. Asynchronous processing by itself brings about all sorts of other considerations (such as more complexity), and the following lists some things to consider if you choose to move forward with using the new Salesforce Toolkit for .NET in your org:

  1. You will have to create a connected app in your Salesforce org and then reference the consumer secret and key it provides inside of your code. See this post by Richard Seroter for more on that.
  2. If you use the new toolkit with an ASP.NET page, you will need to do a few extra things, like add an Async=”true” attribute to your page tag and register the async task. Go here to find more information about how to use asynchronous methods in ASP.NET 4.5.
  3. You will have to create a class that defines the Salesforce object you are accessing. This is the most annoying part for me and something I would like to see addressed. With the Force.com SOAP API, you can reference these definitions through the Web Reference you create. You do not have to create them specifically. This means that the Salesforce Toolkit is loosely tied to your org and therefore does not respect any required fields when it comes to object creation. I actually experimented with using the Case reference from the SOAP API in my asynchronous call using the new toolkit, and got back an error when I tried to add a case with no ClosedDateSpecified. This error was not thrown back when I used my own custom class to define the minimal fields for a Case object.

As far as the code is concerned, the following is the code used to perform the test using the new Salesforce Toolkit for .NET:

public class Case
{
        public string Id { get; set; }
        public string Subject { get; set; }
        public string Description { get; set; }
        public string AccountId { get; set; }
        public string Priority { get; set; }
        public string Status { get; set; }
}

public partial class Test : System.Web.UI.Page
{
        public const String subject = "Test Case";
        public const String description = "testing";
        public const String accountId = "001d000001UsLAX";
        public const String priority = "Medium";
        public const String status = "New";
        public const String username = "your user name here";
        public const String password = "your password and security code here";
        public const String consumerKey = "your connected apps consumer key here";
        public const String consumerSecret = "your connected apps consumer secret here";

        protected void Page_Load(object sender, EventArgs e)
        {
            
        }
        protected void NewToolkit_Click(object sender, EventArgs e)
        {
            //Time how long it takes 
            Stopwatch sp = new Stopwatch();
            sp.Start();
            RegisterAsyncTask(new PageAsyncTask(TestToolkit));
            sp.Stop();
            TimeSpan ts = sp.Elapsed;
            //Display the Results of timer
            lblResults.Text = "Runtime: "
                + String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                    ts.Hours, ts.Minutes,
                    ts.Seconds, ts.Milliseconds / 10);
        }
        
        async Task TestToolkit()
        {
            
            //create a connection and get a token to create a new client
            var auth = new AuthenticationClient();
            await auth.UsernamePasswordAsync(consumerKey, consumerSecret, username, password);
            var instanceUrl = auth.InstanceUrl;
            var accessToken = auth.AccessToken;
            var apiVersion = auth.ApiVersion;
            var client = new ForceClient(instanceUrl, accessToken, apiVersion);

            Case sfCase = new Case()
            {
                Subject = subject,
                Description = description,
                AccountId = accountId,
                Priority = priority,
                Status = status
            };

            string Id = await client.CreateAsync("Case", sfCase);
            lblMessage.Text = "The following case was saved sucessfully: " + Id;

        }
}

How to Run the Sample Ruby on Rails Force.com Canvas App Using Windows

First off, I am a big fan of Jeff Douglas and all that he has done for the Salesforce community. I am constantly getting really useful stuff from his blog. That was why I was so excited to see a post he did this month about getting a sample Ruby on Rails Force.com Canvas App.

I have been playing with Ruby, Node.js, and Heroku for several weeks now, so this seemed like a great thing for me to install and check out. The problem was that I ran into quite a few issues while trying to get the app working (primarily because I am trying to do all this on a Windows machine/command line) and not a Linux or OSX shell (as Jeff was obviously using).

This post is all about the problems I ran into and what you can do to avoid them if you are trying to run this on a Windows machine. So, if you want to install Jeff’s Sample Ruby on Rails app, first follow the great instructions on Jeff’s blog, which have you setup the connected app in your developer org.

For the next section about installing the rails-canvas app, if you are running all this on a Windows machine, you will want to consider the following when completing that section:

  • You will need to already have Ruby running on your machine. But, you will specifically need to be running an older version of it in order to get this particular tutorial to work. I already had the newest version of Ruby (2.0) running on my machine, but I found out that it would not work until I used a particular older version (1.9.3) that is deemed more stable (especially on Windows, and even more specifically on a Windows 64bit machine, as I am using). Specifically, I was not able to start the rails server, without getting an error with the eventmachine. I imagine, you might be able to get around this eventually (even though I tried several things), but I think the easiest way is to just use the more stable version of Ruby.
  • To install Ruby on Windows, go to the RubyInstaller web site and download the Ruby 1.9.3-p545 version specifically. If you already have the latest version of Ruby running on your machine, you will either need to uninstall that version or use a Ruby version manager tool (such as rvm for Linux or Pik for Windows) to specify that you need to be running the older version of Ruby.
  • If you do not already have Git (which is an open source code versioning application) installed on your Windows machine, you will need to install this first in order to get the source code required for this demo. To do that on a Windows machine, you will want to go to the GitHub page to download the installer for the msysGit project. I would also recommend installing GitExtensions for Windows, as it makes it much easier (via a GUI) to clone (aka, copy) GitHub projects to a Windows machine.GitRailsClone
  • Once Git is installed, you will need to use either GitBash (which is installed on your Desktop by default with msysGit) or GitExtensions (as seen in the picture on the right) to clone the sample code that Jeff has provided on GitHub.
  • Once the project is cloned to your local machine, you will need to open a command prompt and change directories to the directory where your project files are located. You will then need to bundle the project (which will install any of the gems this project requires). This is done by issuing the following commands from the command prompt (as seen in the image below).
cd/
cd apps/rails-canvas
bundle

BundleRailsProject

  • You will now need to return to Jeff’s post and follow the instructions to get the Consumer Secret for your connected app. Once you have this secret number, you will need to add it as an environment variable. In Windows, this is done using the Set command from the command window. Jeff’s post refers to the export command, but this is specific to the Linux environment. In Windows, you will just change the command to be “set” instead of “export”, and “YOUR_SECRET” will be the numeric code you retrieve from Salesforce, such as the following:
set CLIENT_SECRET=YOUR-SECRET
  • Now this step is something Jeff’s post does not refer to, but is VERY important if you want to get this tutorial to work. If you were to proceed at this point with Jeff’s instructions, you could start the server, tunnel through port 443 to 3000 and even start your Canvas app, but you would probably get a connection failed error in your browser. The error is caused by the fact that the OpenSSL library that Rails installer uses has no certificate authorities defined by default. Yes, you “could” get around this by changing a line of code in the Gemfile to use http and not https, but that would defeat the whole purpose of this tutorial, since Canvas requires https. So, to fix this, you will need to download a certificate (cacert.pem) and install it on your local machine. Follow the steps in this GitHub Gist post to do that. I imagine Jeff did not mention this because he has been working with this stuff for so long, he probably installed a cert file on his machine two years ago.
  • You will then need to start the Rails server, which you can do from the Windows command prompt. You do this by entering “rails s” or “rails server” from the command prompt.TunnelsUsingCommandprompt
  • Jeff’s post instructs you to use sudo to run the tunnels command, but this is a linux command and will mean nothing to you Windows users. Alternatively, you will need to fire up another instance of the Windows Command Prompt, but do so by right-clicking on the app and selecting, “Run as Administrator”. This essentially does the same thing that the sudo command does. From there just enter “tunnels 443 300” (as I did in the screenshot on the right).
  • From there, you will want to open your browser and go to the https:/localhost/canvas page and click the “Understand the Risks” button that you should be presented with.
  • Finally, you can go back to Salesforce and browse to your Sample Canvas app (either using the Chatter tab) or by going to the Canvas App Previewer (as seen below).

RailsCanvasApp

Now, I realize with all these steps, you might be thinking, “Why the Heck bother?” I hear ya!

But, there is something very powerful in understanding how to do all this. Salesforce and the Force.com platform will only be powerful if you are able to interact with it as seamlessly as possible and Canvas apps offer a GREAT way to do this. I hope you are able to get it working using the steps in this post and you do not waste two days (as I did). 🙂

Good Luck…