class TaskJuggler::SheetHandlerBase

Attributes

dryRun[RW]
workingDir[RW]

Public Class Methods

new(appName) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 24
def initialize(appName)
  @appName = appName
  # User specific settings
  @emailDeliveryMethod = 'smtp'
  @smtpServer = nil
  @senderEmail = nil
  @workingDir = nil
  @scmCommand = nil
  # The default project ID
  @projectId = 'prj'

  # Controls the amount of output that is sent to the terminal.
  # 0: No output
  # 1: only errors
  # 2: errors and warnings
  # 3: All messages
  @outputLevel = 2
  # Controls the amount of information that is added to the log file. The
  # levels are identical to @outputLevel.
  @logLevel = 3
  # Set to true to not send any emails. Instead the email (header + body) is
  # printed to the terminal.
  @dryRun = false

  @logFile = 'timesheets.log'
  @emailFailure = false
end

Public Instance Methods

addToScm(message, fileName) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 108
def addToScm(message, fileName)
  return unless @scmCommand

  cmd = @scmCommand.gsub(/%m/, message)
  cmd.gsub!(/%f/, fileName)
  unless @dryRun
    %x#{cmd}`
    if $? == 0
      info("Added #{fileName} to SCM")
    else
      error("SCM command #{cmd} failed: #{$?.class}")
    end
  end
end
cutOut(text) click to toggle source

Extract the text between the cut-marker lines and remove any email quotes from the beginnin of the line.

# File lib/taskjuggler/SheetHandlerBase.rb, line 54
def cutOut(text)
  # Pattern for the section start marker
  mark1 = /(.*)# --------8<--------8<--------/
  # Pattern for the section end marker
  mark2 = /# -------->8-------->8--------/
  # The cutOut section
  cutOutText = nil
  quoteLen = 0
  quoteMarks = emptyLine = ''
  text.each_line do |line|
    if cutOutText.nil?
      # We are looking for the line with the start marker (mark1)
      if (matches = mark1.match(line))
        quoteMarks = matches[1]
        quoteLen = quoteMarks.length
        # Special case for quoted empty lines without trailing spaces.
        emptyLine = quoteMarks.chomp.chomp(' ') + "\n"
        cutOutText = line[quoteLen..-1]
      end
    else
      # Remove quote marks from the beginning of the line.
      line = line[quoteLen..-1] if line[0, quoteLen] == quoteMarks
      line = "\n" if line == emptyLine

      cutOutText << line
      # We are gathering text until we hit the end marker (mark2)
      return cutOutText if mark2.match(line)
    end
  end

  # There are no cut markers. We just return the original text.
  text
end
error(message) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 133
def error(message)
  $stderr.puts message if @outputLevel >= 1
  log("ERROR", message) if @logLevel >= 1
  raise TjRuntimeError
end
htmlMailBody(message) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 239
    def htmlMailBody(message)
      html = HTMLDocument.new
      head = html.generateHead("TaskJuggler Report - #{@name}",
                               'description' => 'TaskJuggler Report',
                               'keywords' => 'taskjuggler, project, management')

      auxSrcDir = AppConfig.dataDirs('data/css')[0]
      cssFileName = (auxSrcDir ? auxSrcDir + '/tjreport.css' : '')
      # Raise an error if we haven't found the data directory
      if auxSrcDir.nil? || !File.exist?(cssFileName)
        dataDirError(cssFileName)
      end
      cssFile = IO.read(cssFileName)
      if cssFile.empty?
        raise TjException.new, <<"EOT"
Cannot read '#{cssFileName}'. Make sure the file is not empty and you have
read access permission.
EOT
      end
      head << XMLElement.new('meta', 'http-equiv' => 'Content-Style-Type',
                             'content' => 'text/css; charset=utf-8')
      head << (style = XMLElement.new('style', 'type' => 'text/css'))
      style << XMLBlob.new("\n" + cssFile)

      html.html << (body = XMLElement.new('body'))
      body << message.to_html

      html.to_s
    end
info(message) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 123
def info(message)
  puts message if @outputLevel >= 3
  log('INFO', message) if @logLevel >= 3
