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 »