5

I'm using Ruby script and the "mail" gem to send emails.

Question - How could how to send a graph via email in Ruby without saving to disk? Is this possible? Which graphing tool would you recommend and would the "mail" gem support somehow streaming this out? (or it it a given you have to save to disk first) If it's possible/easy sample code lines should how to would be great....

Greg
  • 34,042
  • 79
  • 253
  • 454
  • I think more information would be helpful. What do you mean by a 'graph' - a thing with nodes and edges, a graphical representation of some functional data, something completely different? What kind of data are you starting with? Why is saving to disk a problem? – dantswain Mar 22 '12 at 12:13
  • @dantswain Re graph I meant something that creates a simple graph, for example bar graph, whereby the input to it might be a hash of X,Y values or something. In one specific case. So something like the graph http://www.germane-software.com/software/SVG/SVG%3A%3AGraph/ SVG library referenced from Corens link below looks fine. – Greg Mar 22 '12 at 23:59
  • Looks like @Coren's answer is on the right track, then. – dantswain Mar 23 '12 at 13:58

2 Answers2

10

Your complete answer.

This uses a pure Ruby PNG graph for simplicity; a real world app would likely use SVG, or fast native code, or a graph API.

#!/usr/bin/env ruby
=begin

How to send a graph via email in Ruby without saving to disk
Example code by Joel Parker Henderson at SixArm, joel@sixarm.com

    http://stackoverflow.com/questions/9779565

You need two gems:

    gem install chunky_png
    gem install mail

Documentation:

    http://rdoc.info/gems/chunky_png/frames
    https://github.com/mikel/mail

=end


# Create a simple PNG image from scratch with an x-axis and y-axis.
# We use ChunkyPNG because it's pure Ruby and easy to write results;
# a real-world app would more likely use an SVG library or graph API.

require 'chunky_png'
png = ChunkyPNG::Image.new(100, 100, ChunkyPNG::Color::WHITE)
png.line(0, 50, 100, 50, ChunkyPNG::Color::BLACK)  # x-axis
png.line(50, 0, 50, 100, ChunkyPNG::Color::BLACK)  # y-axis

# We do IO to a String in memory, rather than to a File on disk.
# Ruby does this by using the StringIO class which akin to a stream.
# For more on using a string as a file in Ruby, see this blog post:
# http://macdevelopertips.com/ruby/using-a-string-as-a-file-in-ruby.html

io = StringIO.new
png.write(io) 
io.rewind

# Create a mail message using the Ruby mail gem as usual. 
# We create it item by item; you may prefer to create it in a block.

require 'mail'
mail = Mail.new
mail.to = 'alice@example.com'
mail.from = 'bob@example.com'
mail.subject = 'Hello World'

# Attach the PNG graph, set the correct mime type, and read from the StringIO

mail.attachments['graph.png'] = {
  :mime_type => 'image/png', 
  :content => io.read 
}

# Send mail as usual. We choose sendmail because it bypasses the OpenSSL error.
mail.delivery_method :sendmail
mail.deliver
joelparkerhenderson
  • 34,808
  • 19
  • 98
  • 119
5

I don't see why you couldn't. In mail's documentation, you can see this sample code :

mail = Mail.new do
  from     'me@test.lindsaar.net'
  to       'you@test.lindsaar.net'
  subject  'Here is the image you wanted'
  body     File.read('body.txt')
  add_file :filename => 'somefile.png', :content => File.read('/somefile.png')
end

mail.deliver!

You just have to replace target of :content => ... with your in-memory file content. And that should be enough. There's no real need of having attachments saved, even temporarily, to disk since they are re-encoded in base64 and added at the end of your mail.

For the second part of your question, there's many plot/graph lib around there. See this question or this lib for instance.

There's not really one lib above the others for this kind of matters. There's many lib for many different usage and you have to choose what fits more your needs and your constraints.

Community
  • 1
  • 1
Coren
  • 5,517
  • 1
  • 21
  • 34