attaché - Easy attachment list creation for Apple Mail

Even if there are some companies in the electroplating industry using Macs, most of our own suppliers and customers still happily practice self-mortification by working with PCs running Windows.

And I discovered that Windows users just love attachment lists, a short summary about which files are attached to the eMail including file names, types and sizes. But you cannot easily create them in Apple Mail. So our staff typed them manually at the bottom of the eMail message to satisfy our PC loving business partners. Until I wrote attaché :slight_smile:

If you also need/want to automate this task, then I invite you to take a look at the script.

Overview
attaché is an AppleScript droplet that simplifies the creation of an attachment list for an eMail in Apple Mail.

You can download attaché for free right here:

[center]attaché 1.2 - Easy attachment list creation for Apple Mail (v1.1, ca. 255 KB)
(This version is for Apple Mail only!)[/center]

System Requirements
Mac OS X 10.5.1 or later
Apple Mail 3.1

  • attaché may run on other systems as well, but I did/could not test it

Installation
After downloading and extracting the ZIP archive, just drag the script icon into your Applications/Scripts folder (or wherever you like to put it).

Update
To update your existing attaché installation, just replace the old script with the new one.

IMPORTANT: attaché 1.1 does not anymore rely on Database Events, but instead saves its language entries in a plain text file (UTF-8) internally managed by a simple Python script.

Therefor, when upgrading from an older version, you might have to enter your custom language entries once again, as attaché 1.1 does not (yet) import them automatically.

You can either enter your custom language entries in the options panel (start attaché with a double-click) or by manually editing the database file located at:

/Users/yourname/Library/Application Support/attaché/atmterms.txt

The syntax for the language entries is very simple:

Code:

[Language name]
sglheader = [$catm$ attachment]
plrheader = [$catm$ attachments]
atminfo = «$atmname$» (Size: ca. $atmsize$, Kind: $atmkind$)

A lot of users requested this «direct data manipulating»-feature, so I hope they are now satisfied.

Usage
¢ To create an eMail in Apple Mail with an attachment list, just drop a bunch of files onto attaché’s icon. It will then ask you to choose a language and create the eMail for you.

¢ You can also use attaché as a PDF Service by putting it into the ~/Library/PDF Services/ folder! This is a very convenient way to create and send a PDF document via eMail in one easy step.

¢ To view the preferences and to change the language settings, just start attaché by double-clicking its icon. It will then present its preferences menu:

