Finding an org-contact record's emails in MailMate and events in Google Calendar

· 462 words · 3 minute read

I’ve been digging MailMate, but missing a function I’d added to my Doom Emacs setup that let me search mu4e for mails from a contact in my contacts.org file. I set out to fix that this evening thinking it’d probably be an AppleScript thing, but it turns out MailMate has its own URL scheme (mlmt:) that includes queries. From the command line, for instance, you’d just do something like open mlmt:quicksearch?string="[email protected]" to search for that address.

(I learned about that from this post by James Sulak (another Emacs person, as it turns out), who shared a set of helpful Alfred workflows for working with MailMate.)

This function grabs the EMAIL property of a given org-contacts heading and runs the open shell command:

(defun mph/open-mlmt-quicksearch ()
  "Open a quicksearch URL for the email address at point."
  (interactive)
  (let ((email (org-entry-get (point) "EMAIL")))
    (if (not (string-empty-p email))
        (shell-command (format "open 'mlmt:quicksearch?string=%s'" email))
      (message "No email address found"))))

MailMate search is very fast. The results are there in an eyeblink.

… and that sort of led to this, which searches Google Calendar for an email address from a contact:

(defun mph/open-gcal-search-for-email ()
  "Open a Google Calendar search page for the email address at point."
  (interactive)
  (let ((email (org-entry-get (point) "EMAIL"))
        (search-url "https://calendar.google.com/calendar/u/0/r/search?q=%s"))
    (if (not (string-empty-p email))
        (progn
          (message "Searching Google Calendar for events with email %s..." email)
           (browse-url (format search-url email)))
      (message "No email address found"))))

… and that suggested this one, which gets a date from the interactive org date picker and creates an all-day Google Calendar event with the contact as an invitee:

(defun mph/create-gcal-all-day-appointment-with-contact ()
  "Create a new all-day appointment in Google Calendar and invite the contact at point."
  (interactive)
  (let* ((date (org-read-date nil t nil "Date: "))
         (formatted-date (format-time-string "%Y%m%d" date))
         (next-day (format-time-string "%Y%m%d" (time-add date (* 24 60 60))))
         (contact-email (org-entry-get (point) "EMAIL"))
         (url (concat "https://calendar.google.com/calendar/u/0/r/eventedit?dates="
                      formatted-date
                      "/"
                      next-day
                      "&pli=1&sf=true&action=TEMPLATE&add="
                      contact-email)))
    (browse-url url)))

I preferred just setting it to all-day, because I’ve learned a few things about scheduling time to catch up with people in a non-business context:

  1. It’s usually gonna be a few weeks out. PTO, busy, etc.
  2. Setting a day is pretty easy, but setting a good time can be hard when it’s that far out. Schedules do things, or we know a given day is usually our good day, but specifics can shift around.
  3. Setting an all-day item and a reminder to lock down the details several days out makes it easier to agree to something and work out the details when calendars are a little more clear. No constant shuffling if one party or the other isn’t in complete control of their own calendar.

I wonder if I should go read a book about how to stay in touch with people. I know there are several.