Project

General

Profile

Feature #3003 » create-users-from-emails.patch

Tero Tilus, 2009-05-14 14:35

View differences:

app/controllers/settings_controller.rb
40 40
    @options[:user_format] = User::USER_FORMATS.keys.collect {|f| [User.current.name(f), f.to_s] }
41 41
    @deliveries = ActionMailer::Base.perform_deliveries
42 42

  
43
    @users = User.active.find(:all, :order => :login)
44
    @roles = Role.find(:all, :order => :name)
45

  
43 46
    @guessed_host_and_path = request.host_with_port.dup
44 47
    @guessed_host_and_path << ('/'+ Redmine::Utils.relative_url_root.gsub(%r{^\/}, '')) unless Redmine::Utils.relative_url_root.blank?
45 48
  end
app/models/mail_handler.rb
33 33
    # Project needs to be overridable if not specified
34 34
    @@handler_options[:allow_override] << 'project' unless @@handler_options[:issue].has_key?(:project)
35 35
    # Status overridable by default
36
    @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)    
36
    @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
37 37
    super email
38 38
  end
39 39
  
......
41 41
  def receive(email)
42 42
    @email = email
43 43
    @user = User.active.find_by_mail(email.from.to_a.first.to_s.strip)
44
    unless @user
45
      # Unknown user => the email is ignored
46
      # TODO: ability to create the user's account
47
      logger.info "MailHandler: email submitted by unknown user [#{email.from.first}]" if logger && logger.info
48
      return false
44
    unless @user # create user
45
      if Setting.mail_handler_create_users_from_incoming_mails.to_i != 0 # creates a user and assigns him to a project
46
        @user = create_user(email)
47
        return false unless @user
48
        return false unless create_role(@user)
49
      elsif Setting.mail_handler_assign_unknown_addresses_to_user.to_i != 0 # use default users, needs :add_issue right on project
50
        unless @user = User.find_by_id(Setting.mail_handler_assign_unknown_addresses_to_user.to_i)
51
          logger.info "MailHandler: could not find User with id [#{Setting.mail_handler_assign_unknown_addresses_to_user.to_i}] to assign sender #{email.from.first}" if logger && loggger.info
52
          return false
53
        end
54
      else
55
        # unknown user and no values specified to handle unknown mails
56
        logger.info "MailHandler: email submitted by unknown user [#{email.from.first}] (change Settings in incoming E-Mail tab for default behaviour)" if logger && logger.info
57
        return false
58
      end
49 59
    end
50 60
    User.current = @user
51 61
    dispatch
52 62
  end
53
  
63

  
64

  
65
  protected
66
  def target_project
67
    # TODO: other ways to specify project:
68
    # * parse the email To field
69
    # * specific project (eg. Setting.mail_handler_target_project)
70
    target = Project.find_by_identifier(get_keyword(:project))
71
    raise MissingInformation.new('Unable to determine target project') if target.nil?
72
    target
73
  end
74

  
75
  # creates a user from email address and sets the status depending on the configured actions
76
  def create_user(email)
77
    new_user = User.new
78
    from_addr = email.header['from'].addrs.first
79
    new_user.mail = from_addr.address
80
    new_user.admin = false
81
    email_user_name = from_addr.local
82
    new_user.login = if !User.find_by_login(email_user_name) # set login to the email address without domain or if it exists to the full email
83
      email_user_name
84
    else
85
      new_user.mail
86
    end
87
    new_user.status = User::STATUS_REGISTERED
88
    if from_addr.name
89
      names = from_addr.name.split(' ')
90
    else
91
      names = email_user_name.split('.').map(&:capitalize)
92
    end
93
    new_user.lastname = names.pop
94
    new_user.firstname = names.join(' ')
95
    password = Token.generate_token_value(8)
96
    new_user.password = password
97
    new_user.password_confirmation = password
98

  
99
    case Setting.mail_handler_create_users_from_incoming_mails
100
    when '1' || '2'
101
      token = Token.new(:user => new_user, :action => "register")
102
      Mailer.deliver_register(token) if new_user.save and token.save
103
      Mailer.deliver_account_information(new_user, password)
104
    when '3'
105
      new_user.status = User::STATUS_ACTIVE
106
      new_user.last_login_on = Time.now
107
      if new_user.save
108
        Mailer.deliver_account_information(new_user, password, :notice_account_register_done)
109
      else
110
        logger.info "could not create user #{new_user}" if logger and logger.info
111
        return false
112
      end
113
    else
114
      Mailer.deliver_account_activation_request(new_user)
