Add customization options for enrollment and invitation e-mails

pull/3077/head
Marcelo Schmidt 10 years ago
parent 6a74bbd970
commit 89dfd3435e
No known key found for this signature in database
GPG Key ID: CA48C21A7B66097E
  1. 8
      packages/rocketchat-lib/i18n/en.i18n.json
  2. 20
      packages/rocketchat-lib/lib/placeholders.js
  3. 1
      packages/rocketchat-lib/package.js
  4. 30
      packages/rocketchat-lib/server/methods/insertOrUpdateUser.coffee
  5. 19
      packages/rocketchat-lib/server/methods/sendInvitationEmail.coffee
  6. 14
      packages/rocketchat-lib/server/startup/settings.coffee
  7. 17
      packages/rocketchat-ui-admin/admin/admin.coffee
  8. 32
      packages/rocketchat-ui-admin/admin/admin.html
  9. 31
      server/lib/accounts.coffee

@ -31,6 +31,8 @@
"Accounts_EmailVerification_Description" : "Make sure you have correct SMTP settings to use this feature",
"Accounts_Enrollment_Email" : "Enrollment Email",
"Accounts_Enrollment_Email_Description" : "You may use the following placeholders: <br /><ul><li>[name], [fname], [lname] for the user's full name, first name or last name, respectively.</li><li>[email] for the user's email.</li><li>[Site_Name] and [Site_URL] for the Application Name and URL respectively.</li></ul>",
"Accounts_Enrollment_Email_Default" : "<h2>Welcome to <h1>[Site_Name]</h1></h2><p>Go to [Site_URL] and try the best open source chat solution available today!</p>",
"Accounts_Enrollment_Email_Subject_Default" : "Welcome to [Site_Name]",
"Accounts_Iframe_api_method" : "Api Method",
"Accounts_Iframe_api_url" : "API URL",
"Accounts_iframe_enabled" : "Enabled",
@ -99,8 +101,9 @@
"Accounts_ShowFormLogin" : "Show form-based Login",
"Accounts_UseDefaultBlockedDomainsList" : "Use Default Blocked Domains List",
"Accounts_UseDNSDomainCheck" : "Use DNS Domain Check",
"Accounts_UserAddedEmail_Default" : "<h2>Welcome to <h1>[Site_Name]</h1></h2><p>Go to [Site_URL] and try the best open source chat solution available today!</p><p>You may login using your email: [email] and password: [password]. You may be required to change it after your first login.",
"Accounts_UserAddedEmail_Description" : "You may use the following placeholders: <br /><ul><li>[name], [fname], [lname] for the user's full name, first name or last name, respectively.</li><li>[email] for the user's email.</li><li>[password] for the user's password.</li><li>[Site_Name] and [Site_URL] for the Application Name and URL respectively.</li></ul>",
"Accounts_UserAddedEmail_Subject" : "User Added Welcome Email",
"Accounts_UserAddedEmailSubject_Default" : "Welcome to [Site_Name]",
"Activate" : "Activate",
"Activity" : "Activity",
"Add" : "Add",
@ -283,7 +286,9 @@
"Email_already_exists" : "Email already exists",
"Email_body" : "Email body",
"Email_Change_Disabled" : "Your Rocket.Chat administrator has disabled the changing of email",
"Email_Header_Description" : "You may use the following placeholders: <br /><ul><li>[Site_Name] and [Site_URL] for the Application Name and URL respectively.</li></ul>",
"Email_from" : "From",
"Email_Footer_Description" : "You may use the following placeholders: <br /><ul><li>[Site_Name] and [Site_URL] for the Application Name and URL respectively.</li></ul>",
"Email_Notification_Mode" : "Offline Email Notifications",
"Email_Notification_Mode_All" : "Every Mention/DM",
"Email_Notification_Mode_Disabled" : "Disabled",
@ -400,6 +405,7 @@
"Flags" : "Flags",
"Follow_social_profiles" : "Follow our social profiles, fork us on github and share your thoughts about the rocket.chat app on our trello board.",
"Food_and_Drink" : "Food & Drink",
"Footer" : "Footer",
"For_your_security_you_must_re_enter_your_password_to_continue" : "For your security, you must re-enter your password to continue",
"Force_SSL" : "Force SSL",
"Force_SSL_Description" : "*Caution!* _Force SSL_ should never be used with reverse proxy. If you have a reverse proxy, you should do the redirect THERE. This option exists for deployments like Heroku, that does not allow the redirect configuration at the reverse proxy.",

