Getting RSS from Apple mail to NetNewsWire
I have been using Apple Mail to monitor my RSS feeds. I like it because it’s right there when I check email. Unfortunately, while I can set up my mail account using IMAP and have everything in sync regardless of whether I use the Mac Pro in the study, my Macbook Air, or my iPhone, the RSS feeds do not sync up. So, sitting here in the hospital, I am unable to keep up with all the feeds on my main machine. I did a bit of searching and found that NetNewsWire will do the trick of keeping them all synchronized (including the iPhone).
Downloaded…Installed…now, just import my RSS feeds from Apple Mail…hmmmmm…. search Google… only hit is this blog entry bemoaning the lack of this capability.
Well now, a bored programmer, laid up in the hospital, feeling just fine, and sharing the same need can’t just let a situation like this stand.
So, here’s a ruby script that will read the RSS feeds from your Apple Mail and create an opml file named AppleMailRSS.opml on your desktop. This file will import into NetNewsWire and, though I’ve not tested anything else, presumably any other RSS reader that imports opml files.
(Update note: (March 21, 2009) I’ve updated the script to handle any RSS feeds in folders in Apple Mail. Thanks Sebastion for pointing this out. I was not using folders in Apple Mail so I missed this detail.)
skeleton = <<EOSTRING
<?xml version="1.0" encoding="UTF-8"?>
<opml version="1.1">
<head>
<title>Subscriptions from Apple Mail</title>
</head>
<body>
</body>
</opml>
EOSTRING
return node if folders.length == 0
folder = folders.shift
node.each_element("outline[@title='']") do |fNode|
return getFolder(fNode,folders)
end
fNode = REXML::Element.new 'outline'
fNode.attributes['text'] = folder
fNode.attributes['title'] = folder
node << fNode
return getFolder(fNode,folders)
end
ol = REXML::Element.new 'outline'
ol.attributes['text'] = title
ol.attributes['description'] = ''
ol.attributes['title'] = title
ol.attributes['type'] = 'rss'
ol.attributes['version'] = 'RSS'
ol.attributes['htmlUrl'] = ''
ol.attributes['xmlUrl'] = url
getFolder(body,folders) << ol
end
doc = REXML::Document.new(skeleton)
body = REXML::XPath.match(doc,'//body')[0]
Dir.chdir()
Dir.chdir('Library/Mail/RSS')
Dir.glob('**/*.rssmbox') do |mbox|
m = mbox.match(/(.*\/)*(.*).rssmbox/)
folders = m[1] ? m[1].split('/') : []
title = m[2]
File.open("/Info.plist") do |file|
url = file.read.match(/RSSFeedURLString.*?<string>(.*?)</m)[1]
addRSSNode(body,folders,title,url)
end
end
Dir.chdir()
File.open('Desktop/AppleMailRSS.opml','w') do |file|
doc.write( file, 0 )
end

