Feature #3003 » create-users-from-emails.patch
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={}) |
- « Previous
- 1
- 2
- 3
- 4
- Next »