Skip to content

Commit

Permalink
Merge pull request #3077 from RocketChat/i18n-default-query
Browse files Browse the repository at this point in the history
Add e-mail template options
  • Loading branch information
engelgabriel committed Apr 29, 2016
2 parents 453ad60 + 6e3c5e6 commit d5c7766
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 66 deletions.
14 changes: 11 additions & 3 deletions packages/rocketchat-lib/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -98,8 +100,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",
Expand Down Expand Up @@ -232,6 +235,7 @@
"Created_at" : "Created at",
"Created_at_s_by_s" : "Created at <strong>%s</strong> by <strong>%s</strong>",
"Current_Chats" : "Current Chats",
"Custom" : "Custom",
"Custom_Fields" : "Custom Fields",
"Custom_oauth_helper" : "When setting up your OAuth Provider, you'll have to inform a Callback URL. Use <pre>%s</pre> .",
"Custom_oauth_unique_name" : "Custom oauth unique name",
Expand Down Expand Up @@ -278,7 +282,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",
Expand Down Expand Up @@ -392,6 +398,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.",
Expand Down Expand Up @@ -473,8 +480,9 @@
"Invisible" : "Invisible",
"Invitation_HTML" : "Invitation HTML",
"Invitation_HTML_Description" : "You may use the following placeholders: <br /><ul><li>[email] for the recipient email.</li><li>[Site_Name] and [Site_URL] for the Application Name and URL respectively.</li></ul>",
"Invitation_HTML_Template" : "<h2>You have been invited to <h1>[Site_Name]</h1></h2><p>Go to [Site_URL] and try the best open source chat solution available today!</p>",
"Invitation_HTML_Default" : "<h2>You have been invited to <h1>[Site_Name]</h1></h2><p>Go to [Site_URL] and try the best open source chat solution available today!</p>",
"Invitation_Subject" : "Invitation Subject",
"Invitation_Subject_Default" : "You have been invited to [Site_Name]",
"Invite_user_to_join_channel" : "Invite one user to join this channel",
"Invite_Users" : "Invite Users",
"is_also_typing" : "is also typing",
Expand Down Expand Up @@ -1123,4 +1131,4 @@
"Your_Open_Source_solution" : "Your own Open Source chat solution",
"Your_password_is_wrong" : "Your password is wrong!",
"Your_push_was_sent_to_s_devices" : "Your push was sent to %s devices"
}
}
27 changes: 27 additions & 0 deletions packages/rocketchat-lib/lib/placeholders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
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 || '');

if (data.unsubscribe) {
str = str.replace(/\[unsubscribe\]/g, data.unsubscribe);
}
}

str = str.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br>' + '$2');


return str;
};
1 change: 1 addition & 0 deletions packages/rocketchat-lib/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
3 changes: 3 additions & 0 deletions packages/rocketchat-lib/server/functions/settings.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ RocketChat.settings.add = (_id, value, options = {}) ->
if options.enableQuery?
options.enableQuery = JSON.stringify options.enableQuery

if options.i18nDefaultQuery?
options.i18nDefaultQuery = JSON.stringify options.i18nDefaultQuery

if process?.env?[_id]?
value = process.env[_id]
if value.toLowerCase() is "true"
Expand Down
30 changes: 20 additions & 10 deletions packages/rocketchat-lib/server/methods/insertOrUpdateUser.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
19 changes: 16 additions & 3 deletions packages/rocketchat-lib/server/methods/sendInvitationEmail.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 13 additions & 6 deletions packages/rocketchat-lib/server/startup/settings.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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' }
Expand All @@ -114,16 +118,19 @@ RocketChat.settings.addGroup 'Email', ->
@add 'SMTP_Test_Button', 'sendSMTPTestEmail', { type: 'action', actionText: 'Send_a_test_mail_to_my_user' }

