Index: test/unit/mail_handler_test.rb
===================================================================
--- test/unit/mail_handler_test.rb	(revision 2815)
+++ test/unit/mail_handler_test.rb	(working copy)
@@ -1,5 +1,5 @@
-# redMine - project management software
-# Copyright (C) 2006-2007  Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2009  Jean-Philippe Lang
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -127,6 +127,41 @@
     assert_equal 1, issue.watchers.size
   end
   
+  def test_add_issue_by_unknown_user
+    assert_no_difference 'User.count' do
+      assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'})
+    end
+  end
+  
+  def test_add_issue_by_anonymous_user
+    Role.anonymous.add_permission!(:add_issues)
+    assert_no_difference 'User.count' do
+      issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
+      assert issue.is_a?(Issue)
+      assert issue.author.anonymous?
+    end
+  end
+  
+  def test_add_issue_by_created_user
+    Setting.default_language = 'en'
+    assert_difference 'User.count' do
+      issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create')
+      assert issue.is_a?(Issue)
+      assert issue.author.active?
+      assert_equal 'john.doe@somenet.foo', issue.author.mail
+      assert_equal 'John', issue.author.firstname
+      assert_equal 'Doe', issue.author.lastname
+    
+      # account information
+      email = ActionMailer::Base.deliveries.first
+      assert_not_nil email
+      assert email.subject.include?('account activation')
+      login = email.body.match(/\* Login: (.*)$/)[1]
+      password = email.body.match(/\* Password: (.*)$/)[1]
+      assert_equal issue.author, User.try_to_login(login, password)
+    end
+  end
+  
   def test_add_issue_without_from_header
     Role.anonymous.add_permission!(:add_issues)
     assert_equal false, submit_email('ticket_without_from_header.eml')
Index: app/models/mail_handler.rb
===================================================================
--- app/models/mail_handler.rb	(revision 2815)
+++ app/models/mail_handler.rb	(working copy)
@@ -38,15 +38,34 @@
   end
   
   # Processes incoming emails
+  # Returns the created object (eg. an issue, a message) or false
   def receive(email)
     @email = email
-    @user = User.active.find(:first, :conditions => ["LOWER(mail) = ?", email.from.to_a.first.to_s.strip.downcase])
-    unless @user
-      # Unknown user => the email is ignored
-      # TODO: ability to create the user's account
-      logger.info "MailHandler: email submitted by unknown user [#{email.from.first}]" if logger && logger.info
+    @user = User.find_by_mail(email.from.to_a.first.to_s.strip)
+    if @user && !@user.active?
+      logger.info  "MailHandler: ignoring email from non-active user [#{@user.login}]" if logger && logger.info
       return false
     end
+    if @user.nil?
+      # Email was submitted by an unknown user
+      case @@handler_options[:unknown_user]
+      when 'accept'
+        @user = User.anonymous
+      when 'create'
+        @user = MailHandler.create_user_from_email(email)
+        if @user
+          logger.info "MailHandler: [#{@user.login}] account created" if logger && logger.info
+          Mailer.deliver_account_information(@user, @user.password)
+        else
+          logger.error "MailHandler: could not create account for [#{email.from.first}]" if logger && logger.error
+          return false
+        end
+      else
+        # Default behaviour, emails from unknown users are ignored
+        logger.info  "MailHandler: ignoring email from unknown user [#{email.from.first}]" if logger && logger.info
+        return false
+      end
+    end
     User.current = @user
     dispatch
   end
@@ -197,4 +216,23 @@
     @plain_text_body.strip!
     @plain_text_body
   end
+  
+  # Creates a user account for the +email+ sender
+  def self.create_user_from_email(email)
+    addr = email.from_addrs.to_a.first
+    if addr && !addr.spec.blank?
+      user = User.new
+      user.mail = addr.spec
+      
+      names = addr.name.blank? ? addr.spec.gsub(/@.*$/, '').split('.') : addr.name.split
+      user.firstname = names.shift
+      user.lastname = names.join(' ')
+      user.lastname = '-' if user.lastname.blank?
+      
+      user.login = user.mail
+      user.password = ActiveSupport::SecureRandom.hex(5)
+      user.language = Setting.default_language
+      user.save ? user : nil
+    end
+  end
 end
