C-Command Software Forum

Looking for a mail related AppleScript

Hello everyone,

I am looking for a simply script to include in some of my Mail Act-On rules. All the AppleScript would do is take the current message in capture it into EF. I tag incoming and outgoing emails heavily, and would like to make sure that I can organize them in EF without any having fallen through the cracks.

Thank you very much,

Daniel.

I could help you with the EagleFiler portion of this, but I’m not exactly sure how MailActOn runs scripts. Are the messages that you want to operate on always selected in the user interface? If so, you could simply use EagleFiler’s “capture” script command. Otherwise, if you get something like:

on perform mail action with messages _messages for rule _rule

you would have to get the source of the message, save it as a .eml file, and tell EagleFiler to import that file.

Mail Act-On rules have an option of running an AppleScript, and when they are executed by the end user, the script is run against the active message (I know it works since I have an AppleScript for sending a message to Evernote, which works fine).

I figured I could use the EF capture command, and wrote the following small script:

tell application "EagleFiler"
	capture
end tell

When I try to run it I always get the:

An error occurred when capturing from Mail:

Mail may be downloading from the server or moving messages between mailboxes. Please wait until the Activity window (in the Window menu) is empty or take it offline.

I think this has something to do with the fact that the command is being invoked form within Mail Act-On, since doing the capture manually works fine. Saving the message as an .eml and then having EF pick it up will be cleaner.

The Import From Apple Mail script may help.

Michael,

Not having MailTags imported makes this not really workable for me. Is that it is something that is impossible to do? I adopted a script to send my mails to EverNote and include the MailTag information (pasted below). If you think the portion that captures the MailTagas could be adopted in your script, that would be ideal.

I adopted the script to my purposes (for instance, I always have a Project associated with an email).

Daniel.

-- pseudo code
-- get selected email in Apple Mail
tell application "Mail"
    --activate
    
    set selectedEmails to get selection -- returns a list
    -- get url of selected email (to be stored in Evernote Note source url)
    
    
    -- see if we have a selection first. If not, quit
    try -- trap error if nothing selected
        set singleEmail to item 1 of selectedEmails
    on error
        display alert "Whoops! No email message(s) selected. Can't continue" buttons {"OK"} cancel button 1
    end try
    
    repeat with singleEmail in selectedEmails
        
        --set messageURL to "message://%3c" & singleEmail's message id & "%3e" -- Evernote mail interface doesn't support source url yet
        
        
        set emailSubject to subject of singleEmail
        using terms from application "MailTagsScriptingSupport"
            set emailTags to keywords of item 1 of singleEmail --returns a list
            -- get MailTags project for selected email
            set emailProject to project of singleEmail -- returns MailTags project
        end using terms from
        
        
        
        -- form subject from existing subject + #tags +#project
        set keywordTotal to length of emailTags
        set tagString to "@" & emailProject & " #email"
        set tag to ""
        repeat with k from 1 to keywordTotal
            set tagString to tagString & " #" & (item k of emailTags)
        end repeat
        set emailSubject to emailSubject & " " & tagString
        
        
        
        -- get Evernote account email address
        -- stored in Address Book as contact 'Evernote Notebook' - an organisation
        tell application "Address Book"
            set lastName to "Evernote"
            --set myList to email of (people whose last name) contains lastName
            set thePeople to (every person whose organization = "Evernote Notebook")
            
            try
                set thePerson to item 1 of thePeople -- thePeople is a list
            on error
                display alert "Whoops! No Address Book contact named 'Evernote Notebook' (organisation). Can't continue" buttons {"OK"} cancel button 1
            end try
            
            try
                set theRecipientEmailAddress to (value of item 1 of email of thePerson) -- email returns a list
            on error
                display alert "Whoops! No email address to send to. Can't continue" buttons {"OK"} cancel button 1
            end try
        end tell
        
        
        
        -- create email to Evernote account using contents of selected email
        set newMessage to make new outgoing message at end of outgoing messages
        tell newMessage
            set content to singleEmail's content
            set subject to emailSubject
            make new to recipient with properties {address:theRecipientEmailAddress}
            delete cc recipients
        end tell
        send newMessage
        
    end repeat
    
    -- now sync the evernote app to retrieve the added notes
    tell application "Evernote"
        synchronize
    end tell
    
end tell

Yes, I think you could change the importMessages handler of the script to something like:

