fix: omit empty cc/bcc from Email/set so server does not emit bare Cc: header #301
This commit is contained in:
@@ -127,6 +127,25 @@ describe('JMAPClient.sendEmail threading headers', () => {
|
|||||||
expect(draft.references).toBeUndefined();
|
expect(draft.references).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('omits cc/bcc when arrays are empty so the server does not emit a bare Cc: header', async () => {
|
||||||
|
const client = createClient();
|
||||||
|
const captured = mockSendEmailFlow();
|
||||||
|
|
||||||
|
await client.sendEmail(
|
||||||
|
['recipient@example.com'],
|
||||||
|
'No copies',
|
||||||
|
'body',
|
||||||
|
[], [], 'identity-1', 'user@example.com',
|
||||||
|
);
|
||||||
|
|
||||||
|
const setCall = captured[2].methodCalls[0];
|
||||||
|
const create = setCall[1].create as Record<string, Record<string, unknown>>;
|
||||||
|
const draft = Object.values(create)[0];
|
||||||
|
|
||||||
|
expect(draft.cc).toBeUndefined();
|
||||||
|
expect(draft.bcc).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it('drops empty / whitespace-only ids rather than sending blank entries', async () => {
|
it('drops empty / whitespace-only ids rather than sending blank entries', async () => {
|
||||||
const client = createClient();
|
const client = createClient();
|
||||||
const captured = mockSendEmailFlow();
|
const captured = mockSendEmailFlow();
|
||||||
|
|||||||
@@ -409,8 +409,8 @@ export class DemoJMAPClient implements IJMAPClient {
|
|||||||
receivedAt: new Date().toISOString(),
|
receivedAt: new Date().toISOString(),
|
||||||
from: [{ name: 'Demo User', email: 'demo@example.com' }],
|
from: [{ name: 'Demo User', email: 'demo@example.com' }],
|
||||||
to: to.map(e => ({ email: e })),
|
to: to.map(e => ({ email: e })),
|
||||||
cc: cc?.map(e => ({ email: e })),
|
cc: cc?.length ? cc.map(e => ({ email: e })) : undefined,
|
||||||
bcc: bcc?.map(e => ({ email: e })),
|
bcc: bcc?.length ? bcc.map(e => ({ email: e })) : undefined,
|
||||||
subject,
|
subject,
|
||||||
sentAt: new Date().toISOString(),
|
sentAt: new Date().toISOString(),
|
||||||
preview: body.substring(0, 200),
|
preview: body.substring(0, 200),
|
||||||
@@ -463,8 +463,8 @@ export class DemoJMAPClient implements IJMAPClient {
|
|||||||
receivedAt: new Date().toISOString(),
|
receivedAt: new Date().toISOString(),
|
||||||
from: [{ name: 'Demo User', email: 'demo@example.com' }],
|
from: [{ name: 'Demo User', email: 'demo@example.com' }],
|
||||||
to: to.map(e => ({ email: e })),
|
to: to.map(e => ({ email: e })),
|
||||||
cc: cc?.map(e => ({ email: e })),
|
cc: cc?.length ? cc.map(e => ({ email: e })) : undefined,
|
||||||
bcc: bcc?.map(e => ({ email: e })),
|
bcc: bcc?.length ? bcc.map(e => ({ email: e })) : undefined,
|
||||||
subject,
|
subject,
|
||||||
sentAt: new Date().toISOString(),
|
sentAt: new Date().toISOString(),
|
||||||
preview: body.substring(0, 200),
|
preview: body.substring(0, 200),
|
||||||
|
|||||||
+7
-4
@@ -2014,8 +2014,8 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
const emailData: EmailDraft = {
|
const emailData: EmailDraft = {
|
||||||
from: [{ ...(sanitizedFromName ? { name: sanitizedFromName } : {}), email: fromEmail || this.username }],
|
from: [{ ...(sanitizedFromName ? { name: sanitizedFromName } : {}), email: fromEmail || this.username }],
|
||||||
to: to.map(email => ({ email })),
|
to: to.map(email => ({ email })),
|
||||||
cc: cc?.map(email => ({ email })),
|
cc: cc?.length ? cc.map(email => ({ email })) : undefined,
|
||||||
bcc: bcc?.map(email => ({ email })),
|
bcc: bcc?.length ? bcc.map(email => ({ email })) : undefined,
|
||||||
subject,
|
subject,
|
||||||
keywords: { "$draft": true },
|
keywords: { "$draft": true },
|
||||||
mailboxIds: { [draftsMailbox.id]: true },
|
mailboxIds: { [draftsMailbox.id]: true },
|
||||||
@@ -2141,8 +2141,11 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
from: [{ ...(sanitizedFromName ? { name: sanitizedFromName } : {}), email: fromEmail || this.username }],
|
from: [{ ...(sanitizedFromName ? { name: sanitizedFromName } : {}), email: fromEmail || this.username }],
|
||||||
replyTo: identityReplyTo?.length ? identityReplyTo : undefined,
|
replyTo: identityReplyTo?.length ? identityReplyTo : undefined,
|
||||||
to: to.map(email => ({ email })),
|
to: to.map(email => ({ email })),
|
||||||
cc: cc?.map(email => ({ email })),
|
// RFC 5322 §3.6.3: To/Cc carry an address-list (non-empty). Sending
|
||||||
bcc: bcc?.map(email => ({ email })),
|
// cc:[] makes the server emit a literal `Cc:` header with no addresses,
|
||||||
|
// which is malformed and a spam signal. Omit the field when empty.
|
||||||
|
cc: cc?.length ? cc.map(email => ({ email })) : undefined,
|
||||||
|
bcc: bcc?.length ? bcc.map(email => ({ email })) : undefined,
|
||||||
subject,
|
subject,
|
||||||
inReplyTo: normalizedInReplyTo?.length ? normalizedInReplyTo : undefined,
|
inReplyTo: normalizedInReplyTo?.length ? normalizedInReplyTo : undefined,
|
||||||
references: normalizedReferences?.length ? normalizedReferences : undefined,
|
references: normalizedReferences?.length ? normalizedReferences : undefined,
|
||||||
|
|||||||
Reference in New Issue
Block a user