Index: extra/mail_handler/rdm-mailhandler.rb
===================================================================
--- extra/mail_handler/rdm-mailhandler.rb	(revision 2815)
+++ extra/mail_handler/rdm-mailhandler.rb	(working copy)
@@ -15,6 +15,11 @@
 #   -k, --key                      Redmine API key
 #   
 # General options:
+#       --unknown-user=ACTION      how to handle emails from an unknown user
+#                                  ACTION can be one of the following values:
+#                                  ignore: email is ignored (default)
+#                                  accept: accept as anonymous user
+#                                  create: create a user account
 #   -h, --help                     show this help
 #   -v, --verbose                  show extra information
 #   -V, --version                  show version information and exit
@@ -64,7 +69,7 @@
 class RedmineMailHandler
   VERSION = '0.1'
   
-  attr_accessor :verbose, :issue_attributes, :allow_override, :url, :key
+  attr_accessor :verbose, :issue_attributes, :allow_override, :uknown_user, :url, :key
 
   def initialize
     self.issue_attributes = {}
@@ -80,7 +85,8 @@
       [ '--tracker',        '-t', GetoptLong::REQUIRED_ARGUMENT],
       [ '--category',             GetoptLong::REQUIRED_ARGUMENT],
       [ '--priority',             GetoptLong::REQUIRED_ARGUMENT],
-      [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT]
+      [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT],
+      [ '--unknown-user',         GetoptLong::REQUIRED_ARGUMENT]
     )
 
     opts.each do |opt, arg|
@@ -99,6 +105,8 @@
         self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
       when '--allow-override'
         self.allow_override = arg.dup
+      when '--unknown-user'
+        self.unknown_user = arg.dup
       end
     end
     
@@ -108,7 +116,9 @@
   def submit(email)
     uri = url.gsub(%r{/*$}, '') + '/mail_handler'
     
-    data = { 'key' => key, 'email' => email, 'allow_override' => allow_override }
+    data = { 'key' => key, 'email' => email, 
+                           'allow_override' => allow_override,
+                           'unknown_user' => unknown_user }
     issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
              
     debug "Posting to #{uri}..."
Index: lib/tasks/email.rake
===================================================================
--- lib/tasks/email.rake	(revision 2815)
+++ lib/tasks/email.rake	(working copy)
@@ -21,6 +21,13 @@
     desc <<-END_DESC
 Read an email from standard input.
 
+General options:
+  unknown_user=ACTION      how to handle emails from an unknown user
+                           ACTION can be one of the following values:
+                           ignore: email is ignored (default)
+                           accept: accept as anonymous user
+                           create: create a user account
+  
 Issue attributes control options:
   project=PROJECT          identifier of the target project
   status=STATUS            name of the target status
@@ -47,6 +54,7 @@
       options = { :issue => {} }
       %w(project status tracker category priority).each { |a| options[:issue][a.to_sym] = ENV[a] if ENV[a] }
       options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
+      options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
       
       MailHandler.receive(STDIN.read, options)
     end
@@ -54,6 +62,13 @@
     desc <<-END_DESC
 Read emails from an IMAP server.
 
+General options:
+  unknown_user=ACTION      how to handle emails from an unknown user
+                           ACTION can be one of the following values:
+                           ignore: email is ignored (default)
+                           accept: accept as anonymous user
+                           create: create a user account
+  
 Available IMAP options:
   host=HOST                IMAP server host (default: 127.0.0.1)
   port=PORT                IMAP server port (default: 143)
@@ -61,7 +76,7 @@
   username=USERNAME        IMAP account
   password=PASSWORD        IMAP password
   folder=FOLDER            IMAP folder to read (default: INBOX)
-
+  
 Issue attributes control options:
   project=PROJECT          identifier of the target project
   status=STATUS            name of the target status
@@ -107,6 +122,7 @@
       options = { :issue => {} }
       %w(project status tracker category priority).each { |a| options[:issue][a.to_sym] = ENV[a] if ENV[a] }
       options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
+      options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
 
       Redmine::IMAP.check(imap_options, options)
     end

