AppleScript Email to OF - Help please

Hi All,

I am sure that via this forum I got a huge productivity boost when I found this golden script that allowed me to use Launchbar to invoke. The script then got the last email I sent and popped it into the OF quick entry window with a magic attachment of a link back to the original sent email. This is a massive help to me BUT … as I have changed employers I am moving email and as such the script does nothing now. I am trying to simply just access my standard iCloud sent email, but I can’t get it to work.

Help really appreciated (as I can’t seem to track down the originator) :D

	Add last sent email to OmniFocus Script
	by, Sven Fechner
	Straight forward script that sends the last email sent in to OmniFocus either using the Quick Entry window or silently (well, with Growl based notifications if desired) straight to the Inbox.
	You can influence how the task is named by modifying the PreFix and MidFix properties. The note of the task will contain a link back the email in
	Use the AppleScript Menu or tools likle FastScripts, Launchbar or Alfred to trigger the script.
	The script uses Growl from the App Store for feedback notification if it is installed and running. 

-- account for the sent mailbox the script should use
-- Note that although you can theoretically target the virtual sent mailbox of all acocunts combined
-- AppleScript delivers very inconsistent results when doing so, hence this is not recommended
property theAccount : "iCloud"

-- Open OmniFocus Quick Entry window (true) or add the task silently to the OmniFocus Inbox (false)?
property ShowQuickEntry : true

-- First text in the task name before the email recipient
property PreFix : "Waiting For"

-- Text between receipient name and subject in the task name
property MidFix : "to come back re"

-- Enable Growl notification when adding tasks to OmniFocus Inbox?
-- Growl is not used when using the Quick Entry window
property GrowlRun : true


on run
	my addEMail()
end run

on alfred_script(q)
	my addEMail()
end alfred_script

-- Main functionality

on addEMail()
		tell application "Mail"
			set theSentMailbox to mailbox "Sent" of account theAccount
			set lastMsg to first message in theSentMailbox
			set theSubject to subject of lastMsg
			set theRecipient to name of to recipient of lastMsg
			set theMessageID to urlencode(the message id of lastMsg) of me
			-- See if there is more than one recipient in the 'To' field
			if (count of theRecipient) > 1 then
				set theRecipientName to (item 1 of theRecipient & (ASCII character 202) & "and" & (ASCII character 202) & ((count of theRecipient) - 1) as string) & (ASCII character 202) & "more"
				set theRecipientName to item 1 of theRecipient
			end if
		end tell
		set theTaskTitle to PreFix & (ASCII character 202) & theRecipientName & (ASCII character 202) & MidFix & (ASCII character 202) & theSubject
		set theNote to "Created from message://%3C" & (theMessageID) & "%3E"
		tell application "OmniFocus"
			if ShowQuickEntry then
				tell quick entry
					make new inbox task with properties {name:theTaskTitle, note:theNote}
					tell application "System Events" to keystroke tab
				end tell
				tell default document to make new inbox task with properties {name:theTaskTitle, note:theNote}
				if GrowlRun then
					my growlSetup()
					my growlNotify(theTaskTitle)
				end if
			end if
		end tell
	on error theError
	end try
end addEMail

-- Text encoding routine
on urlencode(theText)
	set theTextEnc to ""
	repeat with eachChar in characters of theText
		set useChar to eachChar
		set eachCharNum to ASCII number of eachChar
		if eachCharNum = 32 then
			set useChar to "+"
		else if (eachCharNum ≠ 42) and (eachCharNum ≠ 95) and (eachCharNum < 45 or eachCharNum > 46) and (eachCharNum < 48 or eachCharNum > 57) and (eachCharNum < 65 or eachCharNum > 90) and (eachCharNum < 97 or eachCharNum > 122) then
			set firstDig to round (eachCharNum / 16) rounding down
			set secondDig to eachCharNum mod 16
			if firstDig > 9 then
				set aNum to firstDig + 55
				set firstDig to ASCII character aNum
			end if
			if secondDig > 9 then
				set aNum to secondDig + 55
				set secondDig to ASCII character aNum
			end if
			set numHex to ("%" & (firstDig as string) & (secondDig as string)) as string
			set useChar to numHex
		end if
		set theTextEnc to theTextEnc & useChar as string
	end repeat
	return theTextEnc
end urlencode

Just did this (very) basic version. Test in Script Editor (language tab set to JavaScript). If this works, it could be improved.

// Twitter @unlocked2412
// This script opens OF Quick Entry with
// details of the last e-mail sent.

(() => {
    'use strict';

    // main :: IO ()
    const main = () => {
            mbox = Application('Mail').sentMailbox,
            lrDict = bindLR(
                // Sent Messages ?
                0 === mbox.messages.length ? (
                    Left('No sent e-mails.')
                ) : Right(mbox.messages())
                    msg => ({
                        'subject': msg.subject(),
                        'msgURL': `message://%3C${
        return isLeft(lrDict) ? (
        ) : ofQuickEntry(lrDict.Right)

    // OMNIFOCUS FUNCTIONS -------------------------------------------------
    // ofQuickEntry :: JS Dict -> OF Item
    const ofQuickEntry = dct => {
            appOF = Application('OmniFocus'),
            qe = appOF.quickEntry,
            doc = appOF.defaultDocument,
            dctTask = {
                name: dct.subject,
                note: dct.msgURL
            oTask = appOF.InboxTask(dctTask);

        return (
    // GENERIC FUNCTIONS ---------------------------------------------------
    // Left :: a -> Either a b
    const Left = x => ({
        type: 'Either',
        Left: x

    // Right :: b -> Either a b
    const Right = x => ({
        type: 'Either',
        Right: x

    // bindLR (>>=) :: Either a -> 
    // (a -> Either b) -> Either b
    const bindLR = m =>
        mf => undefined !== m.Left ? (
        ) : mf(m.Right);

    // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
    const compose = (...fs) =>
        x => fs.reduceRight((a, f) => f(a), x);

    // head :: [a] -> a
    const head = xs => xs.length ? xs[0] : undefined;

    // isLeft :: Either a b -> Bool
    const isLeft = lr =>
        ('Either' === lr.type) && (undefined !== lr.Left);

    // MAIN ----------------------------------------------------------------
    return main()
1 Like

OMG!!! - You absolute Star!! Works perfectly. My email process feels complete! I can not thank you enough. Love the power of this community

1 Like