mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
fix(email): read the MailChannels sender through the address helper
@types/nodemailer 8 types a message's `from` as one address or a list, as
nodemailer has always accepted. The transport only knew a string or one
Address, so the list case did not type-check and, at run time, posted a
sender with no email.
The sender now goes through toMailChannelsAddresses, which already handles
all three shapes for to, cc and bcc, and the first address is the sender. A
string or a single Address comes out exactly as before.
mailchannels.test.ts sends each shape through nodemailer and reads what was
posted; against the old code the list case fails with `{}`.
Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import assert from 'node:assert';
|
||||
import { afterEach, describe, it } from 'node:test';
|
||||
|
||||
import { createTransport } from 'nodemailer';
|
||||
import type { Options } from 'nodemailer/lib/mailer';
|
||||
|
||||
import { MailChannelsTransport } from '../transports/mailchannels';
|
||||
|
||||
const realFetch = globalThis.fetch;
|
||||
|
||||
/** Sends one mail through nodemailer and returns the `from` MailChannels was posted. */
|
||||
const sendFrom = async (from: Options['from']) => {
|
||||
const bodies: string[] = [];
|
||||
|
||||
globalThis.fetch = async (_input: string | URL | Request, init?: RequestInit) => {
|
||||
bodies.push(String(init?.body));
|
||||
|
||||
return Promise.resolve(new Response('{}', { status: 202 }));
|
||||
};
|
||||
|
||||
await createTransport(MailChannelsTransport.makeTransport({ apiKey: 'key' })).sendMail({
|
||||
from,
|
||||
to: '[email protected]',
|
||||
subject: 'hi',
|
||||
html: '<p>hi</p>',
|
||||
});
|
||||
|
||||
assert.equal(bodies.length, 1);
|
||||
|
||||
return JSON.parse(bodies[0]).from;
|
||||
};
|
||||
|
||||
describe('mailchannels transport', () => {
|
||||
afterEach(() => {
|
||||
globalThis.fetch = realFetch;
|
||||
});
|
||||
|
||||
it('sends from a bare address', async () => {
|
||||
assert.deepEqual(await sendFrom('[email protected]'), { email: '[email protected]' });
|
||||
});
|
||||
|
||||
it('sends from a named address', async () => {
|
||||
assert.deepEqual(await sendFrom({ name: 'Sign', address: '[email protected]' }), {
|
||||
email: '[email protected]',
|
||||
name: 'Sign',
|
||||
});
|
||||
});
|
||||
|
||||
it('sends from the first address of a list', async () => {
|
||||
assert.deepEqual(await sendFrom(['[email protected]', '[email protected]']), {
|
||||
email: '[email protected]',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -54,13 +54,8 @@ export class MailChannelsTransport implements Transport<SentMessageInfo> {
|
||||
const mailCc = this.toMailChannelsAddresses(mail.data.cc);
|
||||
const mailBcc = this.toMailChannelsAddresses(mail.data.bcc);
|
||||
|
||||
const from: MailChannelsAddress =
|
||||
typeof mail.data.from === 'string'
|
||||
? { email: mail.data.from }
|
||||
: {
|
||||
email: mail.data.from?.address,
|
||||
name: mail.data.from?.name,
|
||||
};
|
||||
// nodemailer takes a list here as well as one address; a message has one sender.
|
||||
const [from] = this.toMailChannelsAddresses(mail.data.from);
|
||||
|
||||
const requestHeaders: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
Reference in New Issue
Block a user