Is there a way to emulate the Evernote's excellent filing system via Apple Mail?

I moved from Evernote to DT.

I use DT’s filing system via Apple Mail many times a day.
I send myself an email (either new or forward an email of interest) → add @dev in the subject → transfer to DT via Apple Mail rule → filed in Inbox on arrival in DT.

Evernote goes one very convenient step further.
I can write @ in the subject followed by any group name, and evernote will file into that group name.
Example: if I write @kbm in the email subject and send to evernote, evernote will automatically file into the KBM (keyboard maestro) Evernote folder.

I know that I can do this with DT, by creating smart rules on import (example below). My problem is that it requires me to create one rule per group. I am not going to write 500+ smart rules to cover all possibilities of moving to all groups.

What I am looking for is for some way via script or smart rule or both whereby DT

  • reads the name of items being imported. In this case email subject line is automatically converted to filename when it is imported into DT which is great.
  • reads the group name where the item should be filed: if @ is found in the name, the string immediately followed the @ is the group name
  • the group name contains spaces, so it is always put last in the email subject name, so DT knows to read after the @ sign and until the end.

Note that by extension, this would even allow me to create a new DT filing system applicable to any type of file while working inside DT, ie a way of moving documents. When I finish working on a document in the inbox, I simply rename → add @ followed by the group name at the end of the document name and the smart rule with automatically file it. I already do this (see below) but for only a few groups, for the reason stated above: I can’t write 500+ rules. Note that in this case I perform the action on a time basis (looks at my inbox every hour or so for example)

Some people may ask: how do I remember 500+ group names to insert after the @ . It’s very easy: I use a little database of all group names from which I can easily search → insert group name anywhere I want.

thank you for considering this problem.

1 Like

This script should get you started.

Try it to see what it does, then start changing it to fit your needs.

-- Use name to move and rename records

property theDatabaseName : "_temp" -- Set your database name

tell application id "DNtp" to my performSmartRule(selection as list) -- uncomment this line for testing with selected records. comment it out for usage in a Smart Rule

on performSmartRule(theRecords)
	tell application id "DNtp"
		try
			try
				set theDatabase to database named theDatabaseName
			on error
				error "Please open database \"" & theDatabaseName & "\""
			end try
			
			repeat with thisRecord in theRecords
				set thisSubject to my recordName(name of thisRecord, filename of thisRecord)
				
				if thisSubject contains "@" then
					set theOffset to (offset of "@" in thisSubject)
					set theName to (characters 1 thru (theOffset - 2) in thisSubject) as string
					set theGroupName to (characters (theOffset + 1) thru -1 in thisSubject) as string
					
					set theResults to search "name==" & theGroupName & space & "kind:group" in root of theDatabase
					if theResults ≠ {} then
						set theGroup to item 1 of theResults
					else
						set theGroup to create location ("/" & (name of incoming group of theDatabase) & "/" & my replace_String(theGroupName, "/", "\\/")) in theDatabase
					end if
				else
					set theName to thisSubject
					set theGroup to incoming group of theDatabase
				end if
				
				set name of thisRecord to theName
				move record thisRecord to theGroup
			end repeat
			
		on error error_message number error_number
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
			return
		end try
	end tell
end performSmartRule

on replace_String(theText, oldString, newString)
	local ASTID, theText, oldString, newString, lst
	set ASTID to AppleScript's text item delimiters
	try
		considering case
			set AppleScript's text item delimiters to oldString
			set lst to every text item of theText
			set AppleScript's text item delimiters to newString
			set theText to lst as string
		end considering
		set AppleScript's text item delimiters to ASTID
		return theText
	on error eMsg number eNum
		set AppleScript's text item delimiters to ASTID
		error "Can't replaceString: " & eMsg number eNum
	end try
end replace_String

on recordName(theName, theFilename)
	set theSuffix to my getSuffix(theFilename)
	if theName ends with theSuffix and theName ≠ theSuffix then set theName to characters 1 thru -((length of theSuffix) + 2) in theName as string
	return theName
end recordName

on getSuffix(thePath)
	set revPath to reverse of characters in thePath as string
	set theSuffix to reverse of characters 1 thru ((offset of "." in revPath) - 1) in revPath as string
end getSuffix


2 Likes

I created a temp database. Nothing happens after the message “open Database Temp”
I don’t understand what your objective it.
thank you for all the work writing the script.

How did you run the script? With selected records or as a Smart Rule?

