This mail rule script adds the online version of a newsletter to DEVONthink’s or Safari’s reading list.
Setup
1 - Save the script library
As it seems it’s not possible to use AppleScriptObjC inline in a Mail.app rule we need to create a script library.
- Paste this script in Script Editor.app
- Save it
- with name
Add newsletter to reading list
- in folder
/Users/USERNAME/Library/Script Libraries
- with name
-- Script library - Add newsletter to reading list
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
on regexFind(theText, thePattern)
try
set theString to current application's NSString's stringWithString:theText
set {theExpr, theError} to current application's NSRegularExpression's regularExpressionWithPattern:(thePattern) options:0 |error|:(reference)
set theMatches to theExpr's matchesInString:theString options:0 range:{0, theString's |length|()}
set theResults to {}
repeat with thisMatch in theMatches
set thisMatchRange to (thisMatch's rangeAtIndex:0)
set thisMatchString to (theString's substringWithRange:thisMatchRange) as text
set end of theResults to thisMatchString
end repeat
return theResults
on error error_message number error_number
activate
display alert "Error: Handler \"regexFind\"" message error_message as warning
error number -128
end try
end regexFind
on tid(theInput, theDelimiter)
set d to AppleScript's text item delimiters
set AppleScript's text item delimiters to theDelimiter
if class of theInput = text then
set theOutput to text items of theInput
else if class of theInput = list then
set theOutput to theInput as text
end if
set AppleScript's text item delimiters to d
return theOutput
end tid
on decodeBase64(theText, returnPlainAppleScript)
try
set theString to (current application's NSString's stringWithString:theText)
set theData to (current application's NSData's alloc()'s initWithBase64EncodedString:theString options:0)
set theString_decoded to (current application's NSString's alloc()'s initWithData:theData encoding:(current application's NSUTF8StringEncoding))
return theString_decoded as string
on error error_message number error_number
activate
if the error_number is not -128 then display alert "Error: Handler \"decodeBase64String\"" message error_message as warning
error number -128
end try
end decodeBase64
2 - Save the mail rule script
- Paste this script in Script Editor.app
- Save it in
/Users/USERNAME/Library/Application Scripts/com.apple.mail
-- Mail rule script - Add online version of newsletter to reading list
property theNewsletterName : "Altpapier" -- adjust this
property theAssertion_Lookbehind : "Lin=\\nk zum Artikel\" href=3D\"" -- adjust this
property theAssertion_Lookahead : "\" target=3D\"_blank\" rel=3D\"noopener\">ZUM ALTPAPIER" -- adjust this
property theAppName : "DEVONthink" -- "DEVONthink" or "Safari"
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
try
repeat with theMessage in theMessages
set theMessage_Source to source of theMessage
------------------------------------------------------- If necessary: decode base64 --------------------------------------------------------
if theMessage_Source contains "Content-Transfer-Encoding: base64" then
set theMessage_Source_encoded_text to item 1 of script "Add newsletter to reading list"'s regexFind(theMessage_Source, "(?s:(?<=Content-Transfer-Encoding: base64)[^-]*?(?=------=))")
set theMessage_Source_encoded_text_withoutLinefeeds to script "Add newsletter to reading list"'s tid(script "Add newsletter to reading list"'s tid(theMessage_Source_encoded_text, linefeed), "")
set theMessage_Source to script "Add newsletter to reading list"'s decodeBase64(theMessage_Source_encoded_text_withoutLinefeeds, true)
end if
----------------------------------------------------------------- Extract URL ------------------------------------------------------------------
set thePattern to "(?<=" & theAssertion_Lookbehind & ")(?s:https://.*?)(?=" & theAssertion_Lookahead & ")"
set theResults to script "Add newsletter to reading list"'s regexFind(theMessage_Source, thePattern)
if theResults ≠ {} then
set theResult to item 1 of theResults
set theResult_Parts to script "Add newsletter to reading list"'s tid(theResult, "=" & linefeed)
set theURL to script "Add newsletter to reading list"'s tid(theResult_Parts, "")
if theURL contains "=3D" then
set theURL to script "Add newsletter to reading list"'s tid(script "Add newsletter to reading list"'s tid(theURL, "=3D"), "=")
end if
else
error "No URL found"
end if
------------------------------------------------------------- Add to reading list --------------------------------------------------------------
if theAppName = "DEVONthink" then
tell application id "DNtp" to add reading list URL theURL
else if theAppName = "Safari" then
tell application "Safari" to add reading list item theURL
end if
------------------------------------------------------------------ Move mail -------------------------------------------------------------------
set theMailbox to mailbox theNewsletterName of mailbox "Newsletter" of account "iCloud" -- adjust this
move theMessage to theMailbox
end repeat
if the error_number is not -128 then
activate
display alert "Mail" message error_message as warning
end if
end try
end tell
end perform mail action with messages
end using terms from
3 - Copy the mail’s source
- In Mail.app select a newsletter
- Use this helper script to copy the source
- Paste the copied source in a text editor
-- Helper script - Copy selected mail's source
tell application "Mail"
try
set theSelection to selection
if theSelection = {} then error "Please select a mail"
if (count of theSelection) ≠ 1 then error "Please select one mail"
set theMessage to item 1 of theSelection
set theMessage_Source to source of theMessage
if theMessage_Source contains "Content-Transfer-Encoding: base64" then
set theMessage_Source_encoded_text to item 1 of script "Add newsletter to reading list"'s regexFind(theMessage_Source, "(?s:(?<=Content-Transfer-Encoding: base64)[^-]*?(?=------=))")
set theMessage_Source_encoded_text_withoutLinefeeds to script "Add newsletter to reading list"'s tid(script "Add newsletter to reading list"'s tid(theMessage_Source_encoded_text, linefeed), "")
set theMessage_Source to script "Add newsletter to reading list"'s decodeBase64(theMessage_Source_encoded_text_withoutLinefeeds, true)
end if
set the clipboard to theMessage_Source
on error error_message number error_number
if the error_number is not -128 then
activate
display alert "Mail" message error_message as warning
end if
return
end try
end tell
4 - Find the URL in the mail’s source
Unfortunately it’s a bit tricky to find the URL of the online version in a mail’s source. The source of most mails got a maximum line length, if the URL (or the displayed text) is longer than this maximum length then there’s a continuation marker used (=\n
, equal sign and a linefeed). Because of that one can’t simply search for the link’s URL (or the displayed text).
If you can’t find the URL (or the displayed text) in the source try to search for a part of the URL (or the displayed text).
5 - Find regex assertions
Once you’ve found the URL of the online version in the source you’ll need to
- identify what comes before the URL. Use this string in property
theAssertion_Lookbehind
- identify what comes after the URL. Use this string in property
theAssertion_Lookahead
6 - Adjust the mailbox path
The script moves the newsletters to a subfolder of my “Newsletter” mailbox. You need to adjust this line to your Mail.app’s setup
set theMailbox to mailbox theNewsletterName of mailbox "Newsletter" of account "iCloud"
7 - Create a mail rule
- Select a newsletter in Mail.app
- Menu
Preferences > Rules
- Create a new rule
- Choose the mail rule script you’ve created in step 2