FTP Files to WordPress by Email
Yes, another hack to make this site easier for me to manage.
I post a lot from Simplenote now. While this is very efficient for making link-posts, it makes it rather challenging to create a post with images. Images are stored on the Macdrifter host in the standard WordPress content directories but I need a URL to create the image link reference in Simplenote.
I have used GoodReader in the past to upload an image to the server, but I have to manually create the URL for the image. That's no fun.
So I created this insult to everyone that appreciates clean code.2 The script is attached to a mail rule on my primary Mac. When I send an email message with an attached image1 and a subject prefix "iii", the script is triggered. It saves the image to a specific directory on my Mac and then uploads it to Macdrifter.com by FTP using Transmit3. Upon successful upload, it sends a reply email with the URL to the image.
The Abomination
(*
Author: Gabe Weatherhead
date: 2012-03-16_090533
Script for FTP upload to WordPress via Apple Mail rule processing.
This work is Creative Commons-Attribution licensed. Basically, do what you want with it, but don't be dick.
http://creativecommons.org/licenses/
Mesaage subjects are expected to be prepended with "iii"
Transmit is expected a favorite to exist for the destiantion. Mine is named "Macdrifter_WP"
*)
using terms from application "Mail"
-- Uploads file using a saved favorite in Transmit
on upload_file(theFile)
try
-- Creates base URL for remote file based on standard WordPress content structure
set urlPath to "http://www.macdrifter.com/uploads.html"
set myMonth to do shell script "date +\"%m\""
set myYear to 1 * (year of (current date))
set clipContents to {}
tell application "Transmit"
-- Stored Transmit favorite
set myFav to item 1 of (favorites whose name is "Macdrifter_WP")
tell current tab of (make new document at end)
connect to myFav
-- tempMSG is used for Growl reporting of errors.
set tempMSG to "Transmit attmepting to connect"
set this_item to theFile
-- Update Error reporting
set tempMSG to (this_item as text)
-- Get the File's path
set this_info to info for this_item
set myPath to (POSIX path of this_item)
-- Update Error Reporting
set tempMSG to "Attempting to locate local file" & (myPath as text)
set myFileName to name of this_info as text
-- Transmit must open the local location that holds the file
change location of local browser to path (POSIX path of ("Macintosh HD 2:Dropbox:Todo Files:Blog:"))
-- It's just easier to encode URL safe characters with Python
set myURLFileName to do shell script "/usr/bin/python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' " & ¬
quoted form of myFileName
set myURLFileName to urlPath & myYear & "/" & myMonth & "/" & myURLFileName
set end of clipContents to "
" & myURLFileName
-- Tell Transmit to do the upload
tell remote browser
upload item at path myPath to "webapps/wp/wp-content/uploads/" & myYear & "/" & ¬
myMonth & "/" with resume mode overwrite with continue after error
end tell
-- I like to have the URL put on my clipboard as well
set the clipboard to myURLFileName
close remote browser
end tell
close front window
end tell
set AppleScript's text item delimiters to "
"
set clipContents to clipContents as string
set AppleScript's text item delimiters to ""
return clipContents
on error errmesg number errn
set AppleScript's text item delimiters to ""
return errmesg & return & tempMSG & "error number: " & (errn as rich text)
end try
end upload_file
-- I prefer Growl messaging for error reporting since I also use Prowl for iOS
on growl_message(theMessage)
tell application "System Events"
set isRunning to (count of (every process whose bundle identifier is "com.Growl.GrowlHelperApp")) > 0
end tell
if isRunning then
tell application id "com.Growl.GrowlHelperApp"
set the allNotificationsList to ¬
{"FTP Mail Handler Script", "Script Success", "Script Error.app"}
set the enabledNotificationsList to ¬
{"FTP Mail Handler Script"}
register as application ¬
"FTP Mail Rule Script" all notifications allNotificationsList ¬
default notifications enabledNotificationsList ¬
icon of application "Script Editor"
notify with name "FTP Mail Handler Script" title ¬
"FTP Mail Handler" description "FTP Upload: " & ¬
theMessage application name "FTP Mail Rule Script"
end tell
end if
end growl_message
-- Mail Rule starts processing the messages that match
on perform mail action with messages theMessages for rule theRule
try
-- Just another sanity check. Only messages that begin with this prefix get processed.
set custom_prefix to "iii"
-- All of my WordPress images start in the same local location
set localPath to "/Volumes/Macintosh HD 2/Dropbox/Todo Files/Blog/"
repeat with oneMessage in theMessages
set receivedSubject to subject of oneMessage
set outgoingSubject to "Re: " & receivedSubject
set theSender to extract address from sender of oneMessage
if (receivedSubject starts with custom_prefix) then
set {mail attachment:theAttachments} to oneMessage
repeat with oneAttachment in mail attachments of oneMessage
set newFilePath to POSIX path of (("Macintosh HD 2:Dropbox:Todo Files:Blog:") & (name of oneAttachment))
--growl_message(newFilePath)
save oneAttachment in ("Macintosh HD 2:Dropbox:Todo Files:Blog:") & (name of oneAttachment)
set fileURL to upload_file(newFilePath)
growl_message(fileURL)
set mailBody to "File Uploaded to Server: " & return & return & (fileURL as rich text)
set AppleScript's text item delimiters to {""}
set theNewMessage to make new outgoing message with properties ¬
{visible:true, subject:outgoingSubject, content:mailBody, sender:"gabe@macdrifter.com"}
tell theNewMessage
make new recipient at end of to recipients with properties {address:theSender}
end tell
send theNewMessage
set AppleScript's text item delimiters to ""
end repeat
end if
end repeat
on error errmesg number errn
set AppleScript's text item delimiters to ""
growl_message(errmesg & return & return & "error number: " & (errn as rich text))
end try
end perform mail action with messages
end using terms from
Commentary
It might not be obvious, but this method requires an always-on Mac with Mail running. That's not a problem for me.
This is written explicitly for my WordPress content structure. This is pretty standard stuff but it's possible to use another file structure. Just change the urlPath
variable appropriately.
I use Growl for notifications. About 1/3 of this script is for error handling and Growl messaging. I like this method because I also use Prowl. Any errors are displayed on my iOS devices almost immediately. I can also look over the Growl logs to see the history. Good stuff.
The script also inserts the link on my Macs clipboard. Since I use Launchbar, that means when I come back to my desk, all the links I generated remotely are right there in my history, ready to paste.
The script replies back to the same email address I sent from. I am not using the AppleScript "reply" method for Mail. It doesn't work well. Seriously, this is why we can't have nice AppleScripts.
Usage
This will work from any app that can send an image by email. That covers most of them, including the new iPhoto for iOS.
I wish there was an Acorn for iOS, but iPhoto does some nice stuff with images. It's not perfect, but it is pretty good for basic image enhancements.
-
Technically, it will work with any attachment. It should handle multiple attachments as well, but I haven't been using it that way. ↩
-
It's bad. I've tried to provide comments, but that will not make the code any better. I'd clean it up, but I'm planning a total rewrite using AppleScriptObjC. That will take a long time. This works now. ↩
-
I use Transmit because it's the best FTP client around. But it also has some nice features that make scripting easy. For example, Transmit can save my credentials with the FTP connection. The script can then login without ever needing to know the credentials. When I change my FTP credentials, I only need to change them in Transmit, not 25 different scripts. ↩