This is an error message. You can only see this if there’s no database with the name you have set.

  • Set theDatabaseName to the name of an existing database

  • Make sure that the database is open

  • Select some records.

  • Obviously you have to name the records in the way you‘ve described in your first post - if the records are not named that way they will all be moved to the inbox of the database.

1 Like

OK, thanks I will try again

WOW !! very impressive !!
Would it be possible to create a second version of the script in which you do not remove the @ + string in the name, because sometimes I want to keep it in the filename for later searches.
I can’t find the words to thank you enough. BRILLIANT !

Simply do not set the name

1 Like

thank you @pete31 @chrillek

1- @chrillek do you mean to just comment out
set theName to (characters 1 thru (theOffset - 2) in thisSubject) as string

2- With evernote, I created a .txt file listing all notebooks (equivalent of groups in DT) which I use to insert the group name at the end of filenames or emails using Typinator.
Is there a way to create a .txt list of all groups and subgroups for a database ?.

thanks very much to both of you

No. Remove this line:

set name of thisRecord to theName

Did you hand create the text file in Evernote, as yes that’s certainly possible in DEVONthink?

1 Like

A simple script could do this in DT:

  • define a string variable that is going to hold the group names
  • for each database
    • for each group
      • get the name
      • append it as a new line to the variable defined initially
  • create a new record of type text
  • set this record’s plaintext to the variable’s content

This script copies all group names as flat list (including incoming group, annotations group, tags group, trash group and tags).

-- Copy flat list of all group names of a database (including incoming group, annotations group, tags group, trash group and tags)

tell application id "DNtp"
	try
		if not (exists current database) then error "No database is open."
		set theDatabase to current database
		set theNames to name of parents of theDatabase whose type = group
		set theNames_string to my tid(theNames, linefeed)
		set the clipboard to theNames_string
		display notification "Listing in clipboard!" with title "Create Listing"
		
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
	end try
end tell

on tid(theList, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theString to theList as text
	set AppleScript's text item delimiters to d
	return theString
end tid

2 Likes

thanks very much, but there are problems:

  • it includes tags which makes the list confusing
  • (very) many of the groups are missing from the list
    thanks very much for all your time and effort @pete31

thank you @BLUEFROG

1- in EN I used a script make for that purpose (not written by me). Unfortunately, the script below does not work as I explained to @pete31

2- thank you for info about how to edit the script.

I suppose, you’d have to modify this line
set the clipboard to my createListing(children of root of current database whose type is group)
to exclude tags, especially the part following the whose. There’s an explanation on the usage of whose here: https://leancrew.com/all-this/2013/10/whose-in-applescript/. According to the scripting dictionary, the term might be something like tag type is no tag, but I’m not sure about that.

2 Likes

thank you very much. I will try to edit the script

This script copies all group names as flat list, excluding:

  • incoming group,
  • annotations group,
  • tags group,
  • trash group
  • and tags
-- Copy flat list of all group names of a database (excluding incoming group, annotations group, tags group, trash group and tags)

tell application id "DNtp"
	try
		if not (exists current database) then error "No database is open."
		set theDatabase to current database
		
		set theInboxName to (name of incoming group of theDatabase) as string
		set theAnnotationsName to (name of annotations group of theDatabase) as string
		set theTagsName to (name of tags group of theDatabase) as string
		set theTrashName to (name of trash group of theDatabase) as string
		
		set theNames to name of (parents of theDatabase whose type = group and name ≠ theInboxName and name ≠ theAnnotationsName and name ≠ theTagsName and name ≠ theTrashName and location does not start with ("/" & theTagsName) as string)
		set theNames_string to my tid(theNames, linefeed)
		set the clipboard to theNames_string
		display notification "Listing in clipboard!" with title "Create Listing"
		
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
	end try
end tell

on tid(theList, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theString to theList as text
	set AppleScript's text item delimiters to d
	return theString
end tid

thanks very much. Why is the list of groups/subgroups very incomplete, so much as to make it unusable ?

@chrillek I totally missed this possibility here. That’s of course far better and faster. Updated both scripts. Thanks!

@pete31 @chrillek @BLUEFROG

I finally understand the problem.
When you import EN → DT, EN Notes containing PDFs are bundled into a group consisting of 2 files: a PDF and an HTML file, so that there are a gazillion subgroups.
I therefore have to eliminate subgroups.

The most straightforward method I found was to:

  • create a smart group listing kind is group and excluding subgroups
  • smart group → select all → copy → paste into BBedit → save as txt file → import into Typinator → etc

thank you all for your contributions to this discussion.