rename files and remove incompatible characters (Mail export renamer)

Ive setup a Script to rename exported Emails.
Exported means drag them from Apple Mail into a Finder folder.

The Script should look for the receiving date/time an rename the file like this.
A mail with the subject “Test-Subject” will be named “Test-Subject.eml” after dragging it into a Finder folder.
The Script renames the file to “2017-02-28-1412 Test-Subject”

For easy handling he Script is exported to an application an placed in the finder menu bar.

My Problem is:
Id like to replace “incompatible characters” which are in the subject of some Emails.

In my script removing a slash and colon works but if there is a pipe in the file name it remains.

I hope you can help me.

feel free to use, share an modify my script.

here is what my script looks like:

tell application “Finder”
activate
set selected_items to selection
end tell

tell application “Mail”
activate
set theMessages to selection
repeat with theMessage in theMessages

	set theText to source of theMessage
	set theSubject to (subject of theMessage) as Unicode text
	
	--Sollte die E-Mail ohne Betreff ankommen wird *E-Mail hat keinen Betreff* eingesetzt
	if theSubject is "" then set theSubject to ":E-Mail:hat:keinen:Betreff:"
	
	
	--Doppelpunkte im Betreff durch Unterstrich ersetzen
	if theSubject contains ":" then set theSubject to my snr(theSubject, ":", "_")
	
	--Slash im Betreff durch Unterstrich ersetzen
	if theSubject contains "/" then set theSubject to my snr(theSubject, "/", "_")
	
	--Pipe im Betreff durch Unterstrich ersetzen
	if theSubject contains "|" then set theSubject to my snr(theSubject, "|", "_")
	
	
	--Empfangsdatum auslesen
	set msgDate to date received of theMessage
	set {year:y, month:m, day:d, hours:h, minutes:min} to (msgDate)

	
	
	--Datumsformat erstellen
	set msgDate to (y & "-" & my pad2(m as integer) & "-" & my pad2(d) & "-" & my pad2(h) & my pad2(min))

	
	
	
end repeat

end tell

–Einstelligen Tagen und Monaten eine 0 vorstellen
on pad2(n)
return text -2 thru -1 of (“00” & n)
end pad2

–Text im Betreff auf inkompatibele Zeichen scannen und ggf ersetzen
on snr(theString, searchString, replaceString)
tell (a reference to my text item delimiters)
set {oldTID, contents} to {contents, searchString}
set {theString, contents} to {theString’s text items, replaceString}
set {theString, contents} to {theString as Unicode text, oldTID}
end tell
return theString
end snr

tell application “Finder”
try
Рwenn keine Finder Fenster ge̦ffnet sind desktop verwenden
set the source_folder to (folder of the front window) as text
on error
set the source_folder to (path to desktop folder) as text
end try
set these_items to the selection
end tell
repeat with i from 1 to the count of these_items
set this_item to (item i of these_items) as alias
set this_info to info for this_item
set {file_name, file_ext} to splitExtension from the name of this_info
set new_name to ((msgDate & " " & file_name & file_ext)) as string

-- prüfen ob datei mit selbem Namen existiert
tell application "Finder"
	if (exists item (source_folder & new_name)) then
		display dialog "Die Datei " & new_name & " existiert bereits. Weitere Version erstellen?" buttons {"Cancel", "OK"} default button "OK"
		if result = {button returned:"OK"} then
			
			-- Versionsnummer für Datei erfragen
			
			set vers to text returned of (display dialog "Bitte Versionsnummer Eingeben -> " & new_name & "_" buttons {"Cancel", "OK"} default button "OK" default answer "")
			set vers_name to ((msgDate & " " & file_name & "_" & vers & file_ext)) as string
			
			if (exists item (source_folder & vers_name)) then
				display dialog "Die Datei " & vers_name & " existiert auch schon. Bitte nochmal versuchen..." buttons {"Cancel", "OK"} default button "OK"
			else
				
				set name of this_item to vers_name
			end if
		else
			
		end if
	else
		set name of this_item to new_name
	end if
end tell

end repeat

to splitExtension from file_name
set dot to “.”
tell AppleScript
set oT to text item delimiters
set text item delimiters to dot
if (count text items of file_name) > 1 then
set out_name to (text items 1 through -2 of file_name) as string
set ext to last text item of file_name
else
set out_name to file_name
set ext to “”
end if
set text item delimiters to oT
if ext is not “” then set ext to dot & ext
return {out_name, ext}
end tell
end splitExtension

Hey There,

Don’t play with AppleScript’s text item delimiters.

Use a real find/replace mechanism that can handle regular expressions.

-Chris


-------------------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/05/08 00:59
# dMod: 2016/05/08 01:09
# Appl: AppleScriptObjC
# Task: Find-Replace or Change-Text Handler
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Find, @Replace, @Text, @RegEx
-------------------------------------------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
-------------------------------------------------------------------------------------------

set dataString to "This:Is|My/Test-Subject"

set newStr to its cngStr:"[[:blank:]]*[:|/][[:blank:]]*" intoString:" " inString:dataString