115
      Mailer.deliver_account_information(new_user, password, :notice_account_pending)
116
    end
117
    return new_user
118
  end
119

  
120
  # creates a member on the target_project for the given user with the configured role
121
  def create_role(user)
122
    # Roles need right for add_issue
123
    if Setting.mail_handler_role_to_add_users_to_project.to_i != 0
124
      if r = Role.find_by_id(Setting.mail_handler_role_to_add_users_to_project.to_i)
125
        member = Member.new(
126
          :user_id => user.id,
127
          :project_id => self.target_project.id
128
        )
129
        member.roles << r
130
        unless member.save
131
          logger.info "could not create Role for user #{user.login} and project #{self.target_project.name}" if logger and logger.info
132
          return false
133
        end
134
      else
135
        logger.info "could not assing #{user} to #{self.target_project.name}, missing Role id: #{Setting.mail_handler_role_to_add_users_to_project}" if logger and logger.info
136
        return false
137
      end
138
    end
139
    return true
140
  end
141

  
54 142
  private
55 143

  
56 144
  MESSAGE_ID_RE = %r{^<redmine\.([a-z0-9_]+)\-(\d+)\.\d+@}
......
94 182
    priority = (get_keyword(:priority) && Enumeration.find_by_opt_and_name('IPRI', get_keyword(:priority)))
95 183
    status =  (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status)))
96 184

  
97
    # check permission
185
    # check permissions
98 186
    raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
99 187
    issue = Issue.new(:author => user, :project => project, :tracker => tracker, :category => category, :priority => priority)
100 188
    # check workflow
......
117 205
    logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
118 206
    issue
119 207
  end
120
  
121
  def target_project
122
    # TODO: other ways to specify project:
123
    # * parse the email To field
124
    # * specific project (eg. Setting.mail_handler_target_project)
125
    target = Project.find_by_identifier(get_keyword(:project))
126
    raise MissingInformation.new('Unable to determine target project') if target.nil?
127
    target
128
  end
129
  
208

  
130 209
  # Adds a note to an existing issue
131 210
  def receive_issue_reply(issue_id)
132 211
    status =  (get_keyword(:status) && IssueStatus.find_by_name(get_keyword(:status)))
......
164 243
      message = message.root
165 244
      if user.allowed_to?(:add_messages, message.project) && !message.locked?
166 245
        reply = Message.new(:subject => email.subject.gsub(%r{^.*msg\d+\]}, '').strip,
167
                            :content => plain_text_body)
246
          :content => plain_text_body)
168 247
        reply.author = user
169 248
        reply.board = message.board
170 249
        message.children << reply
......
180 259
    if email.has_attachments?
181 260
      email.attachments.each do |attachment|
182 261
        Attachment.create(:container => obj,
183
                          :file => attachment,
184
                          :author => user,
185
                          :content_type => attachment.content_type)
262
          :file => attachment,
263
          :author => user,
264
          :content_type => attachment.content_type)
186 265
      end
187 266
    end
188 267
  end
app/models/mailer.rb
158 158
  # Example:
159 159
  #   account_information(user, password) => tmail object
160 160
  #   Mailer.deliver_account_information(user, password) => sends account information to the user
161
  def account_information(user, password)
161
  def account_information(user, password, information = '')
162 162
    set_language_if_valid user.language
163 163
    recipients user.mail
164 164
    subject l(:mail_subject_register, Setting.app_title)
165 165
    body :user => user,
166 166
         :password => password,
167
         :information => information,
167 168
         :login_url => url_for(:controller => 'account', :action => 'login')
168 169
  end
169 170

  
app/models/token.rb
36 36
  end
37 37
  
38 38
private
39
  def self.generate_token_value
40
    ActiveSupport::SecureRandom.hex(20)
39
  def self.generate_token_value(length = 40)
40
    ActiveSupport::SecureRandom.hex(length)
41 41
  end
42 42
end
app/views/mailer/account_information.text.html.rhtml
1 1
<% if @user.auth_source %>
2
<p><%= l(:mail_body_account_information_external, @user.auth_source.name) %></p>
2
  <p><%= l(:mail_body_account_information_external, @user.auth_source.name) %></p>
3 3
<% else %>
4
<p><%= l(:mail_body_account_information) %>:</p>
5
<ul>
4
  <p><%= l(:mail_body_account_information) %>:</p>
5
  <ul>
6 6
    <li><%= l(:field_login) %>: <%= @user.login %></li>
7 7
    <li><%= l(:field_password) %>: <%= @password %></li>