on importMessages(_messages)
    repeat with _message in _messages
        tell application "Mail"
            set _subject to subject of _message
            set _source to source of _message
        end tell
        using terms from application "MailTagsScriptingSupport"
            set _keywords to keywords of item 1 of _message
            set _project to project of _message
            set _tagNames to _keywords
            if _project is not missing value then
                set _tagNames to _tagNames & {_project}
            end if
        end using terms from
        set _path to my createTempFolder() & "/" & my makeFileName(_subject)
        my writeData(_path, _source)
        tell application "EagleFiler"
            tell library document 1
                import files {_path} tag names _tagNames
            end tell
        end tell
    end repeat
end importMessages

where are the messages going?
So I have the script invoked in my outbox rule but I am not seeing the messages being saved…

Have you tested that the script is actually being invoked?

Have you tested that script, when not invoked from a rule, saves the files?

Now I have… I tested running the script against a selected email message. I tested it both from the scripts dropdown as well as opening the script in the script editor and clicking on the run button.

While at it, I had the Finder window opened to the To Import folder for the EF Library currently open.

When invoked from the scripts dropdown, nothing happens. When invoked from the script editor, I get the following error message:

error “EagleFiler got an error: Can’t make application “EagleFiler” into type library document.” number -1700 from application “EagleFiler” to library document

Daniel.

I’ve modified the script snippet so it should work now.

Michael,

It works! The only strange thing it does is that when the script is invoked through a rule it generates a message that the email I am trying to import already exists. I checked to make sure it does not. At the end of the day the email ends up in EF, so the error message is not indicating any problem I am aware of.

Thanks as always!

Daniel.

Maybe the script is being executed twice?

That’s my guess. It does not make sense otherwise, as I am not getting the error when I launch the script manually.

Just went through all my scripts, and it is indeed invoked twice. Mystery resolved.

Daniel.

The script in its entirety


on run
	tell application "Mail"
		if my isLionOrBetter() and (count of message viewers) is 1 then
			-- If there's more than one, and full screen mode is active, we can't tell which is frontmost
			return my importFromViewer(message viewer 1)
		else
			repeat with _viewer in message viewers
				if index of _viewer's window is 1 then
					my importFromViewer(_viewer)
				end if
			end repeat
		end if
	end tell
end run

on isLionOrBetter()
	tell application "Mail"
		set AppleScript's text item delimiters to "."
		set _versionString to version
		set _major to (first text item of _versionString) as number
		return _major ≥ 5
	end tell
end isLionOrBetter

using terms from application "Mail"
	on perform mail action with messages _messages
		my importMessages(_messages)
	end perform mail action with messages
end using terms from

on importFromViewer(_viewer)
	tell application "Mail"
		set _messages to (get selected messages of _viewer)
		my importMessages(_messages)
	end tell
end importFromViewer

on importMessages(_messages)
	repeat with _message in _messages
		tell application "Mail"
			set _subject to subject of _message
			set _source to source of _message
		end tell
		using terms from application "MailTagsScriptingSupport"
			set _keywords to keywords of item 1 of _message
			set _project to project of _message
			set _tagNames to _keywords
			if _project is not missing value then
				set _tagNames to _tagNames & {_project}
			end if
		end using terms from
		set _path to my createTempFolder() & "/" & my makeFileName(_subject)
		my writeData(_path, _source)
		tell application "EagleFiler"
			tell library document 1
				import files {_path} tag names _tagNames
			end tell
		end tell
	end repeat
end importMessages

on writeData(_path, _data)
	set _file to POSIX file _path
	set _fd to open for access _file with write permission
	write _data to _fd
	close access _fd
end writeData

on createTempFolder()
	set _tempFolder to do shell script "mktemp -d -t 'EFImportAppleMail'"
	return _tempFolder
end createTempFolder

on makeFileName(_subject)
	set _clean to my replace(_subject, "/", ":")
	set _clean to my replace(_clean, ":", "-")
	set _extension to ".eml"
	set _hfsPlusLimit to 255
	set _max to _hfsPlusLimit - (length of _extension)
	set _shortened to my substringToIndex(_clean, _max)
	return _shortened & _extension
end makeFileName

on substringToIndex(_string, _index)
	if length of _string > _index then
		set _end to _index
	else
		set _end to length of _string
	end if
	return my join(characters 1 thru _end of _string, "")
end substringToIndex

on replace(_string, _source, _replacement)
	return my join(my split(_string, _source), _replacement)
end replace

on join(_list, _sep)
	set _temp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to _sep
	set _result to _list as string
	set AppleScript's text item delimiters to _temp
	return _result
end join

on split(_string, _sep)
	set _temp to AppleScript's text item delimiters
	set AppleScript's text item delimiters to _sep
	set _result to text items of _string
	set AppleScript's text item delimiters to _temp
	return _result
end split