class TaskJuggler::SheetReceiver

Public Class Methods

new(appName, type) click to toggle source
Calls superclass method TaskJuggler::SheetHandlerBase.new
# File lib/taskjuggler/SheetReceiver.rb, line 27
def initialize(appName, type)
  super(appName)

  @sheetType = type
  # The following settings must be set by the deriving class.
  # Sheet type specific option for tj3client
  @tj3clientOption = nil
  # Base directory to store received sheets
  @sheetDir = nil
  # Base directory where to find the resource file.
  @templateDir = nil
  # Directory to store the failed emails.
  @failedMailsDir = nil
  # Directory to store the failed sheets
  @failedSheetsDir = nil
  # File that holds the acceptable signatures.
  @signatureFile = nil
  # The log file
  @logFile = nil
  # The subject of the confirmation email
  @emailSubject = nil

  # Regular expressions to identify a sheet.
  @sheetHeader = nil
  # Regular expression to extract the sheet signature (date).
  @signatureFilter = nil
  # The email address of the submitter of the sheet.
  @submitter = nil
  # The resource ID of the submitter.
  @resourceId = nil
  # The stdout content from tj3client
  @report = nil
  # The stderr content from tj3client
  @warnings = nil

  # The extracted sheet text.
  @sheet = nil
  # Will indicate whether the sheet was attached or in mail body
  @sheetWasAttached = true
  # The end date of the reporting period.
  @date = nil
  # The id of the incomming message.
  @messageId = nil
end

Public Instance Methods

processEmail() click to toggle source

Read the sheet from $stdin in email format. Extract the sheet from the attachments or body and check it. If ok, send back a summary, otherwise the error message. The actual check is done by a tj3 server process that is accessed via tj3client.

# File lib/taskjuggler/SheetReceiver.rb, line 77
    def processEmail
      setWorkingDir

      createDirectories

      begin
        # Read the RFC 822 compliant mail from STDIN.
        rawMail = $stdin.read
        rawMail = rawMail.forceUTF8Encoding

        mail = Mail.new(rawMail)
      rescue
        # In certain cases, Mail will fail to create the Mail object. Since we
        # don't have the email sender yet, we have to try to extract it
        # ourself.
        fromLine = nil
        rawMail.each_line do |line|
          unless fromLine
            matches = line.match('^From: .*')
            if matches
              fromLine = matches[0]
              break
            end
          end
        end

        # Try to extract the mail sender the dirty way so we can at least send
        # a response to the submitter.
        @submitter = fromLine[6..-1] if fromLine && fromLine.is_a?(String)
        error("Incoming mail could not be processed: #{$!}")
      end

      # Who sent this email?
      @submitter = mail.from.respond_to?('[]') ? mail.from[0] : mail.from
      # Getting the message ID.
      @messageId = mail.message_id || 'unknown'
      @idDigest = Digest::MD5.hexdigest(@messageId)
      info("Processing #{@sheetType} mail from #{@submitter} " +
           "with ID #{@messageId} (#{@idDigest})")

      # Store the mail in the failedMailsDir in case something goes wrong.
      File.open("#{@failedMailsDir}/#{@idDigest}", 'w') do |f|
        f.write(mail)
      end

      # First we search the attachments and then the body.
      mail.attachments.each do |attachment|
        # We are looking for an attached file with a .tji extension.
        fileName = attachment.filename
        next unless fileName && fileName[-4..-1] == '.tji'

        # Further inspect the attachment. If we could process it, we are done.
        return true if processSheet(attachment.body.decoded)
      end
      # None of the attachements worked, so let's try the mail body.
      @sheetWasAttached = false
      return true if processSheet(mail.body.decoded)

      error(<<"EOT"
No #{@sheetType} sheet found in email. Please make sure the header syntax is
correct and contained in a single line that starts at the begining of the
line. If you had the #{@sheetType} sheet attached, the file name must have a
'.tji' extension to be found.
EOT
           )
    end