end
log(type, message) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 139
def log(type, message)
  timeStamp = Time.new.strftime("%Y-%m-%d %H:%M:%S")
  File.open(@logFile, 'a') do |f|
    f.write("#{timeStamp} #{type} #{@appName}: #{message}\n")
  end
end
sendEmail(to, subject, message, attachment = nil, from = nil, inReplyTo = nil) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 164
def sendEmail(to, subject, message, attachment = nil, from = nil,
              inReplyTo = nil)
  case @emailDeliveryMethod
  when 'smtp'
    Mail.defaults do
      delivery_method :smtp, {
        :address => @smtpServer,
        :port => 25
      }
    end
  when 'sendmail'
    Mail.defaults do
      delivery_method :sendmail
    end
  else
    raise "Unknown email delivery method: #{@emailDeliveryMethod}"
  end

  begin
    self_ = self
    mail = Mail.new do
      subject subject
      text_part do
        content_type [ 'text', 'plain', { 'charset' => 'UTF-8' } ]
        content_transfer_encoding 'base64'
        body message.to_s.to_base64
      end
      if message.is_a?(RichTextIntermediate)
        html_part do
          content_type 'text/html; charset=UTF-8'
          content_transfer_encoding 'base64'
          body self_.htmlMailBody(message).to_base64
        end
      end
    end
    mail.to = to
    mail.from = from || @senderEmail
    mail.in_reply_to = inReplyTo if inReplyTo
    mail['User-Agent'] = "#{AppConfig.softwareName}/#{AppConfig.version}"
    mail['X-TaskJuggler'] = @appName
    if attachment
      mail.add_file ({
        :filename => File.basename(attachment),
        :content => File.read(attachment)
      })
    end
    #raise "Mail header problem" unless mail.errors.empty?
  rescue
    @emailFailure = true
    error("Email processing failed: #{$!}")
  end

  if @dryRun
    # For testing and debugging, we only print out the email.
    puts "-- Email Start #{'-' * 60}\n#{mail.to_s}-- Email End #{'-' * 62}"
    log('INFO', "Show email '#{subject}' to #{to}")
  else
    # Actually send out the email.
    begin
      mail.deliver
    rescue
      # We try to send out another email. If that fails again, we abort
      # without further attempts.
      if @emailFailure
        log('ERROR', "Email double fault: #{$!}")
        raise TjRuntimeError
      else
        @emailFailure = true
        error("Email transmission failed: #{$!}")
      end
    end
    log('INFO', "Sent email '#{subject}' to #{to}")
  end
end
sendRichTextEmail(to, subject, message, attachment = nil, from = nil, inReplyTo = nil) click to toggle source

Like SheetHandlerBase::sendEmail but interpretes the message as RichText markup. The generated mail will have a text/plain and a text/html part.

# File lib/taskjuggler/SheetHandlerBase.rb, line 149
def sendRichTextEmail(to, subject, message, attachment = nil, from = nil,
                      inReplyTo = nil)
  rti = RichText.new(message).generateIntermediateFormat
  rti.lineWidth = 72
  rti.indent = 2
  rti.titleIndent = 0
  rti.listIndent = 2
  rti.parIndent = 2
  rti.preIndent = 4
  rti.sectionNumbers = false

  # Send out the email.
  sendEmail(to, subject, rti, attachment, from, inReplyTo)
end
setWorkingDir() click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 88
def setWorkingDir
  # Make sure the user has provided a properly setup config file.
  case @emailDeliveryMethod
  when 'smtp'
    error('\smtpServer\ not configured') unless @smtpServer
  when 'sendmail'
    # nothing to check
  else
    error("Unknown emailDeliveryMethod #{@emailDeliveryMethod}")
  end
  error('\senderEmail\ not configured') unless @senderEmail

  # Change into the specified working directory
  begin
    Dir.chdir(@workingDir) if @workingDir
  rescue
    error("Working directory #{@workingDir} not found")
  end
end
warning(message) click to toggle source
# File lib/taskjuggler/SheetHandlerBase.rb, line 128
def warning(message)
  puts message if @outputLevel >= 2
  log('WARN', message) if @logLevel >= 2
end