Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/rotten-foxes-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/i18n': patch
'@rocket.chat/meteor': patch
---

Fixes email notifications to display all files when a message contains multiple attachments
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
AtLeast,
FilesAndAttachments,
IMessage,
FileProp,
} from '@rocket.chat/core-typings';
import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Uploads, Users } from '@rocket.chat/models';
Expand Down Expand Up @@ -42,13 +43,14 @@ export const parseFileIntoMessageAttachments = async (

const attachments: MessageAttachment[] = [];

const files = [
const files: FileProp[] = [
{
_id: file._id,
name: file.name || '',
type: file.type || 'file',
size: file.size || 0,
format: file.identify?.format || '',
typeGroup: file.typeGroup,
},
];

Expand Down Expand Up @@ -96,6 +98,7 @@ export const parseFileIntoMessageAttachments = async (
type: thumbnail.type || 'file',
size: thumbnail.size || 0,
format: thumbnail.identify?.format || '',
typeGroup: thumbnail.typeGroup || '',
});
}
} catch (e) {
Expand Down
74 changes: 43 additions & 31 deletions apps/meteor/app/lib/server/functions/notifications/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,55 +29,67 @@ export async function getEmailContent({ message, user, room }) {

const roomDirectives = roomCoordinator.getRoomDirectives(room.t);

const header = i18n.t(!roomDirectives.isGroupChat(room) ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', {
username: userName,
channel: roomName,
lng,
});
const files = (message.files || [message.file]).filter((file) => file && file.typeGroup !== 'thumb');
const hasFiles = files.length > 0;
const hasText = typeof message.msg === 'string' && message.msg.trim() !== '';
const isGroupChat = roomDirectives.isGroupChat(room);

let header;
if (hasFiles && !hasText) {
// file-only message
const isMultipleFiles = files.length > 1;
let headerKey;
if (isGroupChat) {
headerKey = isMultipleFiles ? 'User_uploaded_files_on_channel' : 'User_uploaded_a_file_on_channel';
} else {
headerKey = isMultipleFiles ? 'User_uploaded_files_to_you' : 'User_uploaded_a_file_to_you';
}
header = i18n.t(headerKey, { username: userName, channel: roomName, count: files.length, lng });
} else {
// text message (with or without files)
header = i18n.t(!isGroupChat ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', {
username: userName,
channel: roomName,
lng,
});
}

if (message.t === 'e2e' && !message.file) {
if (message.t === 'e2e' && !message.file && !message.files?.length) {
return settings.get('Email_notification_show_message') ? i18n.t('Encrypted_message_preview_unavailable', { lng }) : header;
}

if (message.msg !== '') {
if (!settings.get('Email_notification_show_message')) {
return header;
}
if (!settings.get('Email_notification_show_message')) {
return header;
}

let messageContent = escapeHTML(message.msg);
const contentParts = [];

if (hasText) {
let messageContent = escapeHTML(message.msg);
message = await callbacks.run('renderMessage', message);
if (message.tokens && message.tokens.length > 0) {
message.tokens.forEach((token) => {
token.text = token.text.replace(/([^\$])(\$[^\$])/gm, '$1$$$2');
messageContent = messageContent.replace(token.token, token.text);
});
}
return `${header}:<br/><br/>${messageContent.replace(/\n/gm, '<br/>')}`;
contentParts.push(messageContent.replace(/\n/gm, '<br/>'));
}

if (message.file) {
const fileHeader = i18n.t(!roomDirectives.isGroupChat(room) ? 'User_uploaded_a_file_to_you' : 'User_uploaded_a_file_on_channel', {
username: userName,
channel: roomName,
lng,
if (hasFiles) {
const attachments = message.attachments || [];
const fileParts = files.map((file, index) => {
let part = escapeHTML(file.name);
if (attachments[index]?.description) {
part += `<br/><br/>${escapeHTML(attachments[index].description)}`;
}
return part;
});

if (!settings.get('Email_notification_show_message')) {
return fileHeader;
}

let content = `${escapeHTML(message.file.name)}`;

if (message.attachments && message.attachments.length === 1 && message.attachments[0].description !== '') {
content += `<br/><br/>${escapeHTML(message.attachments[0].description)}`;
}

return `${fileHeader}:<br/><br/>${content}`;
contentParts.push(fileParts.join('<br/><br/>'));
}

if (!settings.get('Email_notification_show_message')) {
return header;
if (contentParts.length > 0) {
return `${header}:<br/><br/>${contentParts.join('<br/><br/>')}`;
}

if (Array.isArray(message.attachments) && message.attachments.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ export type FileProp = {
type: string;
format: string;
size: number;
// used to filter out thumbnails in email notifications
// may not exist in old messages
typeGroup?: string;
};
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -5641,6 +5641,8 @@
"User_updated_successfully": "User updated successfully",
"User_uploaded_a_file_on_channel": "<strong>{{username}}</strong> uploaded a file on <strong>{{channel}}</strong>",
"User_uploaded_a_file_to_you": "<strong>{{username}}</strong> sent you a file",
"User_uploaded_files_on_channel": "<strong>{{username}}</strong> uploaded {{count}} files on <strong>{{channel}}</strong>",
"User_uploaded_files_to_you": "<strong>{{username}}</strong> sent you {{count}} files",
"User_uploaded_file": "Uploaded a file",
"User_uploaded_image": "Uploaded an image",
"Username": "Username",
Expand Down
Loading