@section 'Invitation', ->
@add 'Invitation_Subject', 'You have been invited to Rocket.Chat', { type: 'string', i18nLabel: 'Subject' }
@add 'Invitation_HTML', '', { type: 'code', code: 'text/html', multiline: true, i18nLabel: 'Body', i18nDescription: 'Invitation_HTML_Description' }
@add 'Invitation_Customized', false, { type: 'boolean', i18nLabel: 'Custom' }
@add 'Invitation_Subject', '', { type: 'string', i18nLabel: 'Subject', enableQuery: { _id: 'Invitation_Customized', value: true }, i18nDefaultQuery: { _id: 'Invitation_Customized', value: false } }
@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', ->
Expand Down
26 changes: 10 additions & 16 deletions packages/rocketchat-mailer/server/functions/sendMail.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,11 @@ Mailer.sendMail = (from, subject, body, dryrun, query) ->
# Meteor.users.find({ "username": /\.rocket\.team/ }).forEach (user) ->
email = user.emails?[0]?.address

html = body.replace /\[unsubscribe\]/g, Meteor.absoluteUrl(FlowRouter.path('mailer/unsubscribe/:_id/:createdAt', { _id: user._id, createdAt: user.createdAt.getTime() }))
html = html.replace /\[name\]/g, user.name
fname = _.strLeft user.name, ' '
lname = _.strRightBack user.name, ' '
html = html.replace /\[fname\]/g, fname
html = html.replace /\[lname\]/g, lname
html = html.replace /\[email\]/g, email
html = html.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br>' + '$2')
html = RocketChat.placeholders.replace(body, {
unsubscribe: Meteor.absoluteUrl(FlowRouter.path('mailer/unsubscribe/:_id/:createdAt', { _id: user._id, createdAt: user.createdAt.getTime() })),
name: user.name,
email: email
});

email = "#{user.name} <#{email}>"

Expand All @@ -44,14 +41,11 @@ Mailer.sendMail = (from, subject, body, dryrun, query) ->
# Meteor.users.find({ "username": /\.rocket\.team/ }).forEach (user) ->
email = user.emails?[0]?.address

html = body.replace /\[unsubscribe\]/g, Meteor.absoluteUrl(FlowRouter.path('mailer/unsubscribe/:_id/:createdAt', { _id: user._id, createdAt: user.createdAt.getTime() }))
html = html.replace /\[name\]/g, user.name
fname = _.strLeft user.name, ' '
lname = _.strRightBack user.name, ' '
html = html.replace /\[fname\]/g, fname
html = html.replace /\[lname\]/g, lname
html = html.replace /\[email\]/g, email
html = html.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br>' + '$2')
html = RocketChat.placeholders.replace(body, {
unsubscribe: Meteor.absoluteUrl(FlowRouter.path('mailer/unsubscribe/:_id/:createdAt', { _id: user._id, createdAt: user.createdAt.getTime() })),
name: user.name,
email: email
});

email = "#{user.name} <#{email}>"

Expand Down
22 changes: 20 additions & 2 deletions packages/rocketchat-ui-admin/admin/admin.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ Template.admin.helpers

sections = {}
for setting in settings
if setting.i18nDefaultQuery?
if _.isString(setting.i18nDefaultQuery)
i18nDefaultQuery = JSON.parse(setting.i18nDefaultQuery)
else
i18nDefaultQuery = setting.i18nDefaultQuery

if not _.isArray(i18nDefaultQuery)
i18nDefaultQuery = [i18nDefaultQuery]

found = 0
for item in i18nDefaultQuery
if TempSettings.findOne(item)?
setting.value = TAPi18n.__(setting._id + '_Default')

sections[setting.section or ''] ?= []
sections[setting.section or ''].push setting

Expand All @@ -51,6 +65,9 @@ Template.admin.helpers

return sectionsArray

i18nDefaultValue: ->
return TAPi18n.__(@_id + '_Default')

isDisabled: ->
if @blocked
return { disabled: 'disabled' }
Expand Down Expand Up @@ -133,7 +150,7 @@ Template.admin.helpers
random: ->
return Random.id()

getEditorOptions: ->
getEditorOptions: (readOnly = false) ->
return {} =
lineNumbers: true
mode: this.code or "javascript"
Expand All @@ -147,6 +164,7 @@ Template.admin.helpers
matchTags: true,
showTrailingSpace: true
highlightSelectionMatches: true
readOnly: readOnly

setEditorOnBlur: (_id) ->
Meteor.defer ->
Expand Down Expand Up @@ -281,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) ->
Expand Down
32 changes: 18 additions & 14 deletions packages/rocketchat-ui-admin/admin/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,25 @@ <h2>
{{/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'}}
Expand Down
Loading

0 comments on commit d5c7766

Please sign in to comment.