Hi!
Looks like a great script, but unfortunately I get an error trying to run it on my MacBook. I ran it by copying the text from here into a file I named mailrssopml.rb and ran it from the Terminal using ‘ruby mailrssopml.rb’.
mailrssopml.rb:31: undefined method `[]‘ for nil:NilClass (NoMethodError)
from mailrssopml.rb:30:in `glob’
from mailrssopml.rb:30
I have no experience in Ruby so I have no idea how to correct it.
That would seem to imply that the script did not find any *.rssmbox files.
Can you open a terminal session and try the follwing command?
ls ~/Library/Mail/RSS
if you see a list of files ending with .rssmbox, then I need to work on the script since I’m obviously not finding them. If you don’t have any files in that directory, I’m not sure what to say. For my version of Apple Mail, this is where those files are located.
I have my RSS feeds organized in folders, so running that command displays my folders, and the lone *.rssmbox that does not reside in a folder. Does your script check in sub folders? Even if it doesn’t, I think it should pick up the one RSS feed that is in the root folder.
Ah, that makes sense. I wasn’t using folders. Let me play around and I’ll try to post an updated version in the next few days (maybe this weekend)
I’ve just updated the script to handle RSS feeds in folders. Give it a try and let me know if you have any problems.
Hey!
Great update to the script.
Sebastian
The style of writing is quite familiar to me. Did you write guest posts for other blogs?
Nope, guess I’ve just been influenced by others. I’ve been told that I write pretty conversationally. Folks that know me have told me that I write exactly the way I talk and that they can pretty much hear me talking as they read what I write. It’s always a bit funny that they find this surprising. “Hey the words come out the same whether you speak or type!!”.
A backslash is missing on line 44, before the yellow forward slash..
Fixed line:
m = mbox.match(/(.*\/)*(.*).rssmbox/)
And so I learned Ruby to avoid writing an email
Thanks Mike!
hmmm… that’s interesting. I just pulled up my local copy and it has the missing backslash. I wondered how it worked for me if I had it wrong. Looks like something funky happened when I used TextMate to create the syntax highlighted html for the script.
I’ve updated it. Thanks for pointing that out.
great, it did exactly the job!
thank you very much for turning out this solution.
maybe, you wanna add some little tips for newbies –
how to use this code.
(saving the code to a “***.rb” file,
executing in terminal with “ruby *file*”
bye,
ewok
sure, share all you want
You wouldn¡¯t believe it but I¡¯ve wasted all day digging for some articles about this. You¡¯re a lifesaver, it was an excellent read and has helped me out to no end. Cheers,
[...] welches die RSS-Feeds aus Mail ausliest und als OPML Datei zusammenfasst. Den Script Content vom Blog des Entwicklers – Danke an dieser Stelle an Mike Cargal – in eine neue “ImportRSS.rb” [...]
Nice post, thanks!
Great blog, I will add this blog to my favorites.
hey, nice blog…really like it and added to bookmarks. keep up with good work
I pasted the code above into a text file and saved as mailrssopml.rb. I placed this file in my /user folder. I then issued this command in terminal: ruby mailrssopml.rb.
However, I got this error message in terminal “mailrssopml.rb:39: uninitialized constant REXML (NameError)”
Any ideas why this would occur? Thanks so much for putting this code together!
Your error message would imply that REXML may not be installed. That’s odd for two reasons. 1 – I would expect to see some error on the require statement at the top of the script. Apparently, that executed fine (unless there were more messages than just the one you left in your comment). 2 – REXML is a standard Ruby library, and definitely should be installed on your machine.
Can you tell me what version of OS X you are on? maybe what version of Ruby as well (you can get this by executing “ruby -v” in a terminal window. I get “ruby 1.8.6 (2007-03-13 patchlevel 0) [universal-darwin8.0]“. That’s on Snow Leopard.
You might take a look at the REXML page as well (http://www.germane-software.com/software/rexml/).
Would you please translate your blog into Germany because I’m not selfsame comfortable reading it in English? I’m getting tired of employing Google Translate totally the time, there is a small WP plugin predicted like global translator which will translate entirely your pages automatically- that will construct reading posts on your corking blog evening more cosy. Cheers dude, Thanks!
thanks for posting this, I was looking for this info
Excellent post once again. I am looking forward for your next post:)
Interesting, thanks a lot!
I liked your post. Cheers
This is chinese to me but i need to do it can you please put step by step.
I understand that i need to copy paste the code into terminal ? is that it?
No, sorry that’s not clear. You’ll need to open an editor and copy and paste the code into the editor. Then save the file. You can call it whatever you want but the convention would be to have the file end in “.rb”. I’d suggest something like ConvertRSS.rb. Once you’ve saved it, open terminal, go to the directory where you’ve saved the file and, at the command prompt, type “Ruby ConvertRSS.rb” (or whatever you decided to name your file.
Hope that helps.