8
</ul>
8
  </ul>
9 9
<% end %>
10 10

  
11
<% if @information -%>
12
  <p><%= l(@information) %></p>
13
<% end -%>
14

  
11 15
<p><%= l(:label_login) %>: <%= auto_link(@login_url) %></p>
app/views/mailer/account_information.text.plain.rhtml
3 3
* <%= l(:field_login) %>: <%= @user.login %>
4 4
* <%= l(:field_password) %>: <%= @password %>
5 5
<% end %>
6
<% if @information -%>
7
  <%= l(@information) %>
8
<% end -%>
6 9
<%= l(:label_login) %>: <%= @login_url %>
app/views/settings/_mail_handler.rhtml
1 1
<% form_tag({:action => 'edit', :tab => 'mail_handler'}) do %>
2 2

  
3
<div class="box tabular settings">
4
<p><label><%= l(:setting_mail_handler_api_enabled) %></label>
5
<%= check_box_tag 'settings[mail_handler_api_enabled]', 1, Setting.mail_handler_api_enabled?,
6
                  :onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }" %>
7
<%= hidden_field_tag 'settings[mail_handler_api_enabled]', 0 %></p>
3
  <div class="box tabular settings">
4
    <p><label><%= l(:setting_mail_handler_api_enabled) %></label>
5
      <%= check_box_tag 'settings[mail_handler_api_enabled]', 1, Setting.mail_handler_api_enabled?,
6
        :onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }" %>
7
      <%= hidden_field_tag 'settings[mail_handler_api_enabled]', 0 %></p>
8 8

  
9
<p><label><%= l(:setting_mail_handler_api_key) %></label>
10
<%= text_field_tag 'settings[mail_handler_api_key]', Setting.mail_handler_api_key, 
11
                                                     :size => 30,
12
                                                     :id => 'settings_mail_handler_api_key',
13
                                                     :disabled => !Setting.mail_handler_api_enabled? %>
14
<%= link_to_function l(:label_generate_key), "if ($('settings_mail_handler_api_key').disabled == false) { $('settings_mail_handler_api_key').value = randomKey(20) }" %></p>
15
</div>
9
    <p><label><%= l(:setting_mail_handler_api_key) %></label>
10
      <%= text_field_tag 'settings[mail_handler_api_key]', Setting.mail_handler_api_key,
11
        :size => 30,
12
        :id => 'settings_mail_handler_api_key',
13
        :disabled => !Setting.mail_handler_api_enabled? %>
14
      <%= link_to_function l(:label_generate_key), "if ($('settings_mail_handler_api_key').disabled == false) { $('settings_mail_handler_api_key').value = randomKey(20) }" %></p>
16 15

  
17
<%= submit_tag l(:button_save) %>
16
    <p>
17
      <label><%= l(:setting_mail_handler_create_users_from_incoming_mails) %></label>
18
      <%= select_tag 'settings[mail_handler_create_users_from_incoming_mails]',
19
        options_for_select( [[l(:label_disabled), "0"],
20
          [l(:label_registration_activation_by_email), "1"],
21
          [l(:label_registration_manual_activation), "2"],
22
          [l(:label_registration_automatic_activation), "3"]
23
        ], Setting.mail_handler_create_users_from_incoming_mails ),
24
        :onChange => "if (this.options[this.selectedIndex].value == \"0\") { Form.Element.enable('settings_mail_handler_assign_unknown_addresses_to_user'); } else { Form.Element.disable('settings_mail_handler_assign_unknown_addresses_to_user'); }"
25
    %>
26
    </p>
27

  
28
    <p>
29
      <label><%= l(:setting_mail_handler_role_to_add_users_to_project) %></label>
30
      <%= select(:settings, :mail_handler_role_to_add_users_to_project, @roles.collect {|p| [ p.name, p.id ] },
31
        { :include_blank => true, :selected => Setting.mail_handler_role_to_add_users_to_project.to_i }
32
      ) %>
33
    </p>
34

  
35
  
36
    <p>
37
      <label><%= l(:setting_mail_handler_assign_unknown_addresses_to_user) %></label>
38
      <%= select(:settings, :mail_handler_assign_unknown_addresses_to_user, @users.collect {|p| [ p.login, p.id ] },
39
        { :include_blank => true, :selected => Setting.mail_handler_assign_unknown_addresses_to_user.to_i },
40
        { :disabled => Setting.mail_handler_create_users_from_incoming_mails.to_i == 0}
41
      ) %>
42
    </p>
43

  
44
  </div>
