How to Connect with MailChimp API in Ruby Code

I’ve been working on a simple newsletter signup feature for my Ruby on Rails application, and I hit a snag that I believe many developers can relate to. Today, I want to share my journey diagnosing and resolving an error with the MailChimp API. I’ll walk you through my original code, explain the error I encountered, and finally present a revised version with additional functionality for practice. Let’s dive in!

Error Code

In my MailChimp controller, I wrote the following code to handle newsletter signups capturing a user’s name and email address. When the form data was submitted, I received an error response.

MailchimpController < ApplicationController

require "net/http"
require "uri"

def subscribe
if request.post?
mailchimp = {}
mailchimp['apikey'] = 'f72328d1de9cc76092casdfsd425e467b6641-us2'
mailchimp['id'] = '8037342dd1874'
mailchimp['email_address'] = "email@gmail.com"
mailchimp['merge_vars[FNAME]'] = "FirstName"
mailchimp['output'] = 'json'

uri = URI.parse("http://us2.api.mailchimp.com/1.3/?method=listSubscribe")
response = Net::HTTP.post_form(uri, mailchimp)
mailchimp = ActiveSupport::JSON.decode(response.body)

if mailchimp['error']
render :text => mailchimp['error'] + "code:" + mailchimp['code'].to_s
elsif mailchimp == 'true'
render :text => 'ok'
else
render :text => 'error'
end
end
end

end

Decoding the Error Message

When I executed this code, I was greeted with the following error:

"Method is not exported by this server -90"

What does this really mean?

  1. API Endpoint/Method Issue:
    The error tells me that the API method I’m trying to call listSubscribe is not available from the MailChimp server I’m interacting with. This typically hints at one or more underlying issues.
  2. Deprecated API Version:
    The code is using MailChimp API version 1.3. As I later learned, this version is outdated. MailChimp has since upgraded to newer versions (like v3.0), which use updated endpoints and different methods.
  3. Insecure Connection and Endpoint Changes:
    I was using an http:// URL instead of https://. MailChimp now requires secure communication, and the endpoint URL might be different from what was originally used.
  4. Parameter Mismatch:
    Sometimes the format or naming of parameters (such as merge variables) changes between versions, leading to errors when the server receives unexpected input.

Steps I Took to Resolve the Issue

Here’s what I did after encountering the error:

  • Updated the Connection to HTTPS:
    I switched the URL from http to https for secure communication.
  • Considered Upgrading the API Version:
    Although for demonstration I continued with version 1.3, I made a note to eventually refactor my code to use the current MailChimp API version (v3.0). This involves a deeper change including switching to JSON-based requests and possibly using a dedicated Ruby gem.
  • Refined Error Handling:
    To capture and log any unexpected errors, I wrapped the HTTP call inside a begin-rescue block.
  • Introduced Dynamic Input Handling:
    Instead of hardcoding email and first name values, I modified the code to accept parameters from the newsletter signup form.
  • Added Extra Functionality:
    To experiment further, I added a dummy unsubscribe function that simulates removing a user from the list. This shows how one might extend similar functionality to other endpoints.

The Improved Code

Below is my revamped MailChimp controller with enhanced error handling, dynamic input, and additional unsubscribe functionality:

 MailchimpController < ApplicationController

require "net/http"
require "uri"
require "json"

# Subscribe action for newsletter signup
def subscribe
if request.post?
# Retrieve form data (ensure your form posts these parameters)
email = params[:email] || "email@gmail.com"
first_name = params[:first_name] || "FirstName"

mailchimp_params = {
'apikey' => 'f72328d1de9cc76092casdfsd425e467b6641-us2',
'id' => '8037342dd1874',
'email_address' => email,
'merge_vars[FNAME]' => first_name,
'output' => 'json'
}

# Use HTTPS endpoint for added security
uri = URI.parse("https://us2.api.mailchimp.com/1.3/?method=listSubscribe")

begin
response = Net::HTTP.post_form(uri, mailchimp_params)
result = JSON.parse(response.body)

if result['error']
render :text => "Error: #{result['error']} (code: #{result['code']})"
elsif result == true || result == 'true'
render :text => 'Subscription successful!'
else
render :text => 'An unexpected error occurred.'
end
rescue StandardError => e
logger.error "Mailchimp Subscribe Error: #{e.message}"
render :text => "An error occurred: #{e.message}"
end
end
end

# Additional practice functionality: Simulated Unsubscribe action
def unsubscribe
if request.post?
email = params[:email] || "email@gmail.com"

mailchimp_params = {
'apikey' => 'f72328d1de9cc76092casdfsd425e467b6641-us2',
'id' => '8037342dd1874',
'email_address' => email,
'output' => 'json'
}

uri = URI.parse("https://us2.api.mailchimp.com/1.3/?method=listUnsubscribe")

begin
response = Net::HTTP.post_form(uri, mailchimp_params)
result = JSON.parse(response.body)

if result['error']
render :text => "Error: #{result['error']} (code: #{result['code']})"
elsif result == true || result == 'true'
render :text => 'Unsubscription successful!'
else
render :text => 'An unexpected error occurred.'
end
rescue StandardError => e
logger.error "Mailchimp Unsubscribe Error: #{e.message}"
render :text => "An error occurred: #{e.message}"
end
end
end
end

Key Enhancements and Benefits

  • Dynamic Form Data Handling:
    Instead of static values, I now accept parameters directly from the form. This flexibility is crucial for real-world applications where user input varies.
  • Secure Communication via HTTPS:
    Switching to HTTPS ensures my API calls are secure and compliant with MailChimp’s requirements, reducing the chance for security-related errors.
  • Robust Error Handling:
    By wrapping the HTTP request in a begin-rescue block, any network or JSON parsing errors are gracefully caught and logged. This means my users see friendly error messages rather than a crashing application.
  • Additional Unsubscribe Functionality:
    I added a dummy unsubscribe action, showcasing how easy it is to extend functionality. This pattern can be duplicated to implement further interactions with the MailChimp API, such as updating subscriber details or fetching mailing list stats.

Final Thoughts

I learned that even a seemingly simple newsletter signup can present a range of challenges from outdated API versions and insecure endpoints to parameter mismatches and inadequate error handling. The error "Method is not exported by this server -90" was a clear signal that changes were needed. By updating the connection protocol, embracing dynamic user input, and beefing up error management, I not only solved the problem but also set the stage for further enhancements.

Related blog posts