@ -0,0 +1,20 @@
RocketChat.placeholders = {};
RocketChat.placeholders.replace = function(str, data) {
if (!str) {
return "";
}
str = str.replace(/\[Site_Name\]/g, RocketChat.settings.get("Site_Name") || '');
str = str.replace(/\[Site_URL\]/g, RocketChat.settings.get("Site_Url") || '');
if (data) {
str = str.replace(/\[name\]/g, data.name || '');
str = str.replace(/\[fname\]/g, _.strLeft(data.name, ' ') || '');
str = str.replace(/\[lname\]/g, _.strRightBack(data.name, ' ') || '');
str = str.replace(/\[email\]/g, data.email || '');
str = str.replace(/\[password\]/g, data.password || '');
}
return str;
};

@ -45,6 +45,7 @@ Package.onUse(function(api) {
api.addFiles('lib/configLogger.coffee');
api.addFiles('lib/callbacks.coffee');
api.addFiles('lib/fileUploadRestrictions.js');
api.addFiles('lib/placeholders.js');
api.addFiles('lib/promises.coffee');
api.addFiles('lib/slashCommand.coffee');
api.addFiles('lib/Message.coffee');

@ -64,20 +64,30 @@ Meteor.methods
Meteor.call('joinDefaultChannels');
if userData.sendWelcomeEmail
html = RocketChat.settings.get('Accounts_UserAddedEmail');
html = html.replace /\[name\]/g, userData.name or ''
html = html.replace /\[fname\]/g, _.strLeft(userData.name, ' ') or ''
html = html.replace /\[lname\]/g, _.strRightBack(userData.name, ' ') or ''
html = html.replace /\[email\]/g, userData.email or ''
html = html.replace /\[password\]/g, userData.password or ''
html = html.replace /\[Site_Name\]/g, RocketChat.settings.get("Site_Name") or ''
html = html.replace /\[Site_URL\]/g, RocketChat.settings.get("Site_Url") or ''
header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || "")
footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || "")
if RocketChat.settings.get('Accounts_UserAddedEmail_Customized')
subject = RocketChat.settings.get('Accounts_UserAddedEmailSubject')
html = RocketChat.settings.get('Accounts_UserAddedEmail')
else
subject = TAPi18n.__('Accounts_UserAddedEmailSubject_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
html = TAPi18n.__('Accounts_UserAddedEmail_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
subject = RocketChat.placeholders.replace(subject);
html = RocketChat.placeholders.replace(html, {
name: userData.name,
email: userData.email,
password: userData.password
});
email = {
to: userData.email
from: RocketChat.settings.get('From_Email'),
subject: RocketChat.settings.get('Accounts_UserAddedEmail_Subject') || TAPi18n.__("Welcome_to_the", { lng: RocketChat.settings.get('Language') || "en" }) + (RocketChat.settings.get('Site_Name') || ""),
html: html
subject: subject,
html: header + html + footer
};
Email.send(email);

@ -9,14 +9,27 @@ Meteor.methods
rfcMailPattern = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
validEmails = _.compact _.map emails, (email) -> return email if rfcMailPattern.test email
header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || "")
footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || "")
if RocketChat.settings.get('Invitation_Customized')
subject = RocketChat.settings.get('Invitation_Subject')
html = RocketChat.settings.get('Invitation_HTML')
else
subject = TAPi18n.__('Invitation_Subject_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
html = TAPi18n.__('Invitation_HTML_Default', { lng: Meteor.user()?.language || RocketChat.settings.get('language') || 'en' })
subject = RocketChat.placeholders.replace(subject);
for email in validEmails
@unblock()
html = RocketChat.placeholders.replace(html, { email: email });
Email.send
to: email
from: RocketChat.settings.get 'From_Email'
subject: RocketChat.settings.get 'Invitation_Subject'
html: RocketChat.settings.get 'Invitation_HTML'
subject: subject
html: header + html + footer
return validEmails

@ -105,6 +105,10 @@ RocketChat.settings.addGroup 'General', ->
RocketChat.settings.addGroup 'Email', ->
@section 'Header and Footer', ->
@add 'Email_Header', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Header' }
@add 'Email_Footer', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Footer' }
@section 'SMTP', ->
@add 'SMTP_Host', '', { type: 'string', env: true, i18nLabel: 'Host' }
@add 'SMTP_Port', '', { type: 'string', env: true, i18nLabel: 'Port' }
@ -119,12 +123,14 @@ RocketChat.settings.addGroup 'Email', ->
@add 'Invitation_HTML', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Invitation_HTML_Description', enableQuery: { _id: 'Invitation_Customized', value: true }, i18nDefaultQuery: { _id: 'Invitation_Customized', value: false } }
@section 'Registration', ->
@add 'Accounts_Enrollment_Email_Subject', '', { type: 'string', i18nLabel: 'Subject' }
@add 'Accounts_Enrollment_Email', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Accounts_Enrollment_Email_Description' }
@add 'Accounts_Enrollment_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
@add 'Accounts_Enrollment_Email_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Accounts_Enrollment_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_Enrollment_Customized', value: false } }
@add 'Accounts_Enrollment_Email', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', enableQuery: { _id: 'Accounts_Enrollment_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_Enrollment_Customized', value: false } }
@section 'Registration via Admin', ->
@add 'Accounts_UserAddedEmailSubject', '', { type: 'string', i18nLabel: "Subject" }
@add 'Accounts_UserAddedEmail', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Accounts_UserAddedEmail_Description' }
@add 'Accounts_UserAddedEmail_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
@add 'Accounts_UserAddedEmailSubject', '', { type: 'string', i18nLabel: "Subject", enableQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: false } }
@add 'Accounts_UserAddedEmail', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Accounts_UserAddedEmail_Description', enableQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: true }, i18nDefaultQuery: { _id: 'Accounts_UserAddedEmail_Customized', value: false } }
RocketChat.settings.addGroup 'Message', ->