45

  
46
  <%= submit_tag l(:button_save) %>
18 47
<% end %>
config/locales/de.yml
304 304
  setting_enabled_scm: Aktivierte Versionskontrollsysteme
305 305
  setting_mail_handler_api_enabled: Abruf eingehender E-Mails aktivieren
306 306
  setting_mail_handler_api_key: API-Schlüssel
307
  setting_mail_handler_create_users_from_incoming_mails: Erstelle Benutzer aus eingehenden E-Mails
308
  setting_mail_handler_assign_unknown_addresses_to_user: Unbekannte Absender folgendem Benutzer zuordnen
309
  setting_mail_handler_role_to_add_users_to_project: Rolle für neue Benutzer
307 310
  setting_sequential_project_identifiers: Fortlaufende Projektkennungen generieren
308 311
  setting_gravatar_enabled: Gravatar Benutzerbilder benutzen
309 312
  setting_diff_max_lines_displayed: Maximale Anzahl anzuzeigender Diff-Zeilen
config/locales/en.yml
280 280
  setting_enabled_scm: Enabled SCM
281 281
  setting_mail_handler_api_enabled: Enable WS for incoming emails
282 282
  setting_mail_handler_api_key: API key
283
  setting_mail_handler_create_users_from_incoming_mails: Create users from incoming E-Mails
284
  setting_mail_handler_assign_unknown_addresses_to_user: Assign Unknown addresses to the following User
285
  setting_mail_handler_role_to_add_users_to_project: Role for new Users
283 286
  setting_sequential_project_identifiers: Generate sequential project identifiers
284 287
  setting_gravatar_enabled: Use Gravatar user icons
285 288
  setting_diff_max_lines_displayed: Max number of diff lines displayed
config/locales/fi.yml
743 743
  label_generate_key: Luo avain
744 744
  setting_mail_handler_api_enabled: Ota käyttöön WS saapuville sähköposteille
745 745
  setting_mail_handler_api_key: API avain
746
  setting_mail_handler_create_users_from_incoming_mails: Luo automaattisesti uusia käyttäjiä saapuvien sähköpostien perusteella
747
  setting_mail_handler_assign_unknown_addresses_to_user: Nimeä tuntemattomasta sähköpostiosoitteesta tulleesta viestistä luodut tehtävät seuraavalle käyttäjälle
748
  setting_mail_handler_role_to_add_users_to_project: Uusien käyttäjien rooli
746 749
  text_email_delivery_not_configured: "Sähköpostin jakelu ei ole määritelty ja sähköpostimuistutukset eivät ole käytössä.\nKonfiguroi sähköpostipalvelinasetukset (SMTP) config/email.yml tiedostosta ja uudelleenkäynnistä sovellus jotta asetukset astuvat voimaan."
747 750
  field_parent_title: Aloitussivu
748 751
  label_issue_watchers: Tapahtuman seuraajat
config/settings.yml
117 117
mail_handler_api_enabled:
118 118
  default: 0
119 119
mail_handler_api_key:
120
  default: 
120
  default:
121
mail_handler_create_users_from_incoming_mails:
122
  default: 0
123
mail_handler_assign_unknown_addresses_to_user:
124
  default: 0
125
mail_handler_role_to_add_users_to_project:
126
  default: 0
121 127
issue_list_default_columns:
122 128
  serialized: true
123 129
  default: 
test/unit/mail_handler_test.rb
33 33
                   :custom_fields,
34 34
                   :custom_fields_trackers,
35 35
                   :boards,
36
                   :messages
36
                   :messages,
37
                   :settings
37 38
  
38 39
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
39 40
  
......
197 198
    assert_equal 'This is a html-only email.', issue.description
198 199
  end
199 200

  
201
  def test_should_create_new_user_and_assign_to_project
202
    issue = submit_email('ticket_with_new_user.eml')
203
    assert issue.is_a?(Issue)
204
    assert !issue.new_record?
205
    assert_equal issue.subject, 'New ticker from new user'
206
    assert_equal 'onlinestore', issue.project.name.downcase
207
    assert_equal 'jjins', issue.author.login
208
    assert_equal 'jjins@somenet.foo', issue.author.mail
209
    creator = User.find_by_login('jjins')
210
    assert_not_nil creator
211
    member = Member.find(:first, :conditions => {:project_id => issue.project.id, :user_id => creator.id})
212
    assert_not_nil member
213
    assert_equal 'Reporter', member.role.name
214
  end
215

  
200 216
  private
201 217
  
202 218
  def submit_email(filename, options={})
(4-4/4)