Sends the selected emails, from Apple Mail or Outlook 2016, to an Inbox project in the active TaskPaper 3 document.
To enable outlook:// links from TaskPaper back to the message in Outlook 2016, you will need to:
- Download the zip of this Github repository: https://github.com/acidix/OutlookURLHandler
- Follow the first three steps in its readme.md, to install the URL handler.
( It isn't code signed, so you may have to refer to this:
https://support.apple.com/kb/PH18657?locale=en_US
but the source code is simple and visible )
(message:// links back to Mail work by default)
KM Macro:
Send selected emails to TaskPaper 3 inbox.kmmacros (26.7 KB)
Source of the JavaScript for Automation action:
// SEND EMAILS SELECTED IN APPLE MAIL OR MS OUTLOOK 2016
// TO INBOX: PROJECT OF FRONT TASKPAPER DOCUMENT
// Ver 0.5 detects whether the front application is Mail or Outlook 2016
// Ver 0.4 Allows for MS Outlook as well as Apple Mail
// Ver 0.31 Keeps whole inbox sorted when new material arrrives,
// fixes issue when only 1 email was selected
// checks that new Inbox is created and used if none found
// Ver 0.2 Sorts incoming mail by sender A-Z and datetime received New-Old
(function (dctOptions) {
'use strict';
// TASKPAPER CONTEXT
function TaskPaperContext(editor, options) {
// FIND OR MAKE A PROJECT TO HOLD INCOMING MAIL
// String -> String -> {project: tpItem, new: Bool}
function projectAtPath(strProjectPath, strDefaultName) {
var strDefault = strDefaultName || 'UnNamed project:',
outline = editor.outline,
lstMatch = outline.evaluateItemPath(strProjectPath),
blnFound = lstMatch.length > 0;
return {
project: blnFound ? lstMatch[0] : (function () {
var defaultProject = outline.createItem(
strDefault
);
return (
outline.groupUndoAndChanges(function () {
outline.root.appendChildren(
defaultProject
);
}),
defaultProject
);
})(),
new: !blnFound
};
}
// tpItem -> (tpiItem -> tpItem -> (-1|0|1)) -> tpItem
function sortChildren(item, fnSort) {
var lstSort = item.children.sort(fnSort);
return (
item.removeChildren(item.children),
item.insertChildrenBefore(
lstSort
),
true
);
}
// FIND OR CREATE AN INBOX
var outline = editor.outline,
mInbox = projectAtPath(options.inboxPath, 'Inbox:'),
itemInbox = mInbox.project,
lstMsg = options.messages;
// Doesn't seem to be undoable
// Perhaps only mutations of existing material undo ?
outline.groupUndoAndChanges(function () {
lstMsg
.forEach(function (msg) {
var item = outline.createItem(
'- ' + [msg.sender, msg.subject]
.join(' ') +
' @received(' + msg.received + ')'
);
itemInbox.appendChildren(item);
item.appendChildren(
outline.createItem(msg.link)
);
});
});
if (!mInbox.new && itemInbox.hasChildren) {
sortChildren(itemInbox, function (a, b) {
var strRA = a.getAttribute('trailingMatch') || '', // date
strRB = a.getAttribute('trailingMatch') || '',
strTA = a.bodyString, // all
strTB = b.bodyString,
iFromA = strTA.charAt(2) === '"' ? 3 : 2,
iFromB = strTB.charAt(2) === '"' ? 3 : 2,
// Lowercase content, ignoring "- "
// + any opening doubleQuote
strCA = strTA.slice(
iFromA, iFromA - strRA.length
)
.toLowerCase(),
strCB = strTB.slice(
iFromB, iFromB - strRB.length
)
.toLowerCase();
// By A-Z sender and New to Old date
return strCA === strCB ? (
strRA < strRB ? 1 : (strRA > strRB ? -1 : 0)
) : (strCA < strCB ? -1 : 1);
});
return 'From: ' + options.appName + '\n' + lstMsg
.map(function (x) {
return x.subject;
})
.join('\n');
}
}
// JAVASCRIPT FOR AUTOMATION CONTEXT
// Date -> String
function fmtTP(dte) {
var s = dte.toISOString(),
d = s.substring(0, 10);
return dte.getMinutes() ? d + ' ' + s.substring(11, 16) : d;
}
// String -> String
function mailURL(strMessageID) {
return "message://%3C" + strMessageID + "%3E";
}
// concatMap :: (a -> [b]) -> [a] -> [b]
function concatMap(f, xs) {
return [].concat.apply([], xs.map(f));
}
// READ MAIL or OUTLOOK SELECTIONS
var lstMailApps = ['com.apple.mail', 'com.microsoft.Outlook'],
procs = Application("System Events")
.applicationProcesses.whose({
_match: [ObjectSpecifier()
.frontmost, true]
}),
strAppID = procs.length ? procs[0].bundleIdentifier() : undefined,
iApp = strAppID ? lstMailApps.indexOf(strAppID) : undefined;
if ((iApp !== undefined) && (iApp !== -1)) {
// Key message fields
if (strAppID.toLowerCase()
.indexOf('outlook') !== -1) {
// MS OUTLOOK 2016
dctOptions.appName = "Outlook 2016";
var ol = Application("com.microsoft.Outlook"),
lstSeln = ol.selectedObjects();
dctOptions.messages = concatMap(function (x) {
var strClass = x.class();
if (strClass
.endsWith('Message')) {
var dctSender = x.sender();
return [{
'sender': dctSender.name + ' ' +
dctSender.address,
'subject': x.subject(),
'received': strClass.indexOf(
'incoming') ===
0 ? fmtTP(x.timeReceived()) : '',
'link': 'outlook://' + x.id()
}]
} else return [];
}, lstSeln);
} else {
// APPLE MAIL
dctOptions.appName = "Apple Mail";
var m = Application("Mail"),
lstSeln = m.selection();
dctOptions.messages = lstSeln.length > 0 ? lstSeln
.map(function (msg) {
return {
'sender': msg.sender(),
'subject': msg.subject(),
'received': fmtTP(msg.dateReceived()),
'link': mailURL(msg.messageId()),
};
}) : [];
}
var ds = Application("com.hogbaysoftware.TaskPaper3")
.documents,
d = (ds.length ? ds[0] : undefined);
if (d) {
if (d.file()) {
return d.evaluate({
script: TaskPaperContext.toString(),
withOptions: dctOptions
});
} else {
var a = Application.currentApplication(),
sa = (a.includeStandardAdditions = true, a),
strMsg =
"Script: (Email to TaskPaper)\n\nFirst save TaskPaper file ...",
strAppFolder = sa.pathTo("applications folder", {
from: 'user domain'
})
.toString();
sa.displayDialog(strMsg, {
withTitle: "TaskPaper file not saved"
});
}
}
} else return strAppID + ' is not a recognised email application'
})({
inboxPath: '//Inbox and @type=project[-1]'
});