Parse Calendar and Contact Data to Enable Better User Engagement

Parse Calendar and Contact Data to Enable Better User Engagement

Learn how to parse data from your user’s calendar and contacts book to help them better engage external clients.

Ben Lloyd Pearson | May 4, 2020

People who manage relationships with external customers and prospects rely heavily on their calendar to keep track of meetings and their contacts book to keep tabs on important info for the people they care about. If you’re a developer who is building an app to help people like this, there is a good chance you’ve found a need to parse calendar and contact book data into your app, and maybe you’ve even considered building direct integrations with third party APIs, like the Google Calendar API. 

The Nylas Communications Platform is a single point of integration that provides access to 100% of all email, calendar, and contacts providers. Nylas enables you to build complex email, calendar, and contacts functionality, this article will teach you how you can use Nylas to build a full-feature dashboard to help your users better engage with external clients and prospects.

Help Your Users Better Engage Their Clients

The Nylas Email, Calendar, and Contacts APIs provide a simple REST interface you can use as the backend for your integration. Nylas enables you to quickly build email, calendar, and contacts functionality, so you can focus on features your users will love. 

In this post, you’ll learn how to use Nylas to help your users better engage their clients with the following functionality:

  • Keep track of important meetings your user has with prospects with the Nylas Calendar API.
  • Enrich the user experience by adding detailed contact information for prospects with the Nylas Contacts API.
  • Make it easy for users to quickly auto-draft emails to prospects that fit the context of their relationship with the Nylas Email API.

The Nylas Email, Calendar, and Contacts APIs is the back end that enables you to build a user experience that looks something like this:

Parsing Data from a user's calendar and contacts book to display a front end user interface

How to Use Nylas To Build Your Email, Calendar, & Contacts Integration

Now, we’ll take a look at what it takes to use the Nylas Email, Calendar, and Contacts APIs to add new functionality to your app. For this example, we’ll use the Nylas Python SDK, but we also offer SDKs for Node.js, Java, and Ruby.

Before starting, you’ll need to take 30 seconds to register your Nylas account and get your developer API keys. Specifically, you need the Client ID and Client Secret for your Nylas app, and an access token for an email account that you want to use. We’ll save these as environment variables so they’re more secure; take a look at our guide on Python environment variables to learn more.

You also need to install the nylas package by heading over to the terminal and running the command pip install nylas. Now we’re ready to start writing code!

Initialize The Nylas Client

To start, import the os and datetime packages; os lets us access our system’s environment variables and datetime will make it easier to access events within specific timeframes. We also need to import the APIClient object from nylas which allows us to make requests to the Nylas Communications Platform. We’ll do this last step inside the main loop for the script.

from nylas import APIClient
import os
import datetime

CLIENT_ID = os.environ['CLIENT_ID']
CLIENT_SECRET = os.environ['CLIENT_SECRET']
ACCESS_TOKEN = os.environ['ACCESS_TOKEN']

def main():
    # Initialize a Nylas client object that uses your user's access token
    nylas = APIClient(
        CLIENT_ID,
        CLIENT_SECRET,
        ACCESS_TOKEN
    )

Parse Calendar Data With The Nylas Calendar API

Now that we’ve setup a Nylas client object, it’s time to parse data into our script that we’ll use to build email, calendar, and contacts functionality. Start by defining the three timeframes in which to organize the user’s meetings: 1) upcoming meetings the user has this week, 2) meetings the user had over the past 7 days, and 3) meetings the user had a month ago. We’ll use the python datetime library to do this; this code will exist in the same main loop used to initialize the Nylas client.

def main():   
    today = datetime.date.today()  
    # Get a datetime for Monday and Friday of this week
    monday = today + datetime.timedelta(days=-today.weekday(), weeks=0)
    friday = monday + datetime.timedelta(days=5)  
    # Get the last week
    past_week_start = today + datetime.timedelta(days=-7)
    # Define the time range for 30-36 days ago
    distant_start_time = today + datetime.timedelta(days=-36)
    distant_end_time = today + datetime.timedelta(days=-30)

