Hello. I have a not very large data base of email addresses where I keep adding and deleting addresses. I manage it manually because its the cheapest I cant do. I would have some maybe 3000 email addresses or so.
Problem is, people keep shifting jobs and email accounts, so I get delivery failures.
Is there a way for me to create a list of delivery failure email addresses (I can do this manually) and use AppleScript to delete these email addresses from my master list? Doing this manually takes far too much time…
(*
This script offer two ways of use.
case 1 : you define a Mail rule moving the rejected messages in a dedicated mailbox (supposed here to be named "aaa")
case 2 : You select a group of mails then run the script.
In both cases you will retrieve the rejected addresses on the desktop in a text file named : "Undelivered_dervilednU.txt"
The behavior is ruled by the setting of the property named usedArule.
*)
(*
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
set startDate to current application's NSDate's |date|()
*)
property usedArule : true
# true --> execute case 1
# false --> execute case 2
# Use of this script object fasten the treatment of lists
script o
property theSources : {}
property theAddresses : {}
end script
set o's theAddresses to {}
tell application "Mail"
activate
if usedArule then
# case 1 : a rule moves the rejected messages in a dedicated box. Here it's assumed to be named "aaa"
tell mailbox "aaa"
set o's theSources to source of every message whose reply to starts with "Mail Delivery System"
end tell # mailbox
repeat with aSource in o's theSources
my extractAddress(aSource)
end repeat
else
# case 2 : You prefer to select a group of messages and apply the script to the selection
set theMessages to the selection
repeat with aMessage in theMessages
if reply to of aMessage starts with "Mail Delivery System" then
my extractAddress(source of aMessage)
end if
end repeat
end if
end tell # Mail
# I retrieved a good old efficient script handler so I use it.
set o's theAddresses to my heapsort(o's theAddresses, my cmpasc)
set theAddresses to my recolle(o's theAddresses, linefeed)
set thePath to (path to desktop as text) & "Undelivered_dervilednU.txt"
my writeto(thePath, theAddresses, «class utf8», false)
(*
set timeDiff to startDate's timeIntervalSinceNow()
tell application "Mail"
display dialog "That took " & (-timeDiff as real) & " seconds."
--> "That took 0,116165041924 seconds."
end tell
*)
#=====
on extractAddress(aSource)
set aSource to aSource as text
if aSource contains "Final-Recipient: " then
set maybe to item 2 of my decoupe(aSource, "Final-Recipient: ")
set maybe to item 2 of my decoupe(paragraph 1 of maybe, ";")
repeat while maybe starts with space
set maybe to text 2 thru -1 of maybe
end repeat
set end of o's theAddresses to maybe
end if
end extractAddress
#=====
on decoupe(t, d)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set l to text items of t
set AppleScript's text item delimiters to oTIDs
return l
end decoupe
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as «class furl»
set openFile to open for access targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access targetFile
end try
return false
end try
end writeto
#=====
(* tri par tas (arbre binaire complet ordonné)
Ce tri figure parmi les plus efficaces et n'exige aucune mémoire supplémentaire.
Implémentation: L. Sebilleau
*)
on heapsort(laListe, fcmp)
set n to the count of laListe
if n ≤ 1 then return laListe
script lstock -- l'intérêt de ce script est d'accélérer le traitement des listes
property liste : laListe
property Compare : fcmp -- pointeur de fonction de comparaison
end script
-- création du tas par insertion fictive des éléments présents dans la liste: ils sont
--"phagocytés" un à un par la croissance du tas dont la dimension est i.
repeat with i from 2 to n
set j to i div 2 -- le premier parent du nouvel inséré
set k to i
set elem to item k of lstock's liste
repeat while k > 1
if lstock's Compare(item j of lstock's liste, elem) then
set item k of lstock's liste to item j of lstock's liste
set k to j
set j to j div 2
else
exit repeat
end if
end repeat
set item k of lstock's liste to elem -- installé dans sa position finale
end repeat
(* destruction du tas: l'extraction répétée donne la liste triée à l'envers:
comme le tas diminue par la fin de la liste, on peut réinsérer les éléments extraits à rebours
dans les emplacements libérés. Ce retournement explique pourquoi un utilise un tas max pour
trier en ordre croissant et vice-versa. *)
repeat with i from n to 2 by -1
set elem to item i of lstock's liste -- diminution du tas
set item i of lstock's liste to item 1 of lstock's liste -- extraction de la racine qui est
-- recopiée dans la position libérée
-- réorganisation du tas en réinsérant l'élément de queue à la racine
set j to 1
set k to j * 2
repeat while k < i
if (k + 1) < i then
if lstock's Compare(item k of lstock's liste, item (k + 1) of lstock's liste) then
set k to k + 1
end if
end if
if lstock's Compare(elem, item k of lstock's liste) then
set item j of lstock's liste to item k of lstock's liste
set j to k
set k to k * 2
else
exit repeat
end if
end repeat
set item j of lstock's liste to elem
end repeat
return lstock's liste
end heapsort
----------- les fonctions de comparaison ------------
on cmpasc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
return n1 < n2
end cmpasc
on cmpdesc(n1, n2) -- tri descendant des nombres et des chaînes
return n1 > n2
end cmpdesc
on recmp(n1, n2) -- tri par noms
return (nom of n1 < nom of n2)
end recmp
on agecmp(n1, n2) -- tri par âges
return (Age of n1 < Age of n2)
end agecmp
---------------------------------------------
I apologizes but I don’t wish to translate the comments in the sort handler.
Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) samedi 7 janvier 2017 13:38:39
Hey thanks! I need to some time understand how to get this working, but seems easy! Thanks a lot again!