Delete Email Addresses from a list

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!