class EmailParser attr_reader :sender, :recipient, :email_text, :email def initialize(sender, recipient, email_text) @sender = sender @recipient = recipient @email_text = email_text.forcibly_convert_to_utf8 @email = nil begin # the mail gem stupidly spams STDERR while parsing e-mail, so silence # that stream to avoid anything getting back to postfix Utils.silence_stream(STDERR) do @email = Mail.read_from_string(email_text) end rescue end @sending_user = nil @parent = nil @body = nil end def user_token @recipient.gsub(/^#{Rails.application.shortname}-/, "").gsub(/@.*/, "") end def been_here? !!@email_text.match(/^X-BeenThere: #{Rails.application.shortname}-/i) end def sending_user return @sending_user if @sending_user if (user = User.where("mailing_list_mode > 0 AND mailing_list_token = ?", user_token).first) && user.is_active? @sending_user = user return user end end def parent return @parent if @parent irt = self.email[:in_reply_to].to_s.gsub(/[^A-Za-z0-9@\.]/, "") if m = irt.match(/^comment\.([^\.]+)\.\d+@/) @parent = Comment.where(:short_id => m[1]).first elsif m = irt.match(/^story\.([^\.]+)\.\d+@/) @parent = Story.where(:short_id => m[1]).first end @parent end def body return @body if @body @possible_charset = nil if self.email.multipart? # parts[0] - multipart/alternative # parts[0].parts[0] - text/plain # parts[0].parts[1] - text/html if (p = self.email.parts.first.parts.select{|p| p.content_type.match(/text\/plain/i) }).any? @body = p.first.body.to_s begin @possible_charset = p.first.content_type_parameters["charset"] rescue end # parts[0] - text/plain elsif (p = self.email.parts.select{|p| p.content_type.match(/text\/plain/i) }).any? @body = p.first.body.to_s begin @possible_charset = p.first.content_type_parameters["charset"] rescue end end # simple one-part elsif self.email.content_type.to_s.match(/text\/plain/) @body = self.email.body.to_s begin @possible_charset = self.email.content_type_parameters["charset"] rescue end elsif !self.email.content_type.to_s.present? # no content-type header, assume it's text/plain @body = self.email.body.to_s end # TODO: use @possible_charset, but did previously forcing the entire # email_text to utf8 screw this up already? # try to remove sig lines @body.gsub!(/^-- \n.+\z/m, "") # try to strip out attribution line, followed by an optional blank line, # and then lines prefixed with > @body.gsub!(/^(On|on|at) .*\n\n?(>.*\n)+/, "") @body.strip! end end