You are not logged in.
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:
Applescript:
-- 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
Offline
Hi!
Wow, thanks! This was just what I was looking for. I'm a colplete newbie at applescript, but I added some lines that creates an outgoing message with the addresses found in the mail as recipients. As you can tell by my un-stringent coding this is just a schmack-hack.
I use this for my forwarded mail from Exchange to gmail, where the from-address gets moved into the body of the mail. Now all I need is a button in applemail to activate this script... (Anyone knows how to do this?)
Regds,
Martin Bergman
PS. Eg I could probably have used count in the first repeat as well...
Applescript:
-- 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
-- this was added to the script, makes a new mail with adresses in the to-field
set excludes to {}
set exclu to ""
tell application "Mail"
repeat with i from 1 to the number of items in accounts
set exclu to email addresses of item i of accounts as text
if excludes does not contain exclu then
set excludes to excludes & {exclu}
end if
end repeat
end tell
set sendlist to {}
repeat with i from 1 to count mailaddrs
if {mailaddrs's item i} is not in excludes then set sendlist's end to mailaddrs's item i
end repeat
if sendlist is {} then
set errmsg to "Only your own addresses in mail" & return & return & msgsubject & return
my dsperrmsg(errmsg, "--")
else
tell application "Mail"
set AppleScript's text item delimiters to ", "
set sendlisttext to sendlist as text
set AppleScript's text item delimiters to ""
set newMessage to make new outgoing message
tell newMessage
set visible to true
make new to recipient with properties {address:sendlisttext}
end tell
activate
end tell
end if
--end of my addings...
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
Last edited by mab75 (2008-06-17 09:21:41 pm)
Offline
I can't seem to get this script to work. I'm pretty ignorant, so could you walk me through the process step by step?
Currently, I highlight all of the emails from which I want to extract email addresses.
Then I click your link that says to open in script editor. I have tried two ways: Opening in script editor choosing no application, and doing so choosing Mail. In both cases the script window comes up with the script.
I double click run. It appears to run until stopping with an error:
Sorry, an error occured:
/usr/bin/python/: can't open file '/
Applications/AppleScript/Script Editor.app/Contents/Resources/findmails.py'(2)
Never mind
Any ideas what I need to do?
Model: iMac Intel
AppleScript: 2.1.2
Browser: Firefox 3.0.10
Operating System: Mac OS X (10.4)
Offline
kevinh1 wrote:
Any ideas what I need to do?
As already written above, you cannot just paste the script code into an open Script editor window and execute it, because the AppleScript internally relies on a Python script, which is located inside its Script bundle. Therefor please download the complete script here.
Once you downloaded the script, you only need to select one or more messages in Apple Mail and then run the script by double-clicking on its icon.
That's it ![]()
Offline
Thanks for the link and instructions. I followed them as you suggested and this is the error message:
Sorry, an error occured
Traceback (most recent call last): File "/Users/.../Extract eMail addresses.app/Contents/Resources/findmails.py",line 52, in ? main()
File "/Users/.../Extract eMail addresses.app/Contents/Resources/findmails.py",line 47, in main mailaddres = extrmailaddrs ([filepath])
File "Users/.../Extract eMail addresses/Extract eMail addresses.app/Contents/Resources/findmails.py", line 24, in extrmailaddrs found = set()
NameError: global name 'set' is not defined (1)
Your thoughts?
Offline
kevinh1 wrote:
Your thoughts?
You are not running Leopard, are you?
I guess you are running Mac OS X 10.4, where the script currently does not work (due to the Python version included).
Offline
That is a real bummer.
Thanks for clarifying.
Offline
Than you very very much!! This is what I'm looking for. I'm a newbie to Apple script, is there a way to copy the email in a text file one after the other? We get a lot of newsletter subscription emails and it would be "life changing" if we could automate this process by automatically screening email messages, copying the subscriber's emails and pasting it in a text file like this:
email1@email.com, email2@email.com, email3@email.com, etc...
Thanks!
Last edited by gugga7 (2009-09-06 08:18:05 am)
Offline
create a file named file.txt on your desktop.
Then open Apple Mail and set up a mail rule in and then in apply action, select "Run Applescript" and give the location to this applescript.
Applescript:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
repeat with eachMessage in theMessages
set thesender to sender of eachMessage
end repeat
end tell
set thesender to thesender & ","
set theshellscript to "echo " & quoted form of thesender & " >> ~/Desktop/file.txt"
do shell script theshellscript
end perform mail action with messages
end using terms from
Offline