mirror of
https://github.com/Mail-0/Zero.git
synced 2026-06-28 23:06:54 +00:00
composer styling (#1259)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added support for forwarding emails, allowing users to send existing messages to new recipients with original content included. - **Bug Fixes** - Improved formatting for quoted and forwarded message sections in email bodies. - **Chores** - Enhanced email composition options to handle more flexible message metadata, such as optional attachments, headers, and recipient fields. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -5,7 +5,7 @@ import { useHotkeysContext } from 'react-hotkeys-hook';
|
||||
import { useTRPC } from '@/providers/query-provider';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { useSettings } from '@/hooks/use-settings';
|
||||
import { constructReplyBody } from '@/lib/utils';
|
||||
import { constructReplyBody, constructForwardBody } from '@/lib/utils';
|
||||
import { useThread } from '@/hooks/use-threads';
|
||||
import { serializeFiles } from '@/lib/schemas';
|
||||
import { useDraft } from '@/hooks/use-drafts';
|
||||
@@ -136,20 +136,28 @@ export default function ReplyCompose({ messageId }: ReplyComposeProps) {
|
||||
? '<p style="color: #666; font-size: 12px;">Sent via <a href="https://0.email/" style="color: #0066cc; text-decoration: none;">Zero</a></p>'
|
||||
: '';
|
||||
|
||||
const replyBody = constructReplyBody(
|
||||
data.message + zeroSignature,
|
||||
new Date(replyToMessage.receivedOn || '').toLocaleString(),
|
||||
replyToMessage.sender,
|
||||
toRecipients,
|
||||
replyToMessage.decodedBody,
|
||||
);
|
||||
const emailBody = mode === 'forward'
|
||||
? constructForwardBody(
|
||||
data.message + zeroSignature,
|
||||
new Date(replyToMessage.receivedOn || '').toLocaleString(),
|
||||
{ ...replyToMessage.sender, subject: replyToMessage.subject },
|
||||
toRecipients,
|
||||
replyToMessage.decodedBody,
|
||||
)
|
||||
: constructReplyBody(
|
||||
data.message + zeroSignature,
|
||||
new Date(replyToMessage.receivedOn || '').toLocaleString(),
|
||||
replyToMessage.sender,
|
||||
toRecipients,
|
||||
replyToMessage.decodedBody,
|
||||
);
|
||||
|
||||
await sendEmail({
|
||||
to: toRecipients,
|
||||
cc: ccRecipients,
|
||||
bcc: bccRecipients,
|
||||
subject: data.subject,
|
||||
message: replyBody,
|
||||
message: emailBody,
|
||||
attachments: await serializeFiles(data.attachments),
|
||||
fromEmail: aliases?.[0]?.email || userEmail,
|
||||
headers: {
|
||||
@@ -163,6 +171,8 @@ export default function ReplyCompose({ messageId }: ReplyComposeProps) {
|
||||
'Thread-Id': replyToMessage?.threadId ?? '',
|
||||
},
|
||||
threadId: replyToMessage?.threadId,
|
||||
isForward: mode === 'forward',
|
||||
originalMessage: replyToMessage.decodedBody,
|
||||
});
|
||||
|
||||
posthog.capture('Reply Email Sent');
|
||||
|
||||
@@ -287,8 +287,33 @@ export const constructReplyBody = (
|
||||
<div style="font-size: 12px;">
|
||||
On ${originalDate}, ${senderName} ${recipientEmails ? `<${recipientEmails}>` : ''} wrote:
|
||||
</div>
|
||||
<div style="">
|
||||
${quotedMessage || ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
|
||||
export const constructForwardBody = (
|
||||
formattedMessage: string,
|
||||
originalDate: string,
|
||||
originalSender: Sender | undefined,
|
||||
otherRecipients: Sender[],
|
||||
quotedMessage?: string,
|
||||
) => {
|
||||
const senderName = originalSender?.name || originalSender?.email || 'Unknown Sender';
|
||||
const recipientEmails = otherRecipients.map((r) => r.email).join(', ');
|
||||
|
||||
return `
|
||||
<div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;">
|
||||
<div style="">
|
||||
${formattedMessage}
|
||||
</div>
|
||||
<div style="margin-top: 20px; border-top: 1px solid #e2e8f0; padding-top: 20px;">
|
||||
<div style="font-size: 12px; color: #64748b; margin-bottom: 10px;">
|
||||
---------- Forwarded message ----------<br/>
|
||||
From: ${senderName} ${originalSender?.email ? `<${originalSender.email}>` : ''}<br/>
|
||||
Date: ${originalDate}<br/>
|
||||
Subject: ${originalSender?.subject || 'No Subject'}<br/>
|
||||
To: ${recipientEmails || 'No Recipients'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,6 +55,7 @@ export interface SidebarData {
|
||||
export interface Sender {
|
||||
name?: string;
|
||||
email: string;
|
||||
subject?: string;
|
||||
}
|
||||
|
||||
export interface ParsedMessage {
|
||||
@@ -113,14 +114,16 @@ export type ThreadProps = {
|
||||
|
||||
export interface IOutgoingMessage {
|
||||
to: Sender[];
|
||||
cc?: Sender[];
|
||||
bcc?: Sender[];
|
||||
subject: string;
|
||||
message: string;
|
||||
attachments: File[];
|
||||
headers: Record<string, string>;
|
||||
attachments?: File[];
|
||||
headers?: Record<string, string>;
|
||||
cc?: Sender[];
|
||||
bcc?: Sender[];
|
||||
threadId?: string;
|
||||
fromEmail?: string;
|
||||
isForward?: boolean;
|
||||
originalMessage?: string;
|
||||
}
|
||||
|
||||
export interface Note {
|
||||
|
||||
@@ -898,6 +898,8 @@ export class GoogleMailManager implements MailManager {
|
||||
cc,
|
||||
bcc,
|
||||
fromEmail,
|
||||
isForward = false,
|
||||
originalMessage = null,
|
||||
}: IOutgoingMessage) {
|
||||
const msg = createMimeMessage();
|
||||
|
||||
@@ -990,10 +992,17 @@ export class GoogleMailManager implements MailManager {
|
||||
|
||||
msg.setSubject(subject);
|
||||
|
||||
msg.addMessage({
|
||||
contentType: 'text/html',
|
||||
data: await sanitizeTipTapHtml(message.trim()),
|
||||
});
|
||||
if (originalMessage) {
|
||||
msg.addMessage({
|
||||
contentType: 'text/html',
|
||||
data: `${await sanitizeTipTapHtml(message.trim())}${originalMessage}`,
|
||||
});
|
||||
} else {
|
||||
msg.addMessage({
|
||||
contentType: 'text/html',
|
||||
data: await sanitizeTipTapHtml(message.trim()),
|
||||
});
|
||||
}
|
||||
|
||||
if (headers) {
|
||||
Object.entries(headers).forEach(([key, value]) => {
|
||||
|
||||
@@ -273,6 +273,8 @@ export const mailRouter = router({
|
||||
threadId: z.string().optional(),
|
||||
fromEmail: z.string().optional(),
|
||||
draftId: z.string().optional(),
|
||||
isForward: z.boolean().optional(),
|
||||
originalMessage: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
|
||||
@@ -136,6 +136,8 @@ export interface IOutgoingMessage {
|
||||
headers: Record<string, string>;
|
||||
threadId?: string;
|
||||
fromEmail?: string;
|
||||
isForward?: boolean;
|
||||
originalMessage?: string | null;
|
||||
}
|
||||
export interface DeleteAllSpamResponse {
|
||||
success: boolean;
|
||||
|
||||
Reference in New Issue
Block a user