-------------------------------------------------------------------------------------------
--» HANDLERS
-------------------------------------------------------------------------------------------
on cngStr:findString intoString:replaceString inString:dataString
	set anNSString to current application's NSString's stringWithString:dataString
	set dataString to (anNSString's ¬
		stringByReplacingOccurrencesOfString:findString withString:replaceString ¬
			options:(current application's NSRegularExpressionSearch) range:{0, length of dataString}) as text
end cngStr:intoString:inString:
-------------------------------------------------------------------------------------------

With no change to the handler, you may filter the string with a single call :

	--Doppelpunkte, Slash or Pipe  im Betreff durch Unterstrich ersetzen
		set theSubject to my snr(theSubject, {":", "/", "|"}, "_")

I tested it with :

on snr(theString, searchString, replaceString)
	tell (a reference to my text item delimiters)
		set {oldTID, contents} to {contents, searchString}
		set {theString, contents} to {theString's text items, replaceString}
		set {theString, contents} to {theString as Unicode text, oldTID}
	end tell
	return theString
end snr

set maybe1 to "aaaa/bbbb:cccc|dddd"
set after1 to my snr(maybe1, {"/", ":", "|"}, "_")

set maybe2 to "aaaa|bbbb|cccc|dddd"
set after2 to my snr(maybe2, {"/", ":", "|"}, "_")

{after1, after2} --> {"aaaa_bbbb_cccc_dddd", "aaaa_bbbb_cccc_dddd"}

Yvan KOENIG running Sierra 10.12.3 in French (VALLAURIS, France) mardi 28 février 2017 17:03:32

Hey SebSta,

Personally I wouldn’t want to mess with drag and drop “ I’d want to do the task with a keystroke from FastScripts.

This will work as is, but it doesn’t add the date to the output file and does nothing to manage potential duplicates.

But “ it should give you enough to work out the rest. If not then holler.

-Chris


-------------------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2017/02/28 10:20
# dMod: 2017/02/28 10:37 
# Appl: Mail
# Task: Write selected messages to the Finder
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Finder, @Mail, @Save, @Write, @Selected, @Messages
-------------------------------------------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
-------------------------------------------------------------------------------------------

set messageSaveFolderPath to POSIX path of ((path to downloads folder as text) & "Saved Emails")
its createDirectoryAtPath:messageSaveFolderPath

tell application "Mail"
	
	set selectedMessageList to selection
	
	repeat with theMessage in selectedMessageList
		tell theMessage
			set msgSubject to subject
			set msgSubject to (my cngStr:":" intoString:";" inString:msgSubject)
			set msgSubject to (my cngStr:"[[:blank:]]*[|:/][[:blank:]]*" intoString:" " inString:msgSubject)
			set msgSource to source
			set messageSavePath to messageSaveFolderPath & "/" & msgSubject & ".eml"
			(my writeString:msgSource toPath:messageSavePath)
		end tell
	end repeat
	
end tell

set messageSaveFolderPath to alias POSIX file messageSaveFolderPath
tell application "Finder" to open messageSaveFolderPath

-------------------------------------------------------------------------------------------
--» HANDLERS
-------------------------------------------------------------------------------------------
on cngStr:findString intoString:replaceString inString:dataString
	set anNSString to current application's NSString's stringWithString:dataString
	set dataString to (anNSString's ¬
		stringByReplacingOccurrencesOfString:findString withString:replaceString ¬
			options:(current application's NSRegularExpressionSearch) range:{0, length of dataString}) as text
end cngStr:intoString:inString:
-------------------------------------------------------------------------------------------
on createDirectoryAtPath:thePath
	set {theResult, theError} to current application's NSFileManager's defaultManager()'s createDirectoryAtPath:thePath withIntermediateDirectories:true attributes:(missing value) |error|:(reference)
	if not (theResult as boolean) then
		set errorMsg to theError's localizedDescription() as text
		error errorMsg
	end if
end createDirectoryAtPath:
-------------------------------------------------------------------------------------------
on writeString:aString toPath:posixPath
	set anNSString to current application's NSString's stringWithString:aString
	anNSString's writeToFile:posixPath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
end writeString:toPath:
-------------------------------------------------------------------------------------------

Here is a version using ASObjC which may be easier to understand than the one using regex.

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions


# Borrowed to Shane STANLEY
on replaceSeveralCharacters:sourceString existingChars:listOfChars newString:d1
	set sourceString to current application's NSString's stringWithString:sourceString
	set theDelims to (current application's NSArray's arrayWithArray:listOfChars)'s componentsJoinedByString:""
	set setOfDelims to current application's NSCharacterSet's characterSetWithCharactersInString:theDelims
	set anArray to (sourceString's componentsSeparatedByCharactersInSet:setOfDelims)
	return (anArray's componentsJoinedByString:d1) as text
end replaceSeveralCharacters:existingChars:newString:

set maybe1 to "aaaa/bbbb:cccc|dddd"
set after1 to my replaceSeveralCharacters:maybe1 existingChars:{"/", ":", "|"} newString:"_"

set maybe2 to "aaaa|bbbb|cccc|dddd"
set after2 to my replaceSeveralCharacters:maybe2 existingChars:{"/", ":", "|"} newString:"_"

{after1, after2} --> {"aaaa_bbbb_cccc_dddd", "aaaa_bbbb_cccc_dddd"}

Yvan KOENIG running Sierra 10.12.3 in French (VALLAURIS, France) mardi 28 février 2017 18:31:25