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/ or ~/Library/Scripts/Applications/Mail/
Last Modified: 2022-08-25


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:

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


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)
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 & " | "
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
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