@ -52,14 +52,7 @@ Template.admin.helpers
found = 0
for item in i18nDefaultQuery
if TempSettings.findOne(item)?
if setting.type is 'code'
codeMirrorBox = $('.code-mirror-box[data-editor-id="'+setting._id+'"]')
codeMirrorBox.find('.CodeMirror')[0].CodeMirror.doc.setValue(TAPi18n.__(setting._id + '_Default'))
else
setting.value = TAPi18n.__(setting._id + '_Default')
# else if setting.type is 'code'
# codeMirrorBox = $('.code-mirror-box[data-editor-id="'+setting._id+'"]')
# codeMirrorBox.find('.CodeMirror')[0].CodeMirror.doc.setValue(setting.value)
setting.value = TAPi18n.__(setting._id + '_Default')
sections[setting.section or ''] ?= []
sections[setting.section or ''].push setting
@ -72,6 +65,9 @@ Template.admin.helpers
return sectionsArray
i18nDefaultValue: ->
return TAPi18n.__(@_id + '_Default')
isDisabled: ->
if @blocked
return { disabled: 'disabled' }
@ -154,7 +150,7 @@ Template.admin.helpers
random: ->
return Random.id()
getEditorOptions: ->
getEditorOptions: (readOnly = false) ->
return {} =
lineNumbers: true
mode: this.code or "javascript"
@ -168,6 +164,7 @@ Template.admin.helpers
matchTags: true,
showTrailingSpace: true
highlightSelectionMatches: true
readOnly: readOnly
setEditorOnBlur: (_id) ->
Meteor.defer ->
@ -302,7 +299,7 @@ Template.admin.events
"click .expand": (e) ->
$(e.currentTarget).closest('.section').removeClass('section-collapsed')
$(e.currentTarget).closest('button').removeClass('expand').addClass('collapse').find('span').text(TAPi18n.__ "Collapse")
$('.code-mirror-box .CodeMirror').each (index, codeMirror) ->
$('.CodeMirror').each (index, codeMirror) ->
codeMirror.CodeMirror.refresh()
"click .collapse": (e) ->