Version History
¢ Version 1.2 (30.09.2009)

  • adding attachments is now compatible with Mac OS X 10.6.1
    ¢ Version 1.1b (24.02.2008)
  • this version does only support Apple Mail, not Microsoft Entourage for now
  • the script does not anymore rely on AppleScript’s Database Events for managing the different language entries, but instead uses a plain text file (UTF-8) for data storage managed by a simple Python script
  • you can now choose a default signature and also set its position (above or below the attachment list)
  • you can now choose a default subject line
  • you can now choose a default sender account
  • you can now choose a default content to be inserted
  • new preferences lib for managing user preferences
  • enhanced eMail lib for controlling Apple Mail
    ¢ Version 1.0.3 (20.10.2007)
  • Apple Mail is now activated when creating the eMail
    ¢ Version 1.0.2 (09.07.2007)
  • new default text modules in French language
    (these text modules were kindly provided by Guillaume CERQUANT)
    ¢ Version 1.0.1 (24.06.2007)
  • new default text modules in Italian language
    (these text modules were kindly provided by Daniele Semeraro,
    visit his blog at «http://dadiontheweb.blogspot.com»)
  • a default language can now be set
  • new menu items for eMail feedback and visiting the JoS website
    ¢ Version 1.0 (June 2007)
  • Public release

Planned Features/Ideas

  • zip dropped folders & items
  • default recipients

Microsoft Entourage
Please note, that the new version of attaché does not support Microsoft Entourage for now, but was only written for Apple Mail alone. Unfortunately supporting another major eMail client is a lot of work and would also mean, that attaché would have to grow from a small AppleScript to a bigger plugin-based AppleScript Studio project. And currently I just don’t have enough time for this…

But all components of the attaché script can be viewed in the Script Editor or in your favourite text editor, so if you really need Microsoft Entourage support and know a little bit of AppleScript, it will be no problem for you to modify attaché’s source accordingly. The code is also pretty well documented.

Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because subidoo internally relies on a Python script, which is located inside its Application bundle. Therefor please download the complete script here.


-- created: June 2007
-- modified:
-- ¢ 09.07.2007
-- ¢ 20.10.2007
-- ¢ 24.02.2008
-- version: 1.1
-- tested with:
-- ¢ Appe Mail Version 3.1 (914/915)
-- ¢ Mac OS X Version 10.5.1
-- ¢ Intel & PowerPC Macs
-- history:
-- ¢ v1.1:
--   + this version does only support Apple Mail,
--      not Microsoft Entourage for now
--   + the script does not anymore rely on Database Events for
--      saving and managing the different language records, but
--      instead uses a plain text file (UTF-8) managed by a simple Python
--      script
--      >> this text file can also be manually edited, as
--      requested by many users
--      ('/Users/yourname/Library/Application SUpport/attaché/atmterms.txt')
--   + you can now choose a default signature and also
--      set its position (above or below the attachment list)
--   + you can now choose a default subject line
--   + you can now choose a default sender account
--   + you can now choose a default content to be inserted
--   + new preferences lib for managing user preferences
--   + enhanced eMail lib for controlling Apple Mail
-- ¢ v1.0.3:
--   + Apple Mail is now activated when creating the eMail
--      (many users were annoyed that Apple Mail still stayed in the background)
-- ¢ v1.0.2:
--   + added default text modules in French language
--      (text modules were kindly provided by Guillaume CERQUANT)
-- ¢ v1.0.1:
--   + added default text modules in Italian language
--      (text modules were kindly provided by Daniele Semeraro,
--      visit his blog at «http://dadiontheweb.blogspot.com»)
--   + a default language can now be set, a feature requested
--     by many users
--   + eMail feedback and visit JoS website menu items
-- ¢ v1.0:
--   + first public release
-- possible features for the future:
-- ¢ zip folders/items
-- ¢ email options: cc/bcc recipients
--    >> this option is planned for the next version = > v1.1
-- ¢ cool icon :D

-- basic script prefs
property mytitle : "attaché"
property mydomain : "com.jos." & mytitle -- «joy of scripting»
property myversion : "1.1"

-- private libraries
property prefslib : missing value
property txtlib : missing value
property emllib : missing value
property itmlib : missing value
property utllib : missing value

-- routine invoked when items are
-- dropped onto the script icon
on open dropitems
	set dropitems to dropitems as list
	my main("on open", dropitems)
end open

-- routine invoked when the script
-- is started by double-clicking its icon
on run
	my main("on run", missing value)
end run

-- main routine controlling the script
on main(mode, args)
	try
		-- establishing a basis for successful script execution
		my initialize()
		-- user started the app by double-clicking its icon and
		-- wants to change the preferences: let's display our wonderful gui!
		if mode is "on run" then
			my guiloop()
			-- user dropped items onto the script icon and
			-- wants to create an eMail with attachments and attachment list
		else if mode is "on open" then
			set dropitems to args
			set dropitems to dropitems as list
			-- separating files and folders
			set {dropfiles, dropfolders} to itmlib's getfilesnfolders(dropitems)
			set countfiles to length of dropfiles
			set countfolders to length of dropfolders
			-- future: zip folders/items?
			-- user dropped folders only? no, no, no, no....
			if countfiles = 0 and countfolders > 0 then
				set errmsg to "You dropped only folders onto the script icon. Please select files only as attachments."
				set errnum to "--"
				my dsperrmsg(errmsg, errnum)
				return
			end if
			-- default language chosen?
			set lang to my getdeflang()
			-- no default language: let's ask the user to choose one
			if lang is missing value then
				-- prompting user for language
				set lang to my chooselang()
				-- damn, user hit Cancel button...
				if lang is missing value then
					return
				end if
			end if
			-- creating attachment info/list
			set atminfo to my createatminfo(lang, dropfiles)
			-- finally creating the eMail with Apple Mail
			my createemailmsg(atminfo, dropfiles)
			-- this is the end...
		end if
		-- catching unexpected errors
	on error errmsg number errnum
		-- ignoring 'User canceled'-error = errnum -128
		if errnum ≠ -128 then
			my dsperrmsg(errmsg, errnum)
		end if
	end try
end main

-- establishes a basis for successful script execution
on initialize()
	-- loading private libraries
	my loadlibs()
	-- creating scripts' application support folder if necessary
	-- if the application support folder does not already exists, the
	-- script was most probably started for the first time, so we are
	-- showing a welcome message «shortly» explaining how to use the script
	set myappsuppfolderpath to my getscriptpath("myappsuppfolder", "posix")
	if not my itmlib's itempathexists(myappsuppfolderpath, "posix") then
		my itmlib's createfolder(myappsuppfolderpath, "posix")
		my dspwelcomemsg()
	end if
	-- copying the default database file to the application support folder if necessary
	set dbpath to (my getscriptpath("myappsuppfolder", "mac") & "atmterms.txt")
	if not my itmlib's itempathexists(dbpath, "mac") then
		my copydefaultdb()
	end if
	-- now everything «should» be ready for a clean run...
end initialize

-- loads the private libraries
on loadlibs()
	-- very simple design...no error catching...go with the flow.
	set scriptsfolderpath to my getscriptpath("scriptsfolder", "mac")
	-- new lib introduced in version 1.1 for managing the preferences
	set prefslib to load script ((scriptsfolderpath & "prefslib.scpt") as alias)
	set txtlib to load script ((scriptsfolderpath & "txtlib.scpt") as alias)
	set emllib to load script ((scriptsfolderpath & "emllib.scpt") as alias)
	set itmlib to load script ((scriptsfolderpath & "itmlib.scpt") as alias)
	set utllib to load script ((scriptsfolderpath & "utllib.scpt") as alias)
end loadlibs

-- controls the gui for the preferences menu
on guiloop()
	try
		-- displaying main menu and getting the chosen menu item
		set menuitem to my dspmainmenu()
		-- user hit Cancel button...
		if menuitem is missing value then
			return
		else
			if menuitem is "Add language" then
				my miaddlang()
			else if menuitem is "Edit language" then
				my mieditlang()
			else if menuitem is "Delete language" then
				my midellang()
			else if menuitem is "Set default language" then
				my misetdeflang()
			else if menuitem is "Reset default language" then
				my miresetdeflang()
			else if menuitem is "Set default account" then
				my misetdefacc()
			else if menuitem is "Reset default account" then
				my miresetdefacc()
			else if menuitem is "Set default signature" then
				my misetdefsig()
			else if menuitem is "Reset default signature" then
				my miresetdefsig()
			else if menuitem is "Set default subject" then
				my misetdefsubj()
			else if menuitem is "Reset default subject" then
				my miresetdefsubj()
			else if menuitem is "Set default contents" then
				my misetdefcont()
			else if menuitem is "Reset default contents" then
				my miresetdefcont
			end if
		end if
		my guiloop()
	on error errmsg number errnum
		-- display any error but a 'User canceled'- or 'AppleEvent Timeout'-error...
		if errnum is not in {-128, -1712} then
			my dsperrmsg(errmsg, errnum)
		end if
		try
			my guiloop()
		end try
	end try
end guiloop

-- prompts the user to choose a language for the attachment info/list
on chooselang()
	-- retrieving the available languages from the database
	set langs to my aspybridge("getlangs", "lines", missing value)
	-- oops, the user deleted all languages from the database...
	if langs is {} then
		set errmsg to "Sorry, there are currently no languages available in your database."
		my dsperrmsg(errmsg, "--")
		return missing value
	else
		set choice to choose from list langs with prompt "Please choose a language:" with title mytitle OK button name "Select" cancel button name "Cancel" without multiple selections allowed and empty selection allowed
		if choice is not false then
			set lang to item 1 of choice
			return lang
		else
			return missing value
		end if
	end if
end chooselang

-- asks the user to choose a signature position:
-- above or below the attachment list
on choosesigpos()
	set menuitems to {"Above the attachment list", "Below the attachment list"}
	tell me
		activate
		choose from list menuitems with title mytitle cancel button name "Cancel" OK button name "Select" with prompt "Where should the signature appear:" without multiple selections allowed and empty selection allowed
		set choice to result
	end tell
	if choice is not false then
		set menuitem to item 1 of choice
		if menuitem is "Above the attachment list" then
			return "above"
		else if menuitem is "Below the attachment list" then
			return "below"
		end if
	else
		return missing value
	end if
end choosesigpos

-- copies the default database file to the application support folder
on copydefaultdb()
	-- no error handling here...
	set sourcepath to (my getscriptpath("resfolder", "posix") & "atmterms.txt")
	set destpath to (my getscriptpath("myappsuppfolder", "posix") & "atmterms.txt")
	set cmd to ("cp " & quoted form of sourcepath & " " & quoted form of destpath)
	set cmd to cmd as «class utf8»
	do shell script cmd
end copydefaultdb

-- returns several environment paths of the script
-- mode ("posix" or "mac") must be given as well!
on getscriptpath(pathkey, mode)
	if pathkey is "myappsuppfolder" then
		set scriptpath to ((path to application support folder from user domain) as Unicode text) & mytitle & ":"
	else if pathkey is "scriptsfolder" then
		set scriptpath to ((path to me) as Unicode text) & "Contents:Resources:Scripts:"
	else if pathkey is "resfolder" then
		set scriptpath to ((path to me) as Unicode text) & "Contents:Resources:"
	end if
	if mode is "posix" then
		return (POSIX path of scriptpath)
	else if mode is "mac" then
		return scriptpath
	end if
end getscriptpath

-- returns the chosen default language or missing value
on getdeflang()
	my prefslib's PrefsFile's initialize(mydomain)
	-- if a prefs file exists and also contains an 'deflang'-key, we
	-- retrieve this information from the prefs file
	if prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("deflang") then
		set deflang to my prefslib's PrefsFile's getpref("deflang")
		-- now let's see if the default language also exists in the database file
		set langexists to my aspybridge("haslang", "bool", {deflang})
		-- oops, it does not...
		if not langexists then
			set msg to "Your chosen default language '" & deflang & "' does not exist in the database file anymore." & return & return & "We will now prompt you to manually choose an available language."
			tell me
				activate
				display dialog msg buttons {"OK"} default button 1 with title mytitle with icon caution
			end tell
			return missing value
			-- yes, its' there! the default language really exists!
		else
			return deflang
		end if
		-- no default language chosen by the user so far
	else
		return missing value
	end if
end getdeflang

-- creates the attachment info/list for the given files in the given language
on createatminfo(lang, dropfiles)
	-- retrieving text modules from the database
	set {atmnotesg, atmnotepl, atmentry} to my aspybridge("getentry", "lines", {lang})
	-- one file/many files? singular/plural?
	set countfiles to length of dropfiles
	if countfiles = 1 then
		set atminfo to my txtlib's searchnreplace("$catm$", countfiles as Unicode text, atmnotesg) & return
	else
		set atminfo to my txtlib's searchnreplace("$catm$", countfiles as Unicode text, atmnotepl) & return
	end if
	repeat with dropfile in dropfiles
		set tmpatmentry to atmentry
		-- getting file info
		set fileinfo to info for dropfile
		set atmname to (name of fileinfo) as Unicode text
		set atmkind to (kind of fileinfo) as Unicode text
		set atmsize to (my utllib's getstringsize(size of fileinfo) as Unicode text)
		-- filling placeholders in text modules with actual data
		repeat with i from 1 to length of {atmname, atmsize, atmkind}
			set searchstr to item i of {"$atmname$", "$atmsize$", "$atmkind$"}
			set replacestr to item i of {atmname, atmsize, atmkind}
			set tmpatmentry to my txtlib's searchnreplace(searchstr, replacestr, tmpatmentry)
		end repeat
		set atminfo to atminfo & tmpatmentry & return
	end repeat
	return atminfo
end createatminfo

-- creates the eMail Message in Apple Mail following the settings found
-- in cathat's preferences file
on createemailmsg(atminfo, dropfiles)
	-- Note: We can not just retrieve the default values from the
	-- preferences file, but must also check if they are still valid.
	-- If we, e.g., use a default signature or sender account,
	-- which does not anymore exist in Apple Mail (deleted/modified),
	-- we will get in trouble.
	
	-- checking for a chosen default subject line
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsubj") then
		set defsubj to my prefslib's PrefsFile's getpref("defsubj")
	else
		set defsubj to missing value
	end if
	-- checking for a chosen default sender account
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defacc") then
		set defacc to my prefslib's PrefsFile's getpref("defacc")
		if not emllib's AppleMail's hassenderaccount(defacc) then
			set msg to "Your chosen default sender account '" & defacc & "' does not exist anymore." & return & return & "Please choose if you want to quit or if " & mytitle & " should continue without using a default sender account."
			tell me
				activate
				display dialog msg buttons {"Quit", "Continue"} default button 2 with icon caution with title mytitle
				set dlgresult to result
			end tell
			if button returned of dlgresult is "Quit" then
				return
			else
				set defacc to missing value
			end if
		end if
	else
		set defacc to missing value
	end if
	-- checking for a chosen default signature
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsig") then
		set defsig to my prefslib's PrefsFile's getpref("defsig")
		if emllib's AppleMail's hassignaturename(defsig) then
			set defsig to emllib's AppleMail's getsigncontent(defsig)
		else
			set msg to "Your chosen default signature '" & defsig & "' does not exist anymore." & return & return & "Please choose if you want to quit or if " & mytitle & " should continue without using a signature."
			tell me
				activate
				display dialog msg buttons {"Quit", "Continue"} default button 2 with icon caution with title mytitle
				set dlgresult to result
			end tell
			if button returned of dlgresult is "Quit" then
				return
			else
				set defsig to missing value
			end if
		end if
	else
		set defsig to missing value
	end if
	-- checking for the chosen default signature position
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsigpos") then
		set defsigpos to my prefslib's PrefsFile's getpref("defsigpos")
	else
		set defsigpos to "below"
	end if
	-- checking for a chosen default eMail body/content
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defcont") then
		set defcont to my prefslib's PrefsFile's getpref("defcont")
	else
		set defcont to missing value
	end if
	-- visibility : true = Apple Mail displays the newly created eMail message
	-- visibilty : false = Apple Mail displays the newly created eMail message
	set visibility to true
	my emllib's AppleMailMessage's createnew(visibility)
	-- setting the default sender account if necessary
	if defacc is not missing value then
		my emllib's AppleMailMessage's setsenderaccount(defacc)
	end if
	-- setting the default subject line if necessary
	if defsubj is not missing value then
		my emllib's AppleMailMessage's addsubject(defsubj)
	end if
	-- composing and inserting the complete eMail body
	-- user chose a default eMail body
	if defcont is not missing value then
		-- user also chose a default signature
		if defsig is not missing value then
			-- default eMail body + signature below attachment list
			if defsigpos is "below" then
				set emlbody to defcont & return & atminfo & return & defsig & return
				-- default eMail body + signature above attachment list
			else if defsigpos is "above" then
				set emlbody to defcont & return & defsig & return & atminfo & return
			end if
			-- user chose no default signature
		else
			-- default eMail body + attachment list
			set emlbody to defcont & return & atminfo & return
		end if
		-- user chose no default eMail body
	else
		-- user chose a default signature
		if defsig is not missing value then
			-- default signature below attachment list 
			if defsigpos is "below" then
				set emlbody to return & atminfo & return & defsig & return
				-- default signature above attachment list
			else if defsigpos is "above" then
				set emlbody to return & defsig & return & atminfo & return
			end if
			-- no default signature chosen
		else
			-- attachment list only...user seems to be an ascetic
			set emlbody to return & atminfo & return
		end if
	end if
	my emllib's AppleMailMessage's addcontent(emlbody)
	-- adding the attachments
	my emllib's AppleMailMessage's addattachments(dropfiles)
	-- bringing Apple Mail tothe foreground
	tell application "Mail"
		activate
	end tell
end createemailmsg

-- controls the menu item for adding a new language
on miaddlang()
	-- flag indicating a successful dialog with the user
	set dlgsuccess to false
	repeat
		set newlang to my promptforlang()
		-- user hit Cancel button
		if newlang is missing value then
			exit repeat
		else
			-- checking whether the new language already exists in the database
			set newlangexists to my aspybridge("haslang", "bool", {newlang})
			-- oops, chosen language already exists
			if newlangexists is true then
				tell me
					activate
					display dialog "Sorry, this language name ('" & newlang & "') already exists. Please choose another one." buttons {"OK"} default button 1 with icon caution with title mytitle
				end tell
				-- back to the beginning...				
			else if newlangexists is false then
				-- no more calls, we have a winner!
				set dlgsuccess to true
				exit repeat
			end if
		end if
	end repeat
	-- successful dialog!
	if dlgsuccess is true then
		set recdata to my promptforrecdata(missing value)
		-- user hit Cancel button...
		if recdata is missing value then
			return
		end if
		-- saving new language and its data set to the database
		set recdata to {newlang} & recdata
		my aspybridge("addentry", "text", recdata)
	end if
end miaddlang

-- controls the menu item for editing an existing language
on mieditlang()
	set lang to my chooselang()
	-- user hit Cancel button
	if lang is missing value then
		-- pass (oops, a Pythonic expression :D must be the force of habit)
	else
		set recdata to my promptforrecdata(lang)
		-- user hit Cancel button...
		if recdata is missing value then
			return
		end if
		-- saving new language and its data set to the database
		set recdata to {lang} & recdata
		my aspybridge("editentry", "text", recdata)
	end if
end mieditlang

-- controls the menu item for deleting a language
on midellang()
	set lang to my chooselang()
	-- user hit Cancel button
	if lang is missing value then
		return
	else
		-- removing chosen language (record) from the database
		my aspybridge("rementry", "text", {lang})
	end if
end midellang

-- sets a default language, which is used for the attachment list
on misetdeflang()
	set lang to my chooselang()
	-- user hit Cancel button
	if lang is missing value then
		return
	else
		-- saving default language in the preferences file
		my prefslib's PrefsFile's initialize(mydomain)
		my prefslib's PrefsFile's setpref("deflang", lang, "string")
	end if
end misetdeflang

-- resets the chosen default language
on miresetdeflang()
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("deflang") then
		my prefslib's PrefsFile's delpref("deflang")
	end if
end miresetdeflang

-- sets the default mail acoount to be used when creating 
-- a new eMail message in Apple Mail
on misetdefacc()
	-- If Apple Mail is not currently running,
	-- we should ask the user if he wants to open it
	if not utllib's appisrunning("Mail") then
		tell me
			activate
			set msg to "Apple Mail is currently not running on your Mac." & return & return & "Do you want to quit for now or open Apple Mail to continue?"
			display dialog msg buttons {"Quit", "Open Apple Mail"} default button 1 with title mytitle with icon (POSIX file "/Applications/Mail.app/Contents/Resources/app.icns")
			set dlgresult to result
		end tell
		if button returned of dlgresult is "Quit" then
			return
		end if
	end if
	set senderaccounts to emllib's AppleMail's getsenderaccounts()
	if senderaccounts is {} then
		set errmsg to "Sorry, there are currently no sender accounts available in your Apple Mail."
		my dsperrmsg(errmsg, "--")
		return
	else
		set choice to choose from list senderaccounts with prompt "Please choose a sender account:" with title mytitle OK button name "Select" cancel button name "Cancel" without multiple selections allowed and empty selection allowed
		if choice is not false then
			set senderaccount to item 1 of choice
			my prefslib's PrefsFile's initialize(mydomain)
			my prefslib's PrefsFile's setpref("defacc", senderaccount, "string")
		else
			return
		end if
	end if
end misetdefacc

-- resets the chosen default language
on miresetdefacc()
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defacc") then
		my prefslib's PrefsFile's delpref("defacc")
	end if
end miresetdefacc

-- sets the default signature to be used when creating 
-- a new eMail message in Apple Mail
on misetdefsig()
	-- If Apple Mail is not currently running,
	-- we should ask the user if he wants to open it
	if not utllib's appisrunning("Mail") then
		tell me
			activate
			set msg to "Apple Mail is currently not running on your Mac." & return & return & "Do you want to quit for now or open Apple Mail to continue?"
			display dialog msg buttons {"Quit", "Open Apple Mail"} default button 1 with title mytitle with icon (POSIX file "/Applications/Mail.app/Contents/Resources/app.icns")
			set dlgresult to result
		end tell
		if button returned of dlgresult is "Quit" then
			return
		end if
	end if
	set signames to emllib's AppleMail's getsignaturenames()
	if signames is {} then
		set errmsg to "Sorry, there are currently no signatures available in your Apple Mail."
		my dsperrmsg(errmsg, "--")
		return
	else
		set choice to choose from list signames with prompt "Please choose a signature:" with title mytitle OK button name "Select" cancel button name "Cancel" without multiple selections allowed and empty selection allowed
		if choice is not false then
			set signame to item 1 of choice
			set sigpos to my choosesigpos()
			-- User hit 'Cancel'-button :(
			if sigpos is missing value then
				return
			else
				my prefslib's PrefsFile's initialize(mydomain)
				my prefslib's PrefsFile's setpref("defsig", signame, "string")
				my prefslib's PrefsFile's setpref("defsigpos", sigpos, "string")
			end if
		else
			return
		end if
	end if
end misetdefsig

-- resets the chosen default signature name
on miresetdefsig()
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsig") then
		my prefslib's PrefsFile's delpref("defsig")
	end if
end miresetdefsig

-- sets the  default subject line to be used when creating
-- a new eMail message in Apple Mail
on misetdefsubj()
	-- if the user already once entered a default subject line, we are using this
	-- as the default answer in the following dialog: pure convenience...
	my prefslib's PrefsFile's initialize(mydomain)
	if prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsubj") then
		set defansw to my prefslib's PrefsFile's getpref("defsubj")
	else
		set defansw to ""
	end if
	-- asking the user to provide a subject line
	tell me
		activate
		display dialog "Please enter a default subject line:" default answer defansw buttons {"Cancel", "Enter"} default button 1 with title mytitle
		set dlgresult to result
	end tell
	if button returned of dlgresult is "Cancel" then
		return
	else if button returned of dlgresult is "Enter" then
		set subj to text returned of dlgresult
		if subj is "" then
			my misetdefsubj()
			return
		else
			my prefslib's PrefsFile's initialize(mydomain)
			my prefslib's PrefsFile's setpref("defsubj", subj, "string")
		end if
	end if
end misetdefsubj

-- resets the chosen default subject line
on miresetdefsubj()
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defsubj") then
		my prefslib's PrefsFile's delpref("defsubj")
	end if
end miresetdefsubj

-- sets the default contents/body to be used when
-- creating a new eMail message in Apple Mail
on misetdefcont()
	set menuitems to {"Copy text from clipboard", "Copy text from frontmost TextEdit document"}
	tell me
		activate
		choose from list menuitems with prompt "Please choose an import method:" with title mytitle cancel button name "Cancel" OK button name "Select" without multiple selections allowed and empty selection allowed
		set choice to result
	end tell
	if choice is not false then
		set menuitem to item 1 of choice
		if menuitem is "Copy text from clipboard" then
			set cont to my imptxtfromcp()
		else if menuitem is "Copy text from frontmost TextEdit document" then
			set cont to my imptxtfromte()
		end if
		if cont is not missing value then
			my prefslib's PrefsFile's initialize(mydomain)
			my prefslib's PrefsFile's setpref("defcont", cont, "string")
		else
			return
		end if
	else
		return
	end if
end misetdefcont

-- resets the chosen default contents/body
on miresetdefcont()
	my prefslib's PrefsFile's initialize(mydomain)
	if my prefslib's PrefsFile's filepathexists() and my prefslib's PrefsFile's haspref("defcont") then
		my prefslib's PrefsFile's delpref("defcont")
	end if
end miresetdefcont

-- imports text from the frontmost document in TextEdit
-- returns the text if successful, otherwise returns missing value
-- reports all errors to dsperrmsg()
on imptxtfromte()
	if not utllib's appisrunning("TextEdit") then
		set errmsg to "Sorry, TextEdit is currently not running on your Mac." & return & return & "Please open the corresponding document in TextEdit first before repeating this procedure."
		my dsperrmsg(errmsg, "--")
		return missing value
	else
		tell application "TextEdit"
			set alldocs to every document
		end tell
		if alldocs is {} then
			set errmsg to "Sorry, there are currently no open documents in TextEdit." & return & return & "Please open the corresponding document in TextEdit first before repeating this procedure."
			my dsperrmsg(errmsg, "--")
			return missing value
		else
			tell application "TextEdit"
				set cont to (text of document 1) as Unicode text
			end tell
			if cont is "" then
				set errmsg to "Sorry, the frontmost document in TextEdit contained no text."
				my dsperrmsg(errmsg, "--")
				return missing value
			else
				return cont
			end if
		end if
	end if
end imptxtfromte

-- imports text from the clipboard
-- returns the text if successful, otherwise returns missing value
-- reports all errors to dsperrmsg()
on imptxtfromcp()
	set cont to the clipboard
	if class of cont is not in {text} then
		set errmsg to "Sorry, the clipboard stores data, but it is not text." & return & return & "Please copy the desired text to the clipboard before repeating this procedure."
		my dsperrmsg(errmsg, "--")
		return missing value
	else
		set cont to cont as Unicode text
		if cont is "" then
			set errmsg to "Sorry, we could not retrieve any text from the clipboard." & return & return & "Please copy the desired text to the clipboard before repeating this procedure."
			my dsperrmsg(errmsg, "--")
			return missing value
		else
			return cont
		end if
	end if
end imptxtfromcp

-- asks the user to provide a language name
on promptforlang()
	tell me
		activate
		display dialog "Please enter the name of the new language:" default answer "" buttons {"Cancel", "Enter"} default button 2 with title mytitle
		set dlgresult to result
	end tell
	if button returned of dlgresult is "Cancel" then
		return missing value
	else if button returned of dlgresult is "Enter" then
		set lang to text returned of dlgresult
		-- user did not enter any text :-(
		if lang is "" then
			my promptforlang()
			return
		else
			return lang
		end if
	end if
end promptforlang

-- prompts the user to enter the data set/text modules for the language
on promptforrecdata(lang)
	-- if a language/record name is given, we are showing default values in the
	-- dialogues, which must be retrieved from the database first
	-- >>> see function mieditlang()
	if lang is not missing value then
		set {atmnotesg, atmnotepl, atmentry} to my aspybridge("getentry", "lines", {lang})
		set defanswers to {atmnotesg, atmnotepl, atmentry}
	else
		set defanswers to {"", "", ""}
	end if
	set prompts to {"Please enter your text for the attachment header for a single attachment:", "Please enter your text for the attachment header for multiple attachments:", "Please enter your text for an attachment entry:"}
	set usranswers to {}
	set counter to 0
	set dlgsuccess to true
	set dsphelp to false
	repeat
		if dsphelp is false then
			set counter to counter + 1
		else
			set dsphelp to false
		end if
		if counter > (length of defanswers) then
			exit repeat
		end if
		set prompt to item counter of prompts
		set defanswer to item counter of defanswers
		tell me
			activate
			display dialog prompt default answer defanswer with title mytitle buttons {"Placeholders", "Cancel", "Enter"} default button 3
			set dlgresult to result
		end tell
		if button returned of dlgresult is "Cancel" then
			set dlgsuccess to false
			exit repeat
		else if button returned of dlgresult is "Enter" then
			set usranswers to usranswers & (text returned of dlgresult)
		else if button returned of dlgresult is "Placeholders" then
			set placeholderhelp to "You can use these placeholders in your text:" & return & return & "$catm$ = total count of attachments" & return & return & "$atmname$ = name of attachment, e.g. 'invoice.pdf'" & return & return & "$atmsize$ = size of attachment, e.g. '1.3 MB'" & return & return & "$atmkind$ = kind of attachment, e.g. 'Microsoft Word Document'"
			tell me
				activate
				display dialog placeholderhelp with title mytitle buttons {"Clipboard", "Thanks!"} default button 2
				set dlgresult to result
			end tell
			if button returned of dlgresult is "Clipboard" then
				set the clipboard to placeholderhelp
			end if
			set dsphelp to true
		end if
	end repeat
	if dlgsuccess is true then
		return usranswers
	else
		return missing value
	end if
end promptforrecdata

-- communicates with the Python script handling the database file for us
on aspybridge(action, retval, args)
	set pyscriptpath to (my getscriptpath("scriptsfolder", "posix") & "aspybridge.py")
	set dbfilepath to (my getscriptpath("myappsuppfolder", "posix") & "atmterms.txt")
	
	if action is "getlangs" then
		set cmd to "python " & quoted form of pyscriptpath & " " & action & " " & quoted form of dbfilepath
	else if action is in {"haslang", "getentry", "rementry"} then
		set cmd to "python " & quoted form of pyscriptpath & " " & action & " " & quoted form of dbfilepath & " " & quoted form of (item 1 of args)
	else if action is in {"addentry", "editentry"} then
		set cmd to "python " & quoted form of pyscriptpath & " " & action & " " & quoted form of dbfilepath & " " & quoted form of (item 1 of args) & " " & quoted form of (item 2 of args) & " " & quoted form of (item 3 of args) & " " & quoted form of (item 4 of args)
	end if
	set cmd to cmd as «class utf8»
	try
		set shellresult to do shell script cmd
	on error errmsg number errnum
		if errmsg contains "FileError" then
			set errmsg to "The database file containing the language entries is missing:" & return & return & "'" & dbfilepath & "'" & return & return & "To install the default database file, please first quit and then restart " & mytitle & "."
			error errmsg number errnum
		else
			error errmsg number errnum
		end if
	end try
	
	if retval is "text" then
		return shellresult
	else if retval is "lines" then
		return paragraphs of shellresult
	else if retval is "bool" then
		if shellresult is in {"1", "True"} then
			return true
		else if shellresult is in {"0", "False"} then
			return false
		end if
	end if
end aspybridge

-- displays a welcome message shortly explaining how to use the app
on dspwelcomemsg()
	tell application "System Events"
		set usrname to (full name of current user) as Unicode text
	end tell
	set welcomemsg to "Hello " & usrname & ", and welcome to " & mytitle & "." & return & return & "It seems, that you are using this application for the first time." & return & return & "If you want to change the preferences, just start the application by double-clicking its icon." & return & return & "If you want to create an eMail with an attachment list in Apple Mail, just drop files onto " & mytitle & "'s icon." & return & return & "Have fun!"
	tell me
		activate
		display dialog welcomemsg buttons {"OK"} default button 1 with title mytitle
	end tell
end dspwelcomemsg

-- displays the main menu and returns chosen menu item
on dspmainmenu()
	-- DEV: recipients
	set spacer to "........."
	set menuitems to {"Add language", "Edit language", "Delete language", spacer, "Set default language", "Reset default language", spacer, "Set default account", "Reset default account", spacer, "Set default signature", "Reset default signature", spacer, "Set default subject", "Reset default subject", spacer, "Set default contents", "Reset default contents"}
	-- future: {".........", "Edit eMail settings"}
	tell me
		activate
		choose from list menuitems with title mytitle cancel button name "Quit" OK button name "Select" with prompt "Please choose an option:" without multiple selections allowed and empty selection allowed
		set choice to result
	end tell
	if choice is not false then
		set menuitem to item 1 of choice
		if menuitem is "........." then
			my dspmainmenu()
		else
			return menuitem
		end if
	else
		return missing value
	end if
end dspmainmenu

-- display an error message
on dsperrmsg(errmsg, errnum)
	tell me
		activate
		display dialog "Sorry, an error coccured:" & return & return & errmsg & " (" & errnum & ")" buttons {"Never mind"} default button 1 with icon stop with title mytitle
	end tell
end dsperrmsg