Now it’s time to start making requests to the Nylas Communications Platform. The first request will be to the Calendars endpoint to return all calendars the user has access to. Then, we’ll get the id for the calendar named “Prospect Meetings,” this id will be used to make requests for events that exist on the calendar.

def main():
    # Request all calendars the user has access to
    calendars = nylas.calendars.all()
    # Get the calendar_id of the calendar named "Prospect Meetings"
    calendar_id = [ calendar['id'] for calendar in calendars if 'Prospect Meetings' in calendar['name'] ][0]

Next, make a request to the Events endpoint to return lists of events for the three timeframes we defined above. In this example, the requests are filtered to only return events for the calendar we’re interested in and that are in between the start times and end times we defined. Nylas uses epoch timestamps to represent time, so this script converts the datetime objects we created earlier into an integer representations of seconds. Keep in mind, this is a shared calendar across the entire team, so it includes meetings for all users who have added events to this calendar.

def main():
    # Return all events between this Monday and Friday
    all_upcoming_events = nylas.events.where(
        calendar_id=calendar_id,
        starts_after=monday.strftime("%s"),
        ends_before=friday.strftime("%s")
    )
    # Return all events in the last week
    all_past_events = nylas.events.where(
        calendar_id=calendar_id,
        starts_after=past_week_start.strftime("%s"),
        ends_before=today.strftime("%s")
    )
    # Return all events 31-37 days ago
    all_distant_events = nylas.events.where(
        calendar_id=calendar_id,
        starts_after=distant_start_time.strftime("%s"),
        ends_before=distant_end_time.strftime("%s")
    )

Parse Meeting Data with the Nylas Calendar API

Now that we have all of the events for our specified times, it’s time to write some functions to work with these events. This section will show your how to get all of the prospect meetings the user is participating in and return contact information for the prospects the user will meet with.

Find All User Meetings

First, we need to filter the three lists of events we created earlier to include only meetings for which the user is a participant. To do so, use the Account endpoint to return the user’s email address and compare it to the list of participants for each event. 

# Accepts: A nylas client object and list of events from the Nylas Calendar API
# Returns: A list of all events in which the user is a participant
def get_user_events(nylas, events):
    # Find the events where the user is a participant
    user_email = nylas.account.email_address
    user_events = []
    for event in events:
        # Get a list of all participants for the evnet
        participants = [participant["email"] for participant in event["participants"]]
        # If the user is one of the participants, add this event to the list that's returned
        if user_email in participants:
            user_events += [event]
    return user_events

Participants include a name, email address, status, and comment:

{
  ...
  "participants": [
      {
          "comment": "I'm looking forward to learn about your product!",
          "email": "[email protected]",
          "name": "Stephanie Kwolek",
          "status": "yes"
      },
      {
          "comment": null,
          "email": "[email protected]_company.com",
          "name": "Susan Seller",
          "status": "yes"
      }
  ],
  ...
}

Parse Contact Data with the Nylas Contacts API

Now that we have a list of events to work with, let’s use the Nylas Contacts API to parse data about the prospects the user will meet with.

Get Prospect Contact Info

The first thing we need to do to parse contact data is to get a list of the email addresses for the prospects the user is meeting with. Like the previous function, this next function accepts a Nylas client object, and a list of events, and it filters to include only events for which our user is a participant. For each of these events, the script returns all email addresses found in the participants attribute and appends them to a list. These email addresses will be used in the next example to enrich our app with detailed contact information from the Nylas Contacts API.

# Accepts: A nylas client object and list of events from the Nylas Calendar API
# Returns: A list of email addresses for the prospects that are participating in the events
def get_prospect_emails(nylas, events):
    prospect_emails = []
    user_email = nylas.account.email_address
    internal_domain = "my_company.com"
    for event in events:
        participants = [participant["email"] for participant in event["participants"]]
        if user_email in participants:
            prospect_emails += [participant for participant in participants if internal_domain not in participant and participant not in prospect_emails]
    return prospect_emails

Now we’ll create a function that accepts a list of email addresses and uses the Contacts endpoint to return detailed data about the user’s contact. This data can be used to enrich the user experience to provide valuable information about the user’s prospects like their email address, job title, company name, phone number, and more.

