node_modules: update (#355)

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Dawid Dziurlaanddawidd6 authored and GitHub committed 2026-10-29 12:25:35 +01:00
1 parent b6d53adeaf
commit f8b8145a29
34 files changed
+375 -36

No files matched your search

+54
View File
@@ -1,6 +1,7 @@
import * as shared from '../shared/index.js';
import MimeNode from '../mime-node/index.js';
import * as mimeFuncs from '../mime-funcs/index.js';
import * as errors from '../errors.js';
// Only an own key counts as already set. `key in obj` also matches every member of
// Object.prototype, which silently drops a transporter default legitimately named
// toString or constructor.
@@ -262,6 +263,26 @@ export default class MailMessage {
});
});
}
/**
* Sets the OTP-Token header from the otp option. The header is defined by
* draft-goto-otp-token-01, an Internet-Draft that expires on 25 March 2027. By then check
* for a newer revision of the draft or a published RFC, the header name and its
* parameters are still open questions in the draft.
*/
setOtpHeader() {
const otp = this.data.otp;
if (!this.message || !otp) {
return;
}
// a structured field String can only hold printable ascii. The code is a secret the recipient
// compares against the one in the message body, so it is rejected rather than cleaned up
if (typeof otp.code !== 'string' || !/^[\x20-\x7e]+$/.test(otp.code)) {
throw otpError('The otp code must be a non-empty string of printable ASCII characters');
}
// a structured field String escapes the same two characters as a quoted-string. setHeader
// replaces any OTP-Token from the custom headers, the field may appear only once
this.message.setHeader('OTP-Token', mimeFuncs.quoteString(otp.code) + '; origin=' + mimeFuncs.quoteString(getOtpOrigin(otp.origin)));
}
/** @internal */
_getListHeaders(listData) {
// make sure an url looks like <protocol:url>
@@ -321,3 +342,36 @@ export default class MailMessage {
return '<http://' + url + '>';
}
}
/**
* Returns the canonical ascii serialization of the origin the code is bound to. The draft
* requires a potentially trustworthy origin, so only https is accepted, plus http on a
* loopback host for local development
*/
function getOtpOrigin(origin) {
let url;
try {
url = new URL(String(origin));
}
catch {
// handled below
}
// the WHATWG parser lets characters such as a quote or a brace into a host, which the
// origin grammar the draft requires (RFC 6454) does not allow, so a receiver would discard
// the header. Only a DNS name, an IPv4 address or a bracketed IPv6 address is accepted.
// Userinfo is refused as well, an origin never has it and it turns a value built as
// 'https://example.com' + input into the origin of whatever host follows an "@"
if (!url || url.username || url.password || !/^([a-z0-9_-]+\.)*[a-z0-9_-]+$|^\[[0-9a-f:.]+\]$/.test(url.hostname)) {
throw otpError('The otp origin must be an absolute https URL');
}
const isLoopback = /^(localhost|.+\.localhost|127(\.\d+){3}|\[::1\])$/.test(url.hostname);
if (url.protocol !== 'https:' && !(url.protocol === 'http:' && isLoopback)) {
throw otpError('The otp origin must be an https URL, or an http URL on a loopback host');
}
// the URL parser already lowercases the host, converts it to punycode and drops the default port
return url.origin;
}
function otpError(message) {
const err = new Error(message);
err.code = errors.EOTP;
return err;
}