Search code examples
rubygraphgruff

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


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


Solution

  • 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