@ -91,21 +91,25 @@
{{/if}}
{{#if $eq type 'code'}}
<div class="code-mirror-box" data-editor-id="{{_id}}" {{isDisabled}}>
<div class="title">
{{label}}
</div>
{{> CodeMirror name=_id options=getEditorOptions code=value }}
{{setEditorOnBlur _id}}
<div class="buttons">
<button class="button button-primary button-fullscreen">
Full Screen
</button>
<button class="button button-primary button-restore">
Exit Full Screen
</button>
{{#if isDisabled.disabled}}
{{> CodeMirror name=_id options=(getEditorOptions true) code=(i18nDefaultValue) }}
{{else}}
<div class="code-mirror-box" data-editor-id="{{_id}}">
<div class="title">
{{label}}
</div>
{{> CodeMirror name=_id options=getEditorOptions code=value }}
{{setEditorOnBlur _id}}
<div class="buttons">
<button class="button button-primary button-fullscreen">
Full Screen
</button>
<button class="button button-primary button-restore">
Exit Full Screen
</button>
</div>
</div>
</div>
{{/if}}
{{/if}}
{{#if $eq type 'action'}}

@ -30,20 +30,27 @@ Accounts.emailTemplates.resetPassword.text = (user, url) ->
url = url.replace /\/#\//, '/'
resetPasswordText user, url
if RocketChat.settings.get 'Accounts_Enrollment_Email_Subject'
Accounts.emailTemplates.enrollAccount.subject = (user) ->
Accounts.emailTemplates.enrollAccount.subject = (user) ->
if RocketChat.settings.get 'Accounts_Enrollment_Customized'
return RocketChat.settings.get 'Accounts_Enrollment_Email_Subject'
else
return TAPi18n.__('Accounts_Enrollment_Email_Subject_Default', { lng: user?.language || RocketChat.settings.get('language') || 'en' })
if RocketChat.settings.get 'Accounts_Enrollment_Email'
Accounts.emailTemplates.enrollAccount.text = (user, url) ->
text = RocketChat.settings.get 'Accounts_Enrollment_Email'
text = text.replace /\[name\]/g, user.name or ''
text = text.replace /\[fname\]/g, _.strLeft(user.name, ' ') or ''
text = text.replace /\[lname\]/g, _.strRightBack(user.name, ' ') or ''
text = text.replace /\[email\]/g, user.emails?[0]?.address or ''
text = text.replace /\[Site_Name\]/g, RocketChat.settings.get("Site_Name") or ''
text = text.replace /\[Site_URL\]/g, RocketChat.settings.get("Site_Url") or ''
return text
Accounts.emailTemplates.enrollAccount.text = (user, url) ->
if RocketChat.settings.get 'Accounts_Enrollment_Customized'
html = RocketChat.settings.get 'Accounts_Enrollment_Email'
else
html = TAPi18n.__('Accounts_Enrollment_Email_Default', { lng: user?.language || RocketChat.settings.get('language') || 'en' })
header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || "")
footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || "")
html = RocketChat.placeholders.replace(html, {
name: user.name,
email: user.emails?[0]?.address
});
return header + html + footer;
Accounts.onCreateUser (options, user) ->
# console.log 'onCreateUser ->',JSON.stringify arguments, null, ' '

Loading…
Cancel
Save