ruby-on-railsrubyrubygemsmailman-gem

How do I get the text part only from Mailman email?


I'm using the Mailman gem to process incoming email for my Rails app. My application looks for a YAML document in the plain-text email and then loads it into a Ruby object for further manipulation by the app.

However, I want to be able to plan ahead for email clients that might respond with a multi-part email. I need to get the plain-text part of the email and pass it into the YAML parser.

For some reason, it's still having problems parsing the YAML. I'm guessing because it's not really getting the plain text part here.

Is there a better way to get the text/plain part of an email with Mailman? Should I scrap Mailman and just get down and dirty with ActionMailer instead?

Mailman::Application.run do
    default do
        begin
            message.parts.each do |part|
                Mailman.logger.info part.content_type
                if part.content_type == 'text/plain; charset=ISO-8859-1' # My poor way of getting the text part
                    the_yaml = part.body.decoded.scan(/(\-\-\-.*\.\.\.)/m).first.last # Find the YAML doc in the email and assign it to the_yaml
                    ruby_obj = YAML::load(the_yaml.sub(">", "")) # Remove any >'s automatically added by email clients

                    if ruby_obj['Jackpots']
                        ruby_obj['Jackpots'].each do |jackpot|
                            jp = Jackpot.find(jackpot['jackpot']['id'])
                            jp.prize = jackpot['jackpot']['prize']
                            jp.save
                        end
                    end
                end
            end
        rescue Exception => e
                Mailman.logger.error "Exception occurred while receiving message:\n#{message}"
                Mailman.logger.error [e, *e.backtrace].join("\n")
        end
    end
end

Solution

  • I was able to find a little bit better way to handle getting the text part of the email.

    Mailman::Application.run do
        default do
            begin           
                if message.multipart?
                    the_message = message.text_part.body.decoded
                else
                    the_message = message.body.decoded
                end
    
                the_yaml = the_message.sub(">", "").scan(/(\-\-\-.*\.\.\.)/m).first.last
                ruby_obj = YAML::load(the_yaml)
    
                if ruby_obj['Jackpots']
                    ruby_obj['Jackpots'].each do |jackpot|
                        jp = Jackpot.find(jackpot['jackpot']['id'])
                        jp.prize = jackpot['jackpot']['prize']
                        jp.save
                    end
                end
    
            rescue Exception => e
                    Mailman.logger.error "Exception occurred while receiving message:\n#{message}"
                    Mailman.logger.error [e, *e.backtrace].join("\n")
            end
        end
    end
    

    And then after running it through the debugger and inspecting after the text part was successfully parsed. It would get hung up on the YAML loading. Turns out, a couple of my lines were too long, to the email client inserted a newline, breaking a comment in my YAML, and thus breaking the whole YAML document.