Import From Apple Mail
Summary: Imports the selected or rule-processed messages from Apple Mail as .eml files.
Requires: EagleFiler
Install Location: ~/Library/Application Scripts/com.apple.mail or ~/Library/Scripts/Applications/Mail/
Last Modified: 2022-08-25
Description
The recommended way to import from Apple Mail is to select some messages and press the capture key. That will import the messages as a new mailbox file. This script is for situations where you want to:
- Import messages as individual .eml files instead of as a mailbox. You can import them into an existing folder if desired. This is less efficient than the normal way that EagleFiler stores messages in a mailbox, but for smaller numbers of messages you may find it more convenient.
- Automate importing the selected messages.
- Import the messages that are being processed by a Mail rule. (Note that, on macOS 10.13, if the message contains attachments, Mail might not download them before applying the rule, so they will not be included in the message source sent to EagleFiler.)
Unlike when using the capture key, the unread/flagged status and MailTags are not preserved.
If you want the script to bring up the options window asking you where import the messages, remove the -- before with asking for options.
Installation Instructions · Download in Compiled Format · Download in Text Format
Script
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()
considering numeric strings
return (system version of (system info)) ≥ "10.7"
end considering
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)
set _paths to {}
repeat with _message in _messages
tell application "Mail"
set _subject to subject of _message
set _source to source of _message
end tell
set _inflatedPath to my createTempFolder() & "/" & "Inflated"
my writeInflatedUnicode(_inflatedPath, _source)
set _path to my createTempFolder() & "/" & my makeFileName(_subject)
my deflate(_inflatedPath, _path)
copy _path to end of _paths
end repeat
tell application "EagleFiler"
import files _paths -- with asking for options
end tell
end importMessages
on writeInflatedUnicode(_path, _string)
set _file to POSIX file _path
set _fd to open for access _file with write permission
write _string to _fd as Unicode text -- UTF-16; byte order doesn't matter since will ignore nil bytes
close access _fd
end writeInflatedUnicode
on deflate(_inflatedPath, _deflatedPath)
-- cat u.eml | tr -d '\000' > out.eml
set _script to "cat " & _inflatedPath's quoted form & " | "
# https://unix.stackexchange.com/questions/45404/why-cant-tr-read-from-dev-urandom-on-osx
set _script to _script & "LC_CTYPE=C tr -d '\\000'"
set _script to _script & " > " & _deflatedPath's quoted form
do shell script _script
end deflate
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