Today I needed a reliable way to extract eMail addresses from the content of eMail messages in Apple Mail. After fiddling around with AppleScript’s text item delimiters first, I finally came up with a robust Python helper script utilizing regular expressions.
To share this solution with you, I have created a sample script. The procedure is as follows:
The AppleScript iterates over selected eMail messages in Apple Mail and writes each message content to a temporary file. Then the Python script searches the temporary file for contained eMail addresses and prints them back to AppleScript. Fairly simple
If you want to take a look at the sample script, please feel free to download it right here:
Extract eMail addresses (ca. 36.7 KB)
It was successfully tested on Intel and PowerPC based Macs running Mac OS X 10.5.3 & Apple Mail 3.3.
The Python script is based on a recipe found on the excellent ASPN: Python Cookbook website.
Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because the AppleScript internally relies on a Python script, which is located inside its Script bundle. Therefor please download the complete script here.
-- created: 17.06.2008
-- This AppleScript iterates over selected eMail messages in Apple Mail
-- and tries to extract eMail addresses from the message content.
-- The AppleScript writes the message content to a temporary file, then a Python
-- script parses the temporary file for eMail addresses and prints them back
-- to the calling AppleScript. Finally the temporary file is removed.
property mytitle : "Extract eMail addresses"
-- I am called when the user opens the script with a double-click
on run
try
-- maybe the script was started without Apple Mail being running?
if not my appisrunning("Mail") then
set infomsg to "Sorry, Apple Mail is currently not running." & return & return & "Please open Apple Mail, select appropriate eMail messages and try again."
my dspinfomsg(infomsg)
return
end if
-- getting the selected eMail messages in Apple Mail
tell application "Mail"
set msgs to selection as list
end tell
-- did the user select any eMail messages?
if msgs is {} then
set errmsg to "You did not select any eMail messages in Apple Mail."
my dsperrmsg(errmsg, "--")
return
end if
-- processing the selected eMail messages
repeat with msg in msgs
tell application "Mail"
set msgsubject to subject of msg
end tell
-- extracting the eMail addresses from the message content
set mailaddrs to my extrmailaddrs(msg)
-- no eMail addresses found...
if mailaddrs is {} then
set errmsg to "We could not detect eMail addresses in the content of the eMail message with the subject:" & return & return & msgsubject & return
my dsperrmsg(errmsg, "--")
else
-- displaying the found eMail addresses
choose from list mailaddrs with prompt "We found these eMail addresses in the eMail message content:" & return & return & "(" & msgsubject & ")" with title mytitle with empty selection allowed
end if
end repeat
on error errmsg number errnum
my dsperrmsg(errmsg, errnum)
end try
end run
-- I am returning a list of eMail addresses embedded in the message content
-- If no addresses are found, I return an empty list
on extrmailaddrs(msg)
-- getting the content of the eMail message
tell application "Mail"
set msgcont to content of msg
end tell
-- writing the content of the eMail message to a temporary file
set tmpfilepath to my TmpFile's newpath()
my writetofile(msgcont, tmpfilepath)
-- extracting the eMail addresses from the temporary file using a Python script
set pyscriptpath to POSIX path of (((path to me) as Unicode text) & "Contents:Resources:findmails.py")
set command to "/usr/bin/python/ " & quoted form of pyscriptpath & " " & quoted form of (POSIX path of tmpfilepath)
set mailaddrs to paragraphs of (do shell script command)
-- removing the temporary file
my TmpFile's remove()
return mailaddrs
end extrmailaddrs
-- I am indicating if a given application is currently running or not
-- only the (full) application name must be given, e.g. "Address Book"
on appisrunning(appname)
tell application "System Events"
set processnames to name of every process
end tell
if appname is in processnames then
return true
else
return false
end if
end appisrunning
-- I am displaying error messages
on dsperrmsg(errmsg, errnum)
tell me
activate
display dialog "Sorry, an error occured:" & return & return & errmsg & " (" & errnum & ")" buttons {"Never mind"} default button 1 with icon stop with title mytitle
end tell
end dsperrmsg
-- I am displaying info messages
on dspinfomsg(infomsg)
tell me
activate
display dialog infomsg buttons {"OK"} default button 1 with icon note with title mytitle
end tell
end dspinfomsg
-- I am writing given content to a given file using UTF-8 text encoding
on writetofile(cont, filepath)
try
set openfile to open for access filepath with write permission
set eof of openfile to 0
set BOM_UTF8 to ((ASCII character 239) & (ASCII character 187) & (ASCII character 191))
write (cont as «class utf8») to openfile
close access openfile
return true
on error
try
close access openfile
end try
return false
end try
end writetofile
-- script object to manage a temporary file
script TmpFile
property filepath : missing value
-- I am creating a new, not yet existing file path in the temp folder
on newpath()
set tmpfolderpath to (path to temporary items folder from user domain) as Unicode text
repeat
set rndnum to random number from 1000 to 99999
set tmpfilepath to (tmpfolderpath & (rndnum as Unicode text) & ".tmp")
try
set tmpfilepath to tmpfilepath as alias
on error
set filepath to tmpfilepath
exit repeat
end try
end repeat
return filepath
end newpath
-- I am returning the file path of the temporary file
on getpath()
return filepath
end getpath
-- I am trying to delete the temporary file using the Finder
on remove()
try
set command to "rm " & quoted form of (POSIX path of filepath)
do shell script command
end try
end remove
end script