# Accepts: A Nylas client object and a list of prospect emails
# Returns: A List of Nylas contact objects
def get_contact_info(nylas, emails):
    contacts = []
    for email in emails:
        contact = nylas.contacts.where(email=email).first()
        if contact:
            contacts += [contact]
    return contacts

Here is an abbreviated example of a response from the Nylas Contacts API.

{
    "given_name": "Stephanie",
    "surname": "Kwolek",
    "company_name": "Fiber Synth",
    "emails": [
        {
            "email": "[email protected]",
            "type": "work"
        }
    ],
    "job_title": "Material Scientist",
    "notes": "Status: Prospect",
    "phone_numbers": [
        {
            "number": "(061) 820-1490",
            "type": "business"
        }
    ],
    ...
}

Build Intelligent Email Interactions

Now that we’ve pulled in the event and contact information our app needs, it’s time to start integrating email functionality to monitor our user’s follow up emails with prospects and auto-draft customized emails to them.

Check Follow Up Status

We want to make it easy for our user to track whether they’ve followed up with prospects they’ve met in the last week. To do so, we’ll write a function that accepts an email address and a list of events and uses the Nylas Messages endpoint to search for any emails our user has sent to the prospect since the end of their most recent meeting.

# Accepts: A Nylas client object, a prospect email, and a list of Nylas event objects
# Returns: Boolean that indicates if user has sent an email to the prospect since their latest meeting.
def has_follow_up(nylas, email, events):
    # Get the most recent email the user sent to the prospect
    most_recent_sent_message = nylas.messages.where(in_="Sent", to=email, limit=1).first()
    # Assign the message date to a variable we'll use later
    try:
        last_comm_time = most_recent_sent_message.date
    except AttributeError:
        # If the user has never sent an email to the prospect, set this value to 0
        last_comm_time = 0

    prospect_meetings = []
    # Check all event participants for the prospect email address
    for event in events:
        participants = [participant["email"] for participant in event["participants"]]
        if email in participants:
            prospect_meetings.append(event)
    if prospect_meetings:
        # Find the last meeting the prospect was a participant in
        last_meeting = prospect_meetings[len(prospect_meetings)-1]
        last_meeting_time = last_meeting.when['end_time']

    # If the last meeting timestamp is larger than the last communication time, it means our user hasn't yet followed up.
    if last_meeting_time > last_comm_time:
        print("You need to follow up with {}".format(email))
        return False
    else:
        print("{} has been followed up with!".format(email))
        return True

Auto-Draft Emails:

The Drafts endpoint makes it super easy to create new email drafts and send them directly from user accounts. The next function accepts a prospect’s email address, creates a new draft, assigns basic data to the draft like a subject line, body, and to / from email addresses, saves the draft, and sends it.

# Accepts: a Nylas client and a prospect's email address
# Returns: Nothing. It creates an email and sends it.
def draft_email(nylas, email):
    draft = nylas.drafts.create()
    draft.to = [{'email': email}]
    draft.subject = "Following up on our discussion earlier"
    draft.body = "Just wanted to say hi and find out if there is anything I can do to help."
    draft.from_ = [{'email': '[email protected]', 'name': 'Your Name'}]
    draft.save()
    draft.send()

Reconnect With Distant Contacts

The last major feature of this Nylas integration is a panel to help our user reconnect with prospects they haven’t communicated with in a while.

Check for Reengagement

Sometimes relationships with prospects go stale, but it doesn’t mean the relationship should stop. Our next function will help the user reconnect with prospects they haven’t spoken to in a while. In this example, we’ll look for prospects the user met with 30-36 days ago, and highlight any that the user hasn’t sent an email to in the past 29 days. We can then offer the user the option to either draft an email to reconnect with the prospect, or modify the prospect contact info to indicate the lead is stale if there doesn’t appear to be a chance of the rebooting the relationship.

This next function takes a prospect’s email address as an argument, searches the user sent folder for the most recent email that was sent to the prospect, and indicates if the user needs to send a new email. 

# Accepts: A Nylas client object and an email address
# Returns: Boolean that indicates if the user has sent an email to the address within the specified timespan
def is_stale(nylas, email):
    # Find the last email the user sent to the provided email address
    last_message = nylas.messages.where(in_="Sent", to=email, limit=1).first()
    # Define the period of time we want the user to respond after
    follow_up_period = int((datetime.date.today() + datetime.timedelta(days=-29)).strftime("%s"))
    
    # If follow_up_period is smaller than the date for the last message, it means an email has been sent within this period, and the user doesn't need to respond.
    if follow_up_period < last_message.date:
        last_message_pretty = datetime.datetime.fromtimestamp(last_message.date).strftime("%B %d, %Y")
        print("Last communication to {} was on {}".format(email, last_message_pretty))
        return False
    else:
        print("You need to follow up with {}".format(email))
        return True

Mark Contacts as Stale with The Nylas Contacts API

Finally, sometimes relationships with prospects come to an end, our last function will take a prospect email as an argument and use the Contacts endpoint to update the prospect’s notes field to indicate the prospect is stale.

def mark_stale(nylas, email):
    contact = get_contact_info(nylas, [email])[0]
    contact.notes = "Status: Stale"
    print(contact)
    contact.save()

Putting it All Together

Now, it’s time to go back to our main loop and add code to generate the content we need for the three panels for upcoming meetings, past meetings, and distant meetings.

For each panel, it generates three lists: the events our user is a participant in, the email addresses for all prospects attending our user’s meetings, and detailed contact objects for all prospects attending the meetings. Then, the panels execute functionality to serve their various functions.

The upcoming meetings panel uses the Messages endpoint to search for the most recent email our user sent to each prospect and display the date of that email.

def main():
    # ----------------------- Upcoming Meetings Panel
    user_upcoming_events = get_user_events(nylas, all_upcoming_events)
    upcoming_prospect_emails = get_prospect_emails(nylas, user_upcoming_events)
    upcoming_prospect_info = get_contact_info(nylas, upcomingprospect_emails)
    for email in upcoming_prospect_emails:
        last_message = nylas.messages.where(in_="Sent", to=email, limit=1).first()
        if last_message:
            print("The most recent message sent to {} was on {}".format(
                email,
                datetime.datetime.fromtimestamp(last_message["date"]).strftime("%B %d, %Y - %H:%M:%S")
            ))
        else:
            print("No communications with {}".format(email))

The past meetings panel also uses the Messages endpoint to search for the most recent email sent to each prospect. From here, it differs because it then compares the timestamp for this email to the timestamp for the most recent meeting with the prospect. If the email is older than the meeting, it prompts the user to draft a follow up email with the Drafts endpoint.

def main():   
    # ----------------------- Past Meetings Panel
    user_past_events = get_user_events(nylas, all_past_events)
    past_prospect_emails = get_prospect_emails(nylas, all_past_events)
    past_prospect_info = get_contact_info(nylas, past_prospect_emails)
    for email in past_prospect_emails:
        if not has_follow_up(nylas, email, user_past_events):
            print("Drafting an email to {}!".format(email))
            draft_email(nylas, email)

The reconnect panel determines if the user has sent an email to the prospect in the last month. If not, there are two options: mark the user as stale with the Contacts endpoint or draft a new email to check in with the prospect.

def main():
    # ----------------------- Prospect Reconnect Panel
    user_distant_events = get_user_events(nylas, all_distant_events)
    distant_prospect_emails = get_prospect_emails(nylas, all_distant_events)
    distant_prospect_info = get_contact_info(nylas, distant_prospect_emails)
    for email in past_prospect_emails:
        if is_stale(nylas, email):
            mark_stale(nylas, email);
            #draft_email(email)

When you’re ready to run your code, don’t forget to initialize the main loop.

if __name__ == "__main__":
    main()

Nylas Takes Your Email, Calendar, & Contacts Integration Further

The Nylas Communications Platform is the easiest way to integrate with 100% of calendar providers in the world. Here’s a few resources to teach you about what else is possible with Nylas.

About the Author

Ben is the Developer Advocate for Nylas. He is a triathlete, musician, avid gamer, and loves to seek out the best breakfast tacos in Austin, Texas.

Ready to Start Building?