Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to send a graph via email in Ruby without saving to disk?

Tags:

graph

ruby

gruff

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....

like image 776
Greg Avatar asked Mar 19 '12 23:03

Greg


2 Answers

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, [email protected]

    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 = '[email protected]'
mail.from = '[email protected]'
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
like image 179
joelparkerhenderson Avatar answered Nov 06 '22 05:11

joelparkerhenderson


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

mail = Mail.new do
  from     '[email protected]'
  to       '[email protected]'
  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.

like image 43
Coren Avatar answered Nov 06 '22 05:11

Coren