'. Data to be sent as response needs to be
* base64 decoded challenge string, MD5 hashed using the password as
* a HMAC key, prefixed by the username and a space, and finally all
* base64 encoded again.
*
* @param {String} str Message from the server
*/ _actionAUTH_CRAM_MD5(str, callback) {
let challengeMatch = str.match(/^334\s+(.+)$/);
let challengeString = '';
if (!challengeMatch) {
return callback(this._formatError('Invalid login sequence while waiting for server challenge string', 'EAUTH', str, 'AUTH CRAM-MD5'));
} else {
challengeString = challengeMatch[1];
}
// Decode from base64
let base64decoded = Buffer.from(challengeString, 'base64').toString('ascii'), hmacMD5 = crypto.createHmac('md5', this._auth.credentials.pass);
hmacMD5.update(base64decoded);
let prepended = this._auth.credentials.user + ' ' + hmacMD5.digest('hex');
this._responseActions.push((str)=>{
this._actionAUTH_CRAM_MD5_PASS(str, callback);
});
this._sendCommand(Buffer.from(prepended).toString('base64'), // hidden hash for logs
Buffer.from(this._auth.credentials.user + ' /* secret */').toString('base64'));
}
/**
* Handles the response to CRAM-MD5 authentication, if there's no error,
* the user can be considered logged in. Start waiting for a message to send
*
* @param {String} str Message from the server
*/ _actionAUTH_CRAM_MD5_PASS(str, callback) {
if (!str.match(/^235\s+/)) {
return callback(this._formatError('Invalid login sequence while waiting for "235"', 'EAUTH', str, 'AUTH CRAM-MD5'));
}
this.logger.info({
tnx: 'smtp',
username: this._auth.user,
action: 'authenticated',
method: this._authMethod
}, 'User %s authenticated', JSON.stringify(this._auth.user));
this.authenticated = true;
callback(null, true);
}
/**
* Handle the response for AUTH LOGIN command. We are expecting
* '334 UGFzc3dvcmQ6' (base64 for 'Password:'). Data to be sent as
* response needs to be base64 encoded password.
*
* @param {String} str Message from the server
*/ _actionAUTH_LOGIN_PASS(str, callback) {
if (!/^334[ -]/.test(str)) {
// expecting '334 UGFzc3dvcmQ6'
return callback(this._formatError('Invalid login sequence while waiting for "334 UGFzc3dvcmQ6"', 'EAUTH', str, 'AUTH LOGIN'));
}
this._responseActions.push((str)=>{
this._actionAUTHComplete(str, callback);
});
this._sendCommand(Buffer.from((this._auth.credentials.pass || '').toString(), 'utf-8').toString('base64'), // Hidden pass for logs
Buffer.from('/* secret */', 'utf-8').toString('base64'));
}
/**
* Handles the response for authentication, if there's no error,
* the user can be considered logged in. Start waiting for a message to send
*
* @param {String} str Message from the server
*/ _actionAUTHComplete(str, isRetry, callback) {
if (!callback && typeof isRetry === 'function') {
callback = isRetry;
isRetry = false;
}
if (str.substr(0, 3) === '334') {
this._responseActions.push((str)=>{
if (isRetry || this._authMethod !== 'XOAUTH2') {
this._actionAUTHComplete(str, true, callback);
} else {
// fetch a new OAuth2 access token
setImmediate(()=>this._handleXOauth2Token(true, callback));
}
});
this._sendCommand('');
return;
}
if (str.charAt(0) !== '2') {
this.logger.info({
tnx: 'smtp',
username: this._auth.user,
action: 'authfail',
method: this._authMethod
}, 'User %s failed to authenticate', JSON.stringify(this._auth.user));
return callback(this._formatError('Invalid login', 'EAUTH', str, 'AUTH ' + this._authMethod));
}
this.logger.info({
tnx: 'smtp',
username: this._auth.user,
action: 'authenticated',
method: this._authMethod
}, 'User %s authenticated', JSON.stringify(this._auth.user));
this.authenticated = true;
callback(null, true);
}
/**
* Handle response for a MAIL FROM: command
*
* @param {String} str Message from the server
*/ _actionMAIL(str, callback) {
let message, curRecipient;
if (Number(str.charAt(0)) !== 2) {
if (this._usingSmtpUtf8 && /^550 /.test(str) && /[\x80-\uFFFF]/.test(this._envelope.from)) {
message = 'Internationalized mailbox name not allowed';
} else {
message = 'Mail command failed';
}
return callback(this._formatError(message, 'EENVELOPE', str, 'MAIL FROM'));
}
if (!this._envelope.rcptQueue.length) {
return callback(this._formatError("Can't send mail - no recipients defined", 'EENVELOPE', false, 'API'));
} else {
this._recipientQueue = [];
if (this._supportedExtensions.includes('PIPELINING')) {
while(this._envelope.rcptQueue.length){
curRecipient = this._envelope.rcptQueue.shift();
this._recipientQueue.push(curRecipient);
this._responseActions.push((str)=>{
this._actionRCPT(str, callback);
});
this._sendCommand('RCPT TO:<' + curRecipient + '>' + this._getDsnRcptToArgs());
}
} else {
curRecipient = this._envelope.rcptQueue.shift();
this._recipientQueue.push(curRecipient);
this._responseActions.push((str)=>{
this._actionRCPT(str, callback);
});
this._sendCommand('RCPT TO:<' + curRecipient + '>' + this._getDsnRcptToArgs());
}
}
}
/**
* Handle response for a RCPT TO: command
*
* @param {String} str Message from the server
*/ _actionRCPT(str, callback) {
let message, err, curRecipient = this._recipientQueue.shift();
if (Number(str.charAt(0)) !== 2) {
// this is a soft error
if (this._usingSmtpUtf8 && /^553 /.test(str) && /[\x80-\uFFFF]/.test(curRecipient)) {
message = 'Internationalized mailbox name not allowed';
} else {
message = 'Recipient command failed';
}
this._envelope.rejected.push(curRecipient);
// store error for the failed recipient
err = this._formatError(message, 'EENVELOPE', str, 'RCPT TO');
err.recipient = curRecipient;
this._envelope.rejectedErrors.push(err);
} else {
this._envelope.accepted.push(curRecipient);
}
if (!this._envelope.rcptQueue.length && !this._recipientQueue.length) {
if (this._envelope.rejected.length < this._envelope.to.length) {
this._responseActions.push((str)=>{
this._actionDATA(str, callback);
});
this._sendCommand('DATA');
} else {
err = this._formatError("Can't send mail - all recipients were rejected", 'EENVELOPE', str, 'RCPT TO');
err.rejected = this._envelope.rejected;
err.rejectedErrors = this._envelope.rejectedErrors;
return callback(err);
}
} else if (this._envelope.rcptQueue.length) {
curRecipient = this._envelope.rcptQueue.shift();
this._recipientQueue.push(curRecipient);
this._responseActions.push((str)=>{
this._actionRCPT(str, callback);
});
this._sendCommand('RCPT TO:<' + curRecipient + '>' + this._getDsnRcptToArgs());
}
}
/**
* Handle response for a DATA command
*
* @param {String} str Message from the server
*/ _actionDATA(str, callback) {
// response should be 354 but according to this issue https://github.com/eleith/emailjs/issues/24
// some servers might use 250 instead, so lets check for 2 or 3 as the first digit
if (!/^[23]/.test(str)) {
return callback(this._formatError('Data command failed', 'EENVELOPE', str, 'DATA'));
}
let response = {
accepted: this._envelope.accepted,
rejected: this._envelope.rejected
};
if (this._ehloLines && this._ehloLines.length) {
response.ehlo = this._ehloLines;
}
if (this._envelope.rejectedErrors.length) {
response.rejectedErrors = this._envelope.rejectedErrors;
}
callback(null, response);
}
/**
* Handle response for a DATA stream when using SMTP
* We expect a single response that defines if the sending succeeded or failed
*
* @param {String} str Message from the server
*/ _actionSMTPStream(str, callback) {
if (Number(str.charAt(0)) !== 2) {
// Message failed
return callback(this._formatError('Message failed', 'EMESSAGE', str, 'DATA'));
} else {
// Message sent succesfully
return callback(null, str);
}
}
/**
* Handle response for a DATA stream
* We expect a separate response for every recipient. All recipients can either
* succeed or fail separately
*
* @param {String} recipient The recipient this response applies to
* @param {Boolean} final Is this the final recipient?
* @param {String} str Message from the server
*/ _actionLMTPStream(recipient, final, str, callback) {
let err;
if (Number(str.charAt(0)) !== 2) {
// Message failed
err = this._formatError('Message failed for recipient ' + recipient, 'EMESSAGE', str, 'DATA');
err.recipient = recipient;
this._envelope.rejected.push(recipient);
this._envelope.rejectedErrors.push(err);
for(let i = 0, len = this._envelope.accepted.length; i < len; i++){
if (this._envelope.accepted[i] === recipient) {
this._envelope.accepted.splice(i, 1);
}
}
}
if (final) {
return callback(null, str);
}
}
_handleXOauth2Token(isRetry, callback) {
this._auth.oauth2.getToken(isRetry, (err, accessToken)=>{
if (err) {
this.logger.info({
tnx: 'smtp',
username: this._auth.user,
action: 'authfail',
method: this._authMethod
}, 'User %s failed to authenticate', JSON.stringify(this._auth.user));
return callback(this._formatError(err, 'EAUTH', false, 'AUTH XOAUTH2'));
}
this._responseActions.push((str)=>{
this._actionAUTHComplete(str, isRetry, callback);
});
this._sendCommand('AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token(accessToken), // Hidden for logs
'AUTH XOAUTH2 ' + this._auth.oauth2.buildXOAuth2Token('/* secret */'));
});
}
/**
*
* @param {string} command
* @private
*/ _isDestroyedMessage(command) {
if (this._destroyed) {
return 'Cannot ' + command + ' - smtp connection is already destroyed.';
}
if (this._socket) {
if (this._socket.destroyed) {
return 'Cannot ' + command + ' - smtp connection socket is already destroyed.';
}
if (!this._socket.writable) {
return 'Cannot ' + command + ' - smtp connection socket is already half-closed.';
}
}
}
_getHostname() {
// defaul hostname is machine hostname or [IP]
let defaultHostname;
try {
defaultHostname = os.hostname() || '';
} catch (_err) {
// fails on windows 7
defaultHostname = 'localhost';
}
// ignore if not FQDN
if (!defaultHostname || defaultHostname.indexOf('.') < 0) {
defaultHostname = '[127.0.0.1]';
}
// IP should be enclosed in []
if (defaultHostname.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) {
defaultHostname = '[' + defaultHostname + ']';
}
return defaultHostname;
}
}
module.exports = SMTPConnection;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/xoauth2/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const Stream = __turbopack_context__.r("[externals]/stream [external] (stream, cjs)").Stream;
const nmfetch = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/fetch/index.js [app-route] (ecmascript)");
const crypto = __turbopack_context__.r("[externals]/crypto [external] (crypto, cjs)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
/**
* XOAUTH2 access_token generator for Gmail.
* Create client ID for web applications in Google API console to use it.
* See Offline Access for receiving the needed refreshToken for an user
* https://developers.google.com/accounts/docs/OAuth2WebServer#offline
*
* Usage for generating access tokens with a custom method using provisionCallback:
* provisionCallback(user, renew, callback)
* * user is the username to get the token for
* * renew is a boolean that if true indicates that existing token failed and needs to be renewed
* * callback is the callback to run with (error, accessToken [, expires])
* * accessToken is a string
* * expires is an optional expire time in milliseconds
* If provisionCallback is used, then Nodemailer does not try to attempt generating the token by itself
*
* @constructor
* @param {Object} options Client information for token generation
* @param {String} options.user User e-mail address
* @param {String} options.clientId Client ID value
* @param {String} options.clientSecret Client secret value
* @param {String} options.refreshToken Refresh token for an user
* @param {String} options.accessUrl Endpoint for token generation, defaults to 'https://accounts.google.com/o/oauth2/token'
* @param {String} options.accessToken An existing valid accessToken
* @param {String} options.privateKey Private key for JSW
* @param {Number} options.expires Optional Access Token expire time in ms
* @param {Number} options.timeout Optional TTL for Access Token in seconds
* @param {Function} options.provisionCallback Function to run when a new access token is required
*/ class XOAuth2 extends Stream {
constructor(options, logger){
super();
this.options = options || {};
if (options && options.serviceClient) {
if (!options.privateKey || !options.user) {
setImmediate(()=>this.emit('error', new Error('Options "privateKey" and "user" are required for service account!')));
return;
}
let serviceRequestTimeout = Math.min(Math.max(Number(this.options.serviceRequestTimeout) || 0, 0), 3600);
this.options.serviceRequestTimeout = serviceRequestTimeout || 5 * 60;
}
this.logger = shared.getLogger({
logger
}, {
component: this.options.component || 'OAuth2'
});
this.provisionCallback = typeof this.options.provisionCallback === 'function' ? this.options.provisionCallback : false;
this.options.accessUrl = this.options.accessUrl || 'https://accounts.google.com/o/oauth2/token';
this.options.customHeaders = this.options.customHeaders || {};
this.options.customParams = this.options.customParams || {};
this.accessToken = this.options.accessToken || false;
if (this.options.expires && Number(this.options.expires)) {
this.expires = this.options.expires;
} else {
let timeout = Math.max(Number(this.options.timeout) || 0, 0);
this.expires = timeout && Date.now() + timeout * 1000 || 0;
}
this.renewing = false; // Track if renewal is in progress
this.renewalQueue = []; // Queue for pending requests during renewal
}
/**
* Returns or generates (if previous has expired) a XOAuth2 token
*
* @param {Boolean} renew If false then use cached access token (if available)
* @param {Function} callback Callback function with error object and token string
*/ getToken(renew, callback) {
if (!renew && this.accessToken && (!this.expires || this.expires > Date.now())) {
this.logger.debug({
tnx: 'OAUTH2',
user: this.options.user,
action: 'reuse'
}, 'Reusing existing access token for %s', this.options.user);
return callback(null, this.accessToken);
}
// check if it is possible to renew, if not, return the current token or error
if (!this.provisionCallback && !this.options.refreshToken && !this.options.serviceClient) {
if (this.accessToken) {
this.logger.debug({
tnx: 'OAUTH2',
user: this.options.user,
action: 'reuse'
}, 'Reusing existing access token (no refresh capability) for %s', this.options.user);
return callback(null, this.accessToken);
}
this.logger.error({
tnx: 'OAUTH2',
user: this.options.user,
action: 'renew'
}, 'Cannot renew access token for %s: No refresh mechanism available', this.options.user);
return callback(new Error("Can't create new access token for user"));
}
// If renewal already in progress, queue this request instead of starting another
if (this.renewing) {
return this.renewalQueue.push({
renew,
callback
});
}
this.renewing = true;
// Handles token renewal completion - processes queued requests and cleans up
const generateCallback = (err, accessToken)=>{
this.renewalQueue.forEach((item)=>item.callback(err, accessToken));
this.renewalQueue = [];
this.renewing = false;
if (err) {
this.logger.error({
err,
tnx: 'OAUTH2',
user: this.options.user,
action: 'renew'
}, 'Failed generating new Access Token for %s', this.options.user);
} else {
this.logger.info({
tnx: 'OAUTH2',
user: this.options.user,
action: 'renew'
}, 'Generated new Access Token for %s', this.options.user);
}
// Complete original request
callback(err, accessToken);
};
if (this.provisionCallback) {
this.provisionCallback(this.options.user, !!renew, (err, accessToken, expires)=>{
if (!err && accessToken) {
this.accessToken = accessToken;
this.expires = expires || 0;
}
generateCallback(err, accessToken);
});
} else {
this.generateToken(generateCallback);
}
}
/**
* Updates token values
*
* @param {String} accessToken New access token
* @param {Number} timeout Access token lifetime in seconds
*
* Emits 'token': { user: User email-address, accessToken: the new accessToken, timeout: TTL in seconds}
*/ updateToken(accessToken, timeout) {
this.accessToken = accessToken;
timeout = Math.max(Number(timeout) || 0, 0);
this.expires = timeout && Date.now() + timeout * 1000 || 0;
this.emit('token', {
user: this.options.user,
accessToken: accessToken || '',
expires: this.expires
});
}
/**
* Generates a new XOAuth2 token with the credentials provided at initialization
*
* @param {Function} callback Callback function with error object and token string
*/ generateToken(callback) {
let urlOptions;
let loggedUrlOptions;
if (this.options.serviceClient) {
// service account - https://developers.google.com/identity/protocols/OAuth2ServiceAccount
let iat = Math.floor(Date.now() / 1000); // unix time
let tokenData = {
iss: this.options.serviceClient,
scope: this.options.scope || 'https://mail.google.com/',
sub: this.options.user,
aud: this.options.accessUrl,
iat,
exp: iat + this.options.serviceRequestTimeout
};
let token;
try {
token = this.jwtSignRS256(tokenData);
} catch (_err) {
return callback(new Error("Can't generate token. Check your auth options"));
}
urlOptions = {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: token
};
loggedUrlOptions = {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: tokenData
};
} else {
if (!this.options.refreshToken) {
return callback(new Error("Can't create new access token for user"));
}
// web app - https://developers.google.com/identity/protocols/OAuth2WebServer
urlOptions = {
client_id: this.options.clientId || '',
client_secret: this.options.clientSecret || '',
refresh_token: this.options.refreshToken,
grant_type: 'refresh_token'
};
loggedUrlOptions = {
client_id: this.options.clientId || '',
client_secret: (this.options.clientSecret || '').substr(0, 6) + '...',
refresh_token: (this.options.refreshToken || '').substr(0, 6) + '...',
grant_type: 'refresh_token'
};
}
Object.keys(this.options.customParams).forEach((key)=>{
urlOptions[key] = this.options.customParams[key];
loggedUrlOptions[key] = this.options.customParams[key];
});
this.logger.debug({
tnx: 'OAUTH2',
user: this.options.user,
action: 'generate'
}, 'Requesting token using: %s', JSON.stringify(loggedUrlOptions));
this.postRequest(this.options.accessUrl, urlOptions, this.options, (error, body)=>{
let data;
if (error) {
return callback(error);
}
try {
data = JSON.parse(body.toString());
} catch (E) {
return callback(E);
}
if (!data || typeof data !== 'object') {
this.logger.debug({
tnx: 'OAUTH2',
user: this.options.user,
action: 'post'
}, 'Response: %s', (body || '').toString());
return callback(new Error('Invalid authentication response'));
}
let logData = {};
Object.keys(data).forEach((key)=>{
if (key !== 'access_token') {
logData[key] = data[key];
} else {
logData[key] = (data[key] || '').toString().substr(0, 6) + '...';
}
});
this.logger.debug({
tnx: 'OAUTH2',
user: this.options.user,
action: 'post'
}, 'Response: %s', JSON.stringify(logData));
if (data.error) {
// Error Response : https://tools.ietf.org/html/rfc6749#section-5.2
let errorMessage = data.error;
if (data.error_description) {
errorMessage += ': ' + data.error_description;
}
if (data.error_uri) {
errorMessage += ' (' + data.error_uri + ')';
}
return callback(new Error(errorMessage));
}
if (data.access_token) {
this.updateToken(data.access_token, data.expires_in);
return callback(null, this.accessToken);
}
return callback(new Error('No access token'));
});
}
/**
* Converts an access_token and user id into a base64 encoded XOAuth2 token
*
* @param {String} [accessToken] Access token string
* @return {String} Base64 encoded token for IMAP or SMTP login
*/ buildXOAuth2Token(accessToken) {
let authData = [
'user=' + (this.options.user || ''),
'auth=Bearer ' + (accessToken || this.accessToken),
'',
''
];
return Buffer.from(authData.join('\x01'), 'utf-8').toString('base64');
}
/**
* Custom POST request handler.
* This is only needed to keep paths short in Windows – usually this module
* is a dependency of a dependency and if it tries to require something
* like the request module the paths get way too long to handle for Windows.
* As we do only a simple POST request we do not actually require complicated
* logic support (no redirects, no nothing) anyway.
*
* @param {String} url Url to POST to
* @param {String|Buffer} payload Payload to POST
* @param {Function} callback Callback function with (err, buff)
*/ postRequest(url, payload, params, callback) {
let returned = false;
let chunks = [];
let chunklen = 0;
let req = nmfetch(url, {
method: 'post',
headers: params.customHeaders,
body: payload,
allowErrorResponse: true
});
req.on('readable', ()=>{
let chunk;
while((chunk = req.read()) !== null){
chunks.push(chunk);
chunklen += chunk.length;
}
});
req.once('error', (err)=>{
if (returned) {
return;
}
returned = true;
return callback(err);
});
req.once('end', ()=>{
if (returned) {
return;
}
returned = true;
return callback(null, Buffer.concat(chunks, chunklen));
});
}
/**
* Encodes a buffer or a string into Base64url format
*
* @param {Buffer|String} data The data to convert
* @return {String} The encoded string
*/ toBase64URL(data) {
if (typeof data === 'string') {
data = Buffer.from(data);
}
return data.toString('base64').replace(/[=]+/g, '') // remove '='s
.replace(/\+/g, '-') // '+' → '-'
.replace(/\//g, '_'); // '/' → '_'
}
/**
* Creates a JSON Web Token signed with RS256 (SHA256 + RSA)
*
* @param {Object} payload The payload to include in the generated token
* @return {String} The generated and signed token
*/ jwtSignRS256(payload) {
payload = [
'{"alg":"RS256","typ":"JWT"}',
JSON.stringify(payload)
].map((val)=>this.toBase64URL(val)).join('.');
let signature = crypto.createSign('RSA-SHA256').update(payload).sign(this.options.privateKey);
return payload + '.' + this.toBase64URL(signature);
}
}
module.exports = XOAuth2;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-pool/pool-resource.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const SMTPConnection = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-connection/index.js [app-route] (ecmascript)");
const assign = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)").assign;
const XOAuth2 = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/xoauth2/index.js [app-route] (ecmascript)");
const EventEmitter = __turbopack_context__.r("[externals]/events [external] (events, cjs)");
/**
* Creates an element for the pool
*
* @constructor
* @param {Object} options SMTPPool instance
*/ class PoolResource extends EventEmitter {
constructor(pool){
super();
this.pool = pool;
this.options = pool.options;
this.logger = this.pool.logger;
if (this.options.auth) {
switch((this.options.auth.type || '').toString().toUpperCase()){
case 'OAUTH2':
{
let oauth2 = new XOAuth2(this.options.auth, this.logger);
oauth2.provisionCallback = this.pool.mailer && this.pool.mailer.get('oauth2_provision_cb') || oauth2.provisionCallback;
this.auth = {
type: 'OAUTH2',
user: this.options.auth.user,
oauth2,
method: 'XOAUTH2'
};
oauth2.on('token', (token)=>this.pool.mailer.emit('token', token));
oauth2.on('error', (err)=>this.emit('error', err));
break;
}
default:
if (!this.options.auth.user && !this.options.auth.pass) {
break;
}
this.auth = {
type: (this.options.auth.type || '').toString().toUpperCase() || 'LOGIN',
user: this.options.auth.user,
credentials: {
user: this.options.auth.user || '',
pass: this.options.auth.pass,
options: this.options.auth.options
},
method: (this.options.auth.method || '').trim().toUpperCase() || this.options.authMethod || false
};
}
}
this._connection = false;
this._connected = false;
this.messages = 0;
this.available = true;
}
/**
* Initiates a connection to the SMTP server
*
* @param {Function} callback Callback function to run once the connection is established or failed
*/ connect(callback) {
this.pool.getSocket(this.options, (err, socketOptions)=>{
if (err) {
return callback(err);
}
let returned = false;
let options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info({
tnx: 'proxy',
remoteAddress: socketOptions.connection.remoteAddress,
remotePort: socketOptions.connection.remotePort,
destHost: options.host || '',
destPort: options.port || '',
action: 'connected'
}, 'Using proxied socket from %s:%s to %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort, options.host || '', options.port || '');
options = assign(false, options);
Object.keys(socketOptions).forEach((key)=>{
options[key] = socketOptions[key];
});
}
this.connection = new SMTPConnection(options);
this.connection.once('error', (err)=>{
this.emit('error', err);
if (returned) {
return;
}
returned = true;
return callback(err);
});
this.connection.once('end', ()=>{
this.close();
if (returned) {
return;
}
returned = true;
let timer = setTimeout(()=>{
if (returned) {
return;
}
// still have not returned, this means we have an unexpected connection close
let err = new Error('Unexpected socket close');
if (this.connection && this.connection._socket && this.connection._socket.upgrading) {
// starttls connection errors
err.code = 'ETLS';
}
callback(err);
}, 1000);
try {
timer.unref();
} catch (_E) {
// Ignore. Happens on envs with non-node timer implementation
}
});
this.connection.connect(()=>{
if (returned) {
return;
}
if (this.auth && (this.connection.allowsAuth || options.forceAuth)) {
this.connection.login(this.auth, (err)=>{
if (returned) {
return;
}
returned = true;
if (err) {
this.connection.close();
this.emit('error', err);
return callback(err);
}
this._connected = true;
callback(null, true);
});
} else {
returned = true;
this._connected = true;
return callback(null, true);
}
});
});
}
/**
* Sends an e-mail to be sent using the selected settings
*
* @param {Object} mail Mail object
* @param {Function} callback Callback function
*/ send(mail, callback) {
if (!this._connected) {
return this.connect((err)=>{
if (err) {
return callback(err);
}
return this.send(mail, callback);
});
}
let envelope = mail.message.getEnvelope();
let messageId = mail.message.messageId();
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info({
tnx: 'send',
messageId,
cid: this.id
}, 'Sending message %s using #%s to <%s>', messageId, this.id, recipients.join(', '));
if (mail.data.dsn) {
envelope.dsn = mail.data.dsn;
}
this.connection.send(envelope, mail.message.createReadStream(), (err, info)=>{
this.messages++;
if (err) {
this.connection.close();
this.emit('error', err);
return callback(err);
}
info.envelope = {
from: envelope.from,
to: envelope.to
};
info.messageId = messageId;
setImmediate(()=>{
let err;
if (this.messages >= this.options.maxMessages) {
err = new Error('Resource exhausted');
err.code = 'EMAXLIMIT';
this.connection.close();
this.emit('error', err);
} else {
this.pool._checkRateLimit(()=>{
this.available = true;
this.emit('available');
});
}
});
callback(null, info);
});
}
/**
* Closes the connection
*/ close() {
this._connected = false;
if (this.auth && this.auth.oauth2) {
this.auth.oauth2.removeAllListeners();
}
if (this.connection) {
this.connection.close();
}
this.emit('close');
}
}
module.exports = PoolResource;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/well-known/services.json (json)", ((__turbopack_context__) => {
__turbopack_context__.v(JSON.parse("{\"1und1\":{\"description\":\"1&1 Mail (German hosting provider)\",\"host\":\"smtp.1und1.de\",\"port\":465,\"secure\":true,\"authMethod\":\"LOGIN\"},\"126\":{\"description\":\"126 Mail (NetEase)\",\"host\":\"smtp.126.com\",\"port\":465,\"secure\":true},\"163\":{\"description\":\"163 Mail (NetEase)\",\"host\":\"smtp.163.com\",\"port\":465,\"secure\":true},\"Aliyun\":{\"description\":\"Alibaba Cloud Mail\",\"domains\":[\"aliyun.com\"],\"host\":\"smtp.aliyun.com\",\"port\":465,\"secure\":true},\"AliyunQiye\":{\"description\":\"Alibaba Cloud Enterprise Mail\",\"host\":\"smtp.qiye.aliyun.com\",\"port\":465,\"secure\":true},\"AOL\":{\"description\":\"AOL Mail\",\"domains\":[\"aol.com\"],\"host\":\"smtp.aol.com\",\"port\":587},\"Aruba\":{\"description\":\"Aruba PEC (Italian email provider)\",\"domains\":[\"aruba.it\",\"pec.aruba.it\"],\"aliases\":[\"Aruba PEC\"],\"host\":\"smtps.aruba.it\",\"port\":465,\"secure\":true,\"authMethod\":\"LOGIN\"},\"Bluewin\":{\"description\":\"Bluewin (Swiss email provider)\",\"host\":\"smtpauths.bluewin.ch\",\"domains\":[\"bluewin.ch\"],\"port\":465},\"BOL\":{\"description\":\"BOL Mail (Brazilian provider)\",\"domains\":[\"bol.com.br\"],\"host\":\"smtp.bol.com.br\",\"port\":587,\"requireTLS\":true},\"DebugMail\":{\"description\":\"DebugMail (email testing service)\",\"host\":\"debugmail.io\",\"port\":25},\"Disroot\":{\"description\":\"Disroot (privacy-focused provider)\",\"domains\":[\"disroot.org\"],\"host\":\"disroot.org\",\"port\":587,\"secure\":false,\"authMethod\":\"LOGIN\"},\"DynectEmail\":{\"description\":\"Dyn Email Delivery\",\"aliases\":[\"Dynect\"],\"host\":\"smtp.dynect.net\",\"port\":25},\"ElasticEmail\":{\"description\":\"Elastic Email\",\"aliases\":[\"Elastic Email\"],\"host\":\"smtp.elasticemail.com\",\"port\":465,\"secure\":true},\"Ethereal\":{\"description\":\"Ethereal Email (email testing service)\",\"aliases\":[\"ethereal.email\"],\"host\":\"smtp.ethereal.email\",\"port\":587},\"FastMail\":{\"description\":\"FastMail\",\"domains\":[\"fastmail.fm\"],\"host\":\"smtp.fastmail.com\",\"port\":465,\"secure\":true},\"Feishu Mail\":{\"description\":\"Feishu Mail (Lark)\",\"aliases\":[\"Feishu\",\"FeishuMail\"],\"domains\":[\"www.feishu.cn\"],\"host\":\"smtp.feishu.cn\",\"port\":465,\"secure\":true},\"Forward Email\":{\"description\":\"Forward Email (email forwarding service)\",\"aliases\":[\"FE\",\"ForwardEmail\"],\"domains\":[\"forwardemail.net\"],\"host\":\"smtp.forwardemail.net\",\"port\":465,\"secure\":true},\"GandiMail\":{\"description\":\"Gandi Mail\",\"aliases\":[\"Gandi\",\"Gandi Mail\"],\"host\":\"mail.gandi.net\",\"port\":587},\"Gmail\":{\"description\":\"Gmail\",\"aliases\":[\"Google Mail\"],\"domains\":[\"gmail.com\",\"googlemail.com\"],\"host\":\"smtp.gmail.com\",\"port\":465,\"secure\":true},\"GMX\":{\"description\":\"GMX Mail\",\"domains\":[\"gmx.com\",\"gmx.net\",\"gmx.de\"],\"host\":\"mail.gmx.com\",\"port\":587},\"Godaddy\":{\"description\":\"GoDaddy Email (US)\",\"host\":\"smtpout.secureserver.net\",\"port\":25},\"GodaddyAsia\":{\"description\":\"GoDaddy Email (Asia)\",\"host\":\"smtp.asia.secureserver.net\",\"port\":25},\"GodaddyEurope\":{\"description\":\"GoDaddy Email (Europe)\",\"host\":\"smtp.europe.secureserver.net\",\"port\":25},\"hot.ee\":{\"description\":\"Hot.ee (Estonian email provider)\",\"host\":\"mail.hot.ee\"},\"Hotmail\":{\"description\":\"Outlook.com / Hotmail\",\"aliases\":[\"Outlook\",\"Outlook.com\",\"Hotmail.com\"],\"domains\":[\"hotmail.com\",\"outlook.com\"],\"host\":\"smtp-mail.outlook.com\",\"port\":587},\"iCloud\":{\"description\":\"iCloud Mail\",\"aliases\":[\"Me\",\"Mac\"],\"domains\":[\"me.com\",\"mac.com\"],\"host\":\"smtp.mail.me.com\",\"port\":587},\"Infomaniak\":{\"description\":\"Infomaniak Mail (Swiss hosting provider)\",\"host\":\"mail.infomaniak.com\",\"domains\":[\"ik.me\",\"ikmail.com\",\"etik.com\"],\"port\":587},\"KolabNow\":{\"description\":\"KolabNow (secure email service)\",\"domains\":[\"kolabnow.com\"],\"aliases\":[\"Kolab\"],\"host\":\"smtp.kolabnow.com\",\"port\":465,\"secure\":true,\"authMethod\":\"LOGIN\"},\"Loopia\":{\"description\":\"Loopia (Swedish hosting provider)\",\"host\":\"mailcluster.loopia.se\",\"port\":465},\"Loops\":{\"description\":\"Loops\",\"host\":\"smtp.loops.so\",\"port\":587},\"mail.ee\":{\"description\":\"Mail.ee (Estonian email provider)\",\"host\":\"smtp.mail.ee\"},\"Mail.ru\":{\"description\":\"Mail.ru\",\"host\":\"smtp.mail.ru\",\"port\":465,\"secure\":true},\"Mailcatch.app\":{\"description\":\"Mailcatch (email testing service)\",\"host\":\"sandbox-smtp.mailcatch.app\",\"port\":2525},\"Maildev\":{\"description\":\"MailDev (local email testing)\",\"port\":1025,\"ignoreTLS\":true},\"MailerSend\":{\"description\":\"MailerSend\",\"host\":\"smtp.mailersend.net\",\"port\":587},\"Mailgun\":{\"description\":\"Mailgun\",\"host\":\"smtp.mailgun.org\",\"port\":465,\"secure\":true},\"Mailjet\":{\"description\":\"Mailjet\",\"host\":\"in.mailjet.com\",\"port\":587},\"Mailosaur\":{\"description\":\"Mailosaur (email testing service)\",\"host\":\"mailosaur.io\",\"port\":25},\"Mailtrap\":{\"description\":\"Mailtrap\",\"host\":\"live.smtp.mailtrap.io\",\"port\":587},\"Mandrill\":{\"description\":\"Mandrill (by Mailchimp)\",\"host\":\"smtp.mandrillapp.com\",\"port\":587},\"Naver\":{\"description\":\"Naver Mail (Korean email provider)\",\"host\":\"smtp.naver.com\",\"port\":587},\"OhMySMTP\":{\"description\":\"OhMySMTP (email delivery service)\",\"host\":\"smtp.ohmysmtp.com\",\"port\":587,\"secure\":false},\"One\":{\"description\":\"One.com Email\",\"host\":\"send.one.com\",\"port\":465,\"secure\":true},\"OpenMailBox\":{\"description\":\"OpenMailBox\",\"aliases\":[\"OMB\",\"openmailbox.org\"],\"host\":\"smtp.openmailbox.org\",\"port\":465,\"secure\":true},\"Outlook365\":{\"description\":\"Microsoft 365 / Office 365\",\"host\":\"smtp.office365.com\",\"port\":587,\"secure\":false},\"Postmark\":{\"description\":\"Postmark\",\"aliases\":[\"PostmarkApp\"],\"host\":\"smtp.postmarkapp.com\",\"port\":2525},\"Proton\":{\"description\":\"Proton Mail\",\"aliases\":[\"ProtonMail\",\"Proton.me\",\"Protonmail.com\",\"Protonmail.ch\"],\"domains\":[\"proton.me\",\"protonmail.com\",\"pm.me\",\"protonmail.ch\"],\"host\":\"smtp.protonmail.ch\",\"port\":587,\"requireTLS\":true},\"qiye.aliyun\":{\"description\":\"Alibaba Mail Enterprise Edition\",\"host\":\"smtp.mxhichina.com\",\"port\":\"465\",\"secure\":true},\"QQ\":{\"description\":\"QQ Mail\",\"domains\":[\"qq.com\"],\"host\":\"smtp.qq.com\",\"port\":465,\"secure\":true},\"QQex\":{\"description\":\"QQ Enterprise Mail\",\"aliases\":[\"QQ Enterprise\"],\"domains\":[\"exmail.qq.com\"],\"host\":\"smtp.exmail.qq.com\",\"port\":465,\"secure\":true},\"Resend\":{\"description\":\"Resend\",\"host\":\"smtp.resend.com\",\"port\":465,\"secure\":true},\"Runbox\":{\"description\":\"Runbox (Norwegian email provider)\",\"domains\":[\"runbox.com\"],\"host\":\"smtp.runbox.com\",\"port\":465,\"secure\":true},\"SendCloud\":{\"description\":\"SendCloud (Chinese email delivery)\",\"host\":\"smtp.sendcloud.net\",\"port\":2525},\"SendGrid\":{\"description\":\"SendGrid\",\"host\":\"smtp.sendgrid.net\",\"port\":587},\"SendinBlue\":{\"description\":\"Brevo (formerly Sendinblue)\",\"aliases\":[\"Brevo\"],\"host\":\"smtp-relay.brevo.com\",\"port\":587},\"SendPulse\":{\"description\":\"SendPulse\",\"host\":\"smtp-pulse.com\",\"port\":465,\"secure\":true},\"SES\":{\"description\":\"AWS SES US East (N. Virginia)\",\"host\":\"email-smtp.us-east-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-NORTHEAST-1\":{\"description\":\"AWS SES Asia Pacific (Tokyo)\",\"host\":\"email-smtp.ap-northeast-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-NORTHEAST-2\":{\"description\":\"AWS SES Asia Pacific (Seoul)\",\"host\":\"email-smtp.ap-northeast-2.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-NORTHEAST-3\":{\"description\":\"AWS SES Asia Pacific (Osaka)\",\"host\":\"email-smtp.ap-northeast-3.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-SOUTH-1\":{\"description\":\"AWS SES Asia Pacific (Mumbai)\",\"host\":\"email-smtp.ap-south-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-SOUTHEAST-1\":{\"description\":\"AWS SES Asia Pacific (Singapore)\",\"host\":\"email-smtp.ap-southeast-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-AP-SOUTHEAST-2\":{\"description\":\"AWS SES Asia Pacific (Sydney)\",\"host\":\"email-smtp.ap-southeast-2.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-CA-CENTRAL-1\":{\"description\":\"AWS SES Canada (Central)\",\"host\":\"email-smtp.ca-central-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-EU-CENTRAL-1\":{\"description\":\"AWS SES Europe (Frankfurt)\",\"host\":\"email-smtp.eu-central-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-EU-NORTH-1\":{\"description\":\"AWS SES Europe (Stockholm)\",\"host\":\"email-smtp.eu-north-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-EU-WEST-1\":{\"description\":\"AWS SES Europe (Ireland)\",\"host\":\"email-smtp.eu-west-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-EU-WEST-2\":{\"description\":\"AWS SES Europe (London)\",\"host\":\"email-smtp.eu-west-2.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-EU-WEST-3\":{\"description\":\"AWS SES Europe (Paris)\",\"host\":\"email-smtp.eu-west-3.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-SA-EAST-1\":{\"description\":\"AWS SES South America (São Paulo)\",\"host\":\"email-smtp.sa-east-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-EAST-1\":{\"description\":\"AWS SES US East (N. Virginia)\",\"host\":\"email-smtp.us-east-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-EAST-2\":{\"description\":\"AWS SES US East (Ohio)\",\"host\":\"email-smtp.us-east-2.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-GOV-EAST-1\":{\"description\":\"AWS SES GovCloud (US-East)\",\"host\":\"email-smtp.us-gov-east-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-GOV-WEST-1\":{\"description\":\"AWS SES GovCloud (US-West)\",\"host\":\"email-smtp.us-gov-west-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-WEST-1\":{\"description\":\"AWS SES US West (N. California)\",\"host\":\"email-smtp.us-west-1.amazonaws.com\",\"port\":465,\"secure\":true},\"SES-US-WEST-2\":{\"description\":\"AWS SES US West (Oregon)\",\"host\":\"email-smtp.us-west-2.amazonaws.com\",\"port\":465,\"secure\":true},\"Seznam\":{\"description\":\"Seznam Email (Czech email provider)\",\"aliases\":[\"Seznam Email\"],\"domains\":[\"seznam.cz\",\"email.cz\",\"post.cz\",\"spoluzaci.cz\"],\"host\":\"smtp.seznam.cz\",\"port\":465,\"secure\":true},\"SMTP2GO\":{\"description\":\"SMTP2GO\",\"host\":\"mail.smtp2go.com\",\"port\":2525},\"Sparkpost\":{\"description\":\"SparkPost\",\"aliases\":[\"SparkPost\",\"SparkPost Mail\"],\"domains\":[\"sparkpost.com\"],\"host\":\"smtp.sparkpostmail.com\",\"port\":587,\"secure\":false},\"Tipimail\":{\"description\":\"Tipimail (email delivery service)\",\"host\":\"smtp.tipimail.com\",\"port\":587},\"Tutanota\":{\"description\":\"Tutanota (Tuta Mail)\",\"domains\":[\"tutanota.com\",\"tuta.com\",\"tutanota.de\",\"tuta.io\"],\"host\":\"smtp.tutanota.com\",\"port\":465,\"secure\":true},\"Yahoo\":{\"description\":\"Yahoo Mail\",\"domains\":[\"yahoo.com\"],\"host\":\"smtp.mail.yahoo.com\",\"port\":465,\"secure\":true},\"Yandex\":{\"description\":\"Yandex Mail\",\"domains\":[\"yandex.ru\"],\"host\":\"smtp.yandex.ru\",\"port\":465,\"secure\":true},\"Zimbra\":{\"description\":\"Zimbra Mail Server\",\"aliases\":[\"Zimbra Collaboration\"],\"host\":\"smtp.zimbra.com\",\"port\":587,\"requireTLS\":true},\"Zoho\":{\"description\":\"Zoho Mail\",\"host\":\"smtp.zoho.com\",\"port\":465,\"secure\":true,\"authMethod\":\"LOGIN\"}}"));}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/well-known/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const services = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/well-known/services.json (json)");
const normalized = {};
Object.keys(services).forEach((key)=>{
let service = services[key];
normalized[normalizeKey(key)] = normalizeService(service);
[].concat(service.aliases || []).forEach((alias)=>{
normalized[normalizeKey(alias)] = normalizeService(service);
});
[].concat(service.domains || []).forEach((domain)=>{
normalized[normalizeKey(domain)] = normalizeService(service);
});
});
function normalizeKey(key) {
return key.replace(/[^a-zA-Z0-9.-]/g, '').toLowerCase();
}
function normalizeService(service) {
let filter = [
'domains',
'aliases'
];
let response = {};
Object.keys(service).forEach((key)=>{
if (filter.indexOf(key) < 0) {
response[key] = service[key];
}
});
return response;
}
/**
* Resolves SMTP config for given key. Key can be a name (like 'Gmail'), alias (like 'Google Mail') or
* an email address (like 'test@googlemail.com').
*
* @param {String} key [description]
* @returns {Object} SMTP config or false if not found
*/ module.exports = function(key) {
key = normalizeKey(key.split('@').pop());
return normalized[key] || false;
};
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-pool/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const EventEmitter = __turbopack_context__.r("[externals]/events [external] (events, cjs)");
const PoolResource = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-pool/pool-resource.js [app-route] (ecmascript)");
const SMTPConnection = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-connection/index.js [app-route] (ecmascript)");
const wellKnown = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/well-known/index.js [app-route] (ecmascript)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
/**
* Creates a SMTP pool transport object for Nodemailer
*
* @constructor
* @param {Object} options SMTP Connection options
*/ class SMTPPool extends EventEmitter {
constructor(options){
super();
options = options || {};
if (typeof options === 'string') {
options = {
url: options
};
}
let urlData;
let service = options.service;
if (typeof options.getSocket === 'function') {
this.getSocket = options.getSocket;
}
if (options.url) {
urlData = shared.parseConnectionUrl(options.url);
service = service || urlData.service;
}
this.options = shared.assign(false, options, urlData, service && wellKnown(service) // wellknown options
);
this.options.maxConnections = this.options.maxConnections || 5;
this.options.maxMessages = this.options.maxMessages || 100;
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'smtp-pool'
});
// temporary object
let connection = new SMTPConnection(this.options);
this.name = 'SMTP (pool)';
this.version = packageData.version + '[client:' + connection.version + ']';
this._rateLimit = {
counter: 0,
timeout: null,
waiting: [],
checkpoint: false,
delta: Number(this.options.rateDelta) || 1000,
limit: Number(this.options.rateLimit) || 0
};
this._closed = false;
this._queue = [];
this._connections = [];
this._connectionCounter = 0;
this.idling = true;
setImmediate(()=>{
if (this.idling) {
this.emit('idle');
}
});
}
/**
* Placeholder function for creating proxy sockets. This method immediatelly returns
* without a socket
*
* @param {Object} options Connection options
* @param {Function} callback Callback function to run with the socket keys
*/ getSocket(options, callback) {
// return immediatelly
return setImmediate(()=>callback(null, false));
}
/**
* Queues an e-mail to be sent using the selected settings
*
* @param {Object} mail Mail object
* @param {Function} callback Callback function
*/ send(mail, callback) {
if (this._closed) {
return false;
}
this._queue.push({
mail,
requeueAttempts: 0,
callback
});
if (this.idling && this._queue.length >= this.options.maxConnections) {
this.idling = false;
}
setImmediate(()=>this._processMessages());
return true;
}
/**
* Closes all connections in the pool. If there is a message being sent, the connection
* is closed later
*/ close() {
let connection;
let len = this._connections.length;
this._closed = true;
// clear rate limit timer if it exists
clearTimeout(this._rateLimit.timeout);
if (!len && !this._queue.length) {
return;
}
// remove all available connections
for(let i = len - 1; i >= 0; i--){
if (this._connections[i] && this._connections[i].available) {
connection = this._connections[i];
connection.close();
this.logger.info({
tnx: 'connection',
cid: connection.id,
action: 'removed'
}, 'Connection #%s removed', connection.id);
}
}
if (len && !this._connections.length) {
this.logger.debug({
tnx: 'connection'
}, 'All connections removed');
}
if (!this._queue.length) {
return;
}
// make sure that entire queue would be cleaned
let invokeCallbacks = ()=>{
if (!this._queue.length) {
this.logger.debug({
tnx: 'connection'
}, 'Pending queue entries cleared');
return;
}
let entry = this._queue.shift();
if (entry && typeof entry.callback === 'function') {
try {
entry.callback(new Error('Connection pool was closed'));
} catch (E) {
this.logger.error({
err: E,
tnx: 'callback',
cid: connection.id
}, 'Callback error for #%s: %s', connection.id, E.message);
}
}
setImmediate(invokeCallbacks);
};
setImmediate(invokeCallbacks);
}
/**
* Check the queue and available connections. If there is a message to be sent and there is
* an available connection, then use this connection to send the mail
*/ _processMessages() {
let connection;
let i, len;
// do nothing if already closed
if (this._closed) {
return;
}
// do nothing if queue is empty
if (!this._queue.length) {
if (!this.idling) {
// no pending jobs
this.idling = true;
this.emit('idle');
}
return;
}
// find first available connection
for(i = 0, len = this._connections.length; i < len; i++){
if (this._connections[i].available) {
connection = this._connections[i];
break;
}
}
if (!connection && this._connections.length < this.options.maxConnections) {
connection = this._createConnection();
}
if (!connection) {
// no more free connection slots available
this.idling = false;
return;
}
// check if there is free space in the processing queue
if (!this.idling && this._queue.length < this.options.maxConnections) {
this.idling = true;
this.emit('idle');
}
let entry = connection.queueEntry = this._queue.shift();
entry.messageId = (connection.queueEntry.mail.message.getHeader('message-id') || '').replace(/[<>\s]/g, '');
connection.available = false;
this.logger.debug({
tnx: 'pool',
cid: connection.id,
messageId: entry.messageId,
action: 'assign'
}, 'Assigned message <%s> to #%s (%s)', entry.messageId, connection.id, connection.messages + 1);
if (this._rateLimit.limit) {
this._rateLimit.counter++;
if (!this._rateLimit.checkpoint) {
this._rateLimit.checkpoint = Date.now();
}
}
connection.send(entry.mail, (err, info)=>{
// only process callback if current handler is not changed
if (entry === connection.queueEntry) {
try {
entry.callback(err, info);
} catch (E) {
this.logger.error({
err: E,
tnx: 'callback',
cid: connection.id
}, 'Callback error for #%s: %s', connection.id, E.message);
}
connection.queueEntry = false;
}
});
}
/**
* Creates a new pool resource
*/ _createConnection() {
let connection = new PoolResource(this);
connection.id = ++this._connectionCounter;
this.logger.info({
tnx: 'pool',
cid: connection.id,
action: 'conection'
}, 'Created new pool resource #%s', connection.id);
// resource comes available
connection.on('available', ()=>{
this.logger.debug({
tnx: 'connection',
cid: connection.id,
action: 'available'
}, 'Connection #%s became available', connection.id);
if (this._closed) {
// if already closed run close() that will remove this connections from connections list
this.close();
} else {
// check if there's anything else to send
this._processMessages();
}
});
// resource is terminated with an error
connection.once('error', (err)=>{
if (err.code !== 'EMAXLIMIT') {
this.logger.error({
err,
tnx: 'pool',
cid: connection.id
}, 'Pool Error for #%s: %s', connection.id, err.message);
} else {
this.logger.debug({
tnx: 'pool',
cid: connection.id,
action: 'maxlimit'
}, 'Max messages limit exchausted for #%s', connection.id);
}
if (connection.queueEntry) {
try {
connection.queueEntry.callback(err);
} catch (E) {
this.logger.error({
err: E,
tnx: 'callback',
cid: connection.id
}, 'Callback error for #%s: %s', connection.id, E.message);
}
connection.queueEntry = false;
}
// remove the erroneus connection from connections list
this._removeConnection(connection);
this._continueProcessing();
});
connection.once('close', ()=>{
this.logger.info({
tnx: 'connection',
cid: connection.id,
action: 'closed'
}, 'Connection #%s was closed', connection.id);
this._removeConnection(connection);
if (connection.queueEntry) {
// If the connection closed when sending, add the message to the queue again
// if max number of requeues is not reached yet
// Note that we must wait a bit.. because the callback of the 'error' handler might be called
// in the next event loop
setTimeout(()=>{
if (connection.queueEntry) {
if (this._shouldRequeuOnConnectionClose(connection.queueEntry)) {
this._requeueEntryOnConnectionClose(connection);
} else {
this._failDeliveryOnConnectionClose(connection);
}
}
this._continueProcessing();
}, 50);
} else {
if (!this._closed && this.idling && !this._connections.length) {
this.emit('clear');
}
this._continueProcessing();
}
});
this._connections.push(connection);
return connection;
}
_shouldRequeuOnConnectionClose(queueEntry) {
if (this.options.maxRequeues === undefined || this.options.maxRequeues < 0) {
return true;
}
return queueEntry.requeueAttempts < this.options.maxRequeues;
}
_failDeliveryOnConnectionClose(connection) {
if (connection.queueEntry && connection.queueEntry.callback) {
try {
connection.queueEntry.callback(new Error('Reached maximum number of retries after connection was closed'));
} catch (E) {
this.logger.error({
err: E,
tnx: 'callback',
messageId: connection.queueEntry.messageId,
cid: connection.id
}, 'Callback error for #%s: %s', connection.id, E.message);
}
connection.queueEntry = false;
}
}
_requeueEntryOnConnectionClose(connection) {
connection.queueEntry.requeueAttempts = connection.queueEntry.requeueAttempts + 1;
this.logger.debug({
tnx: 'pool',
cid: connection.id,
messageId: connection.queueEntry.messageId,
action: 'requeue'
}, 'Re-queued message <%s> for #%s. Attempt: #%s', connection.queueEntry.messageId, connection.id, connection.queueEntry.requeueAttempts);
this._queue.unshift(connection.queueEntry);
connection.queueEntry = false;
}
/**
* Continue to process message if the pool hasn't closed
*/ _continueProcessing() {
if (this._closed) {
this.close();
} else {
setTimeout(()=>this._processMessages(), 100);
}
}
/**
* Remove resource from pool
*
* @param {Object} connection The PoolResource to remove
*/ _removeConnection(connection) {
let index = this._connections.indexOf(connection);
if (index !== -1) {
this._connections.splice(index, 1);
}
}
/**
* Checks if connections have hit current rate limit and if so, queues the availability callback
*
* @param {Function} callback Callback function to run once rate limiter has been cleared
*/ _checkRateLimit(callback) {
if (!this._rateLimit.limit) {
return callback();
}
let now = Date.now();
if (this._rateLimit.counter < this._rateLimit.limit) {
return callback();
}
this._rateLimit.waiting.push(callback);
if (this._rateLimit.checkpoint <= now - this._rateLimit.delta) {
return this._clearRateLimit();
} else if (!this._rateLimit.timeout) {
this._rateLimit.timeout = setTimeout(()=>this._clearRateLimit(), this._rateLimit.delta - (now - this._rateLimit.checkpoint));
this._rateLimit.checkpoint = now;
}
}
/**
* Clears current rate limit limitation and runs paused callback
*/ _clearRateLimit() {
clearTimeout(this._rateLimit.timeout);
this._rateLimit.timeout = null;
this._rateLimit.counter = 0;
this._rateLimit.checkpoint = false;
// resume all paused connections
while(this._rateLimit.waiting.length){
let cb = this._rateLimit.waiting.shift();
setImmediate(cb);
}
}
/**
* Returns true if there are free slots in the queue
*/ isIdle() {
return this.idling;
}
/**
* Verifies SMTP configuration
*
* @param {Function} callback Callback function
*/ verify(callback) {
let promise;
if (!callback) {
promise = new Promise((resolve, reject)=>{
callback = shared.callbackPromise(resolve, reject);
});
}
let auth = new PoolResource(this).auth;
this.getSocket(this.options, (err, socketOptions)=>{
if (err) {
return callback(err);
}
let options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info({
tnx: 'proxy',
remoteAddress: socketOptions.connection.remoteAddress,
remotePort: socketOptions.connection.remotePort,
destHost: options.host || '',
destPort: options.port || '',
action: 'connected'
}, 'Using proxied socket from %s:%s to %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort, options.host || '', options.port || '');
options = shared.assign(false, options);
Object.keys(socketOptions).forEach((key)=>{
options[key] = socketOptions[key];
});
}
let connection = new SMTPConnection(options);
let returned = false;
connection.once('error', (err)=>{
if (returned) {
return;
}
returned = true;
connection.close();
return callback(err);
});
connection.once('end', ()=>{
if (returned) {
return;
}
returned = true;
return callback(new Error('Connection closed'));
});
let finalize = ()=>{
if (returned) {
return;
}
returned = true;
connection.quit();
return callback(null, true);
};
connection.connect(()=>{
if (returned) {
return;
}
if (auth && (connection.allowsAuth || options.forceAuth)) {
connection.login(auth, (err)=>{
if (returned) {
return;
}
if (err) {
returned = true;
connection.close();
return callback(err);
}
finalize();
});
} else if (!auth && connection.allowsAuth && options.forceAuth) {
let err = new Error('Authentication info was not provided');
err.code = 'NoAuth';
returned = true;
connection.close();
return callback(err);
} else {
finalize();
}
});
});
return promise;
}
}
// expose to the world
module.exports = SMTPPool;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-transport/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const EventEmitter = __turbopack_context__.r("[externals]/events [external] (events, cjs)");
const SMTPConnection = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-connection/index.js [app-route] (ecmascript)");
const wellKnown = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/well-known/index.js [app-route] (ecmascript)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
const XOAuth2 = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/xoauth2/index.js [app-route] (ecmascript)");
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
/**
* Creates a SMTP transport object for Nodemailer
*
* @constructor
* @param {Object} options Connection options
*/ class SMTPTransport extends EventEmitter {
constructor(options){
super();
options = options || {};
if (typeof options === 'string') {
options = {
url: options
};
}
let urlData;
let service = options.service;
if (typeof options.getSocket === 'function') {
this.getSocket = options.getSocket;
}
if (options.url) {
urlData = shared.parseConnectionUrl(options.url);
service = service || urlData.service;
}
this.options = shared.assign(false, options, urlData, service && wellKnown(service) // wellknown options
);
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'smtp-transport'
});
// temporary object
let connection = new SMTPConnection(this.options);
this.name = 'SMTP';
this.version = packageData.version + '[client:' + connection.version + ']';
if (this.options.auth) {
this.auth = this.getAuth({});
}
}
/**
* Placeholder function for creating proxy sockets. This method immediatelly returns
* without a socket
*
* @param {Object} options Connection options
* @param {Function} callback Callback function to run with the socket keys
*/ getSocket(options, callback) {
// return immediatelly
return setImmediate(()=>callback(null, false));
}
getAuth(authOpts) {
if (!authOpts) {
return this.auth;
}
let hasAuth = false;
let authData = {};
if (this.options.auth && typeof this.options.auth === 'object') {
Object.keys(this.options.auth).forEach((key)=>{
hasAuth = true;
authData[key] = this.options.auth[key];
});
}
if (authOpts && typeof authOpts === 'object') {
Object.keys(authOpts).forEach((key)=>{
hasAuth = true;
authData[key] = authOpts[key];
});
}
if (!hasAuth) {
return false;
}
switch((authData.type || '').toString().toUpperCase()){
case 'OAUTH2':
{
if (!authData.service && !authData.user) {
return false;
}
let oauth2 = new XOAuth2(authData, this.logger);
oauth2.provisionCallback = this.mailer && this.mailer.get('oauth2_provision_cb') || oauth2.provisionCallback;
oauth2.on('token', (token)=>this.mailer.emit('token', token));
oauth2.on('error', (err)=>this.emit('error', err));
return {
type: 'OAUTH2',
user: authData.user,
oauth2,
method: 'XOAUTH2'
};
}
default:
return {
type: (authData.type || '').toString().toUpperCase() || 'LOGIN',
user: authData.user,
credentials: {
user: authData.user || '',
pass: authData.pass,
options: authData.options
},
method: (authData.method || '').trim().toUpperCase() || this.options.authMethod || false
};
}
}
/**
* Sends an e-mail using the selected settings
*
* @param {Object} mail Mail object
* @param {Function} callback Callback function
*/ send(mail, callback) {
this.getSocket(this.options, (err, socketOptions)=>{
if (err) {
return callback(err);
}
let returned = false;
let options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info({
tnx: 'proxy',
remoteAddress: socketOptions.connection.remoteAddress,
remotePort: socketOptions.connection.remotePort,
destHost: options.host || '',
destPort: options.port || '',
action: 'connected'
}, 'Using proxied socket from %s:%s to %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort, options.host || '', options.port || '');
// only copy options if we need to modify it
options = shared.assign(false, options);
Object.keys(socketOptions).forEach((key)=>{
options[key] = socketOptions[key];
});
}
let connection = new SMTPConnection(options);
connection.once('error', (err)=>{
if (returned) {
return;
}
returned = true;
connection.close();
return callback(err);
});
connection.once('end', ()=>{
if (returned) {
return;
}
let timer = setTimeout(()=>{
if (returned) {
return;
}
returned = true;
// still have not returned, this means we have an unexpected connection close
let err = new Error('Unexpected socket close');
if (connection && connection._socket && connection._socket.upgrading) {
// starttls connection errors
err.code = 'ETLS';
}
callback(err);
}, 1000);
try {
timer.unref();
} catch (_E) {
// Ignore. Happens on envs with non-node timer implementation
}
});
let sendMessage = ()=>{
let envelope = mail.message.getEnvelope();
let messageId = mail.message.messageId();
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
if (mail.data.dsn) {
envelope.dsn = mail.data.dsn;
}
this.logger.info({
tnx: 'send',
messageId
}, 'Sending message %s to <%s>', messageId, recipients.join(', '));
connection.send(envelope, mail.message.createReadStream(), (err, info)=>{
returned = true;
connection.close();
if (err) {
this.logger.error({
err,
tnx: 'send'
}, 'Send error for %s: %s', messageId, err.message);
return callback(err);
}
info.envelope = {
from: envelope.from,
to: envelope.to
};
info.messageId = messageId;
try {
return callback(null, info);
} catch (E) {
this.logger.error({
err: E,
tnx: 'callback'
}, 'Callback error for %s: %s', messageId, E.message);
}
});
};
connection.connect(()=>{
if (returned) {
return;
}
let auth = this.getAuth(mail.data.auth);
if (auth && (connection.allowsAuth || options.forceAuth)) {
connection.login(auth, (err)=>{
if (auth && auth !== this.auth && auth.oauth2) {
auth.oauth2.removeAllListeners();
}
if (returned) {
return;
}
if (err) {
returned = true;
connection.close();
return callback(err);
}
sendMessage();
});
} else {
sendMessage();
}
});
});
}
/**
* Verifies SMTP configuration
*
* @param {Function} callback Callback function
*/ verify(callback) {
let promise;
if (!callback) {
promise = new Promise((resolve, reject)=>{
callback = shared.callbackPromise(resolve, reject);
});
}
this.getSocket(this.options, (err, socketOptions)=>{
if (err) {
return callback(err);
}
let options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info({
tnx: 'proxy',
remoteAddress: socketOptions.connection.remoteAddress,
remotePort: socketOptions.connection.remotePort,
destHost: options.host || '',
destPort: options.port || '',
action: 'connected'
}, 'Using proxied socket from %s:%s to %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort, options.host || '', options.port || '');
options = shared.assign(false, options);
Object.keys(socketOptions).forEach((key)=>{
options[key] = socketOptions[key];
});
}
let connection = new SMTPConnection(options);
let returned = false;
connection.once('error', (err)=>{
if (returned) {
return;
}
returned = true;
connection.close();
return callback(err);
});
connection.once('end', ()=>{
if (returned) {
return;
}
returned = true;
return callback(new Error('Connection closed'));
});
let finalize = ()=>{
if (returned) {
return;
}
returned = true;
connection.quit();
return callback(null, true);
};
connection.connect(()=>{
if (returned) {
return;
}
let authData = this.getAuth({});
if (authData && (connection.allowsAuth || options.forceAuth)) {
connection.login(authData, (err)=>{
if (returned) {
return;
}
if (err) {
returned = true;
connection.close();
return callback(err);
}
finalize();
});
} else if (!authData && connection.allowsAuth && options.forceAuth) {
let err = new Error('Authentication info was not provided');
err.code = 'NoAuth';
returned = true;
connection.close();
return callback(err);
} else {
finalize();
}
});
});
return promise;
}
/**
* Releases resources
*/ close() {
if (this.auth && this.auth.oauth2) {
this.auth.oauth2.removeAllListeners();
}
this.emit('close');
}
}
// expose to the world
module.exports = SMTPTransport;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/sendmail-transport/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const spawn = __turbopack_context__.r("[externals]/child_process [external] (child_process, cjs)").spawn;
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
/**
* Generates a Transport object for Sendmail
*
* Possible options can be the following:
*
* * **path** optional path to sendmail binary
* * **newline** either 'windows' or 'unix'
* * **args** an array of arguments for the sendmail binary
*
* @constructor
* @param {Object} optional config parameter for Sendmail
*/ class SendmailTransport {
constructor(options){
options = options || {};
// use a reference to spawn for mocking purposes
this._spawn = spawn;
this.options = options || {};
this.name = 'Sendmail';
this.version = packageData.version;
this.path = 'sendmail';
this.args = false;
this.winbreak = false;
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'sendmail'
});
if (options) {
if (typeof options === 'string') {
this.path = options;
} else if (typeof options === 'object') {
if (options.path) {
this.path = options.path;
}
if (Array.isArray(options.args)) {
this.args = options.args;
}
this.winbreak = [
'win',
'windows',
'dos',
'\r\n'
].includes((options.newline || '').toString().toLowerCase());
}
}
}
/**
* Compiles a mailcomposer message and forwards it to handler that sends it.
*
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/ send(mail, done) {
// Sendmail strips this header line by itself
mail.message.keepBcc = true;
let envelope = mail.data.envelope || mail.message.getEnvelope();
let messageId = mail.message.messageId();
let args;
let sendmail;
let returned;
const hasInvalidAddresses = [].concat(envelope.from || []).concat(envelope.to || []).some((addr)=>/^-/.test(addr));
if (hasInvalidAddresses) {
return done(new Error('Can not send mail. Invalid envelope addresses.'));
}
if (this.args) {
// force -i to keep single dots
args = [
'-i'
].concat(this.args).concat(envelope.to);
} else {
args = [
'-i'
].concat(envelope.from ? [
'-f',
envelope.from
] : []).concat(envelope.to);
}
let callback = (err)=>{
if (returned) {
// ignore any additional responses, already done
return;
}
returned = true;
if (typeof done === 'function') {
if (err) {
return done(err);
} else {
return done(null, {
envelope: mail.data.envelope || mail.message.getEnvelope(),
messageId,
response: 'Messages queued for delivery'
});
}
}
};
try {
sendmail = this._spawn(this.path, args);
} catch (E) {
this.logger.error({
err: E,
tnx: 'spawn',
messageId
}, 'Error occurred while spawning sendmail. %s', E.message);
return callback(E);
}
if (sendmail) {
sendmail.on('error', (err)=>{
this.logger.error({
err,
tnx: 'spawn',
messageId
}, 'Error occurred when sending message %s. %s', messageId, err.message);
callback(err);
});
sendmail.once('exit', (code)=>{
if (!code) {
return callback();
}
let err;
if (code === 127) {
err = new Error('Sendmail command not found, process exited with code ' + code);
} else {
err = new Error('Sendmail exited with code ' + code);
}
this.logger.error({
err,
tnx: 'stdin',
messageId
}, 'Error sending message %s to sendmail. %s', messageId, err.message);
callback(err);
});
sendmail.once('close', callback);
sendmail.stdin.on('error', (err)=>{
this.logger.error({
err,
tnx: 'stdin',
messageId
}, 'Error occurred when piping message %s to sendmail. %s', messageId, err.message);
callback(err);
});
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info({
tnx: 'send',
messageId
}, 'Sending message %s to <%s>', messageId, recipients.join(', '));
let sourceStream = mail.message.createReadStream();
sourceStream.once('error', (err)=>{
this.logger.error({
err,
tnx: 'stdin',
messageId
}, 'Error occurred when generating message %s. %s', messageId, err.message);
sendmail.kill('SIGINT'); // do not deliver the message
callback(err);
});
sourceStream.pipe(sendmail.stdin);
} else {
return callback(new Error('sendmail was not found'));
}
}
}
module.exports = SendmailTransport;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/stream-transport/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
/**
* Generates a Transport object for streaming
*
* Possible options can be the following:
*
* * **buffer** if true, then returns the message as a Buffer object instead of a stream
* * **newline** either 'windows' or 'unix'
*
* @constructor
* @param {Object} optional config parameter
*/ class StreamTransport {
constructor(options){
options = options || {};
this.options = options || {};
this.name = 'StreamTransport';
this.version = packageData.version;
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'stream-transport'
});
this.winbreak = [
'win',
'windows',
'dos',
'\r\n'
].includes((options.newline || '').toString().toLowerCase());
}
/**
* Compiles a mailcomposer message and forwards it to handler that sends it
*
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/ send(mail, done) {
// We probably need this in the output
mail.message.keepBcc = true;
let envelope = mail.data.envelope || mail.message.getEnvelope();
let messageId = mail.message.messageId();
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info({
tnx: 'send',
messageId
}, 'Sending message %s to <%s> using %s line breaks', messageId, recipients.join(', '), this.winbreak ? '' : '');
setImmediate(()=>{
let stream;
try {
stream = mail.message.createReadStream();
} catch (E) {
this.logger.error({
err: E,
tnx: 'send',
messageId
}, 'Creating send stream failed for %s. %s', messageId, E.message);
return done(E);
}
if (!this.options.buffer) {
stream.once('error', (err)=>{
this.logger.error({
err,
tnx: 'send',
messageId
}, 'Failed creating message for %s. %s', messageId, err.message);
});
return done(null, {
envelope: mail.data.envelope || mail.message.getEnvelope(),
messageId,
message: stream
});
}
let chunks = [];
let chunklen = 0;
stream.on('readable', ()=>{
let chunk;
while((chunk = stream.read()) !== null){
chunks.push(chunk);
chunklen += chunk.length;
}
});
stream.once('error', (err)=>{
this.logger.error({
err,
tnx: 'send',
messageId
}, 'Failed creating message for %s. %s', messageId, err.message);
return done(err);
});
stream.on('end', ()=>done(null, {
envelope: mail.data.envelope || mail.message.getEnvelope(),
messageId,
message: Buffer.concat(chunks, chunklen)
}));
});
}
}
module.exports = StreamTransport;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/json-transport/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
/**
* Generates a Transport object to generate JSON output
*
* @constructor
* @param {Object} optional config parameter
*/ class JSONTransport {
constructor(options){
options = options || {};
this.options = options || {};
this.name = 'JSONTransport';
this.version = packageData.version;
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'json-transport'
});
}
/**
* Compiles a mailcomposer message and forwards it to handler that sends it.
*
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/ send(mail, done) {
// Sendmail strips this header line by itself
mail.message.keepBcc = true;
let envelope = mail.data.envelope || mail.message.getEnvelope();
let messageId = mail.message.messageId();
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info({
tnx: 'send',
messageId
}, 'Composing JSON structure of %s to <%s>', messageId, recipients.join(', '));
setImmediate(()=>{
mail.normalize((err, data)=>{
if (err) {
this.logger.error({
err,
tnx: 'send',
messageId
}, 'Failed building JSON structure for %s. %s', messageId, err.message);
return done(err);
}
delete data.envelope;
delete data.normalizedHeaders;
return done(null, {
envelope,
messageId,
message: this.options.skipEncoding ? data : JSON.stringify(data)
});
});
});
}
}
module.exports = JSONTransport;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/ses-transport/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const EventEmitter = __turbopack_context__.r("[externals]/events [external] (events, cjs)");
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
const LeWindows = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/mime-node/le-windows.js [app-route] (ecmascript)");
const MimeNode = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/mime-node/index.js [app-route] (ecmascript)");
/**
* Generates a Transport object for AWS SES
*
* @constructor
* @param {Object} optional config parameter
*/ class SESTransport extends EventEmitter {
constructor(options){
super();
options = options || {};
this.options = options || {};
this.ses = this.options.SES;
this.name = 'SESTransport';
this.version = packageData.version;
this.logger = shared.getLogger(this.options, {
component: this.options.component || 'ses-transport'
});
}
getRegion(cb) {
if (this.ses.sesClient.config && typeof this.ses.sesClient.config.region === 'function') {
// promise
return this.ses.sesClient.config.region().then((region)=>cb(null, region)).catch((err)=>cb(err));
}
return cb(null, false);
}
/**
* Compiles a mailcomposer message and forwards it to SES
*
* @param {Object} emailMessage MailComposer object
* @param {Function} callback Callback function to run when the sending is completed
*/ send(mail, callback) {
let statObject = {
ts: Date.now(),
pending: true
};
let fromHeader = mail.message._headers.find((header)=>/^from$/i.test(header.key));
if (fromHeader) {
let mimeNode = new MimeNode('text/plain');
fromHeader = mimeNode._convertAddresses(mimeNode._parseAddresses(fromHeader.value));
}
let envelope = mail.data.envelope || mail.message.getEnvelope();
let messageId = mail.message.messageId();
let recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info({
tnx: 'send',
messageId
}, 'Sending message %s to <%s>', messageId, recipients.join(', '));
let getRawMessage = (next)=>{
// do not use Message-ID and Date in DKIM signature
if (!mail.data._dkim) {
mail.data._dkim = {};
}
if (mail.data._dkim.skipFields && typeof mail.data._dkim.skipFields === 'string') {
mail.data._dkim.skipFields += ':date:message-id';
} else {
mail.data._dkim.skipFields = 'date:message-id';
}
let sourceStream = mail.message.createReadStream();
let stream = sourceStream.pipe(new LeWindows());
let chunks = [];
let chunklen = 0;
stream.on('readable', ()=>{
let chunk;
while((chunk = stream.read()) !== null){
chunks.push(chunk);
chunklen += chunk.length;
}
});
sourceStream.once('error', (err)=>stream.emit('error', err));
stream.once('error', (err)=>{
next(err);
});
stream.once('end', ()=>next(null, Buffer.concat(chunks, chunklen)));
};
setImmediate(()=>getRawMessage((err, raw)=>{
if (err) {
this.logger.error({
err,
tnx: 'send',
messageId
}, 'Failed creating message for %s. %s', messageId, err.message);
statObject.pending = false;
return callback(err);
}
let sesMessage = {
Content: {
Raw: {
// required
Data: raw // required
}
},
FromEmailAddress: fromHeader ? fromHeader : envelope.from,
Destination: {
ToAddresses: envelope.to
}
};
Object.keys(mail.data.ses || {}).forEach((key)=>{
sesMessage[key] = mail.data.ses[key];
});
this.getRegion((err, region)=>{
if (err || !region) {
region = 'us-east-1';
}
const command = new this.ses.SendEmailCommand(sesMessage);
const sendPromise = this.ses.sesClient.send(command);
sendPromise.then((data)=>{
if (region === 'us-east-1') {
region = 'email';
}
statObject.pending = true;
callback(null, {
envelope: {
from: envelope.from,
to: envelope.to
},
messageId: '<' + data.MessageId + (!/@/.test(data.MessageId) ? '@' + region + '.amazonses.com' : '') + '>',
response: data.MessageId,
raw
});
}).catch((err)=>{
this.logger.error({
err,
tnx: 'send'
}, 'Send error for %s: %s', messageId, err.message);
statObject.pending = false;
callback(err);
});
});
}));
}
/**
* Verifies SES configuration
*
* @param {Function} callback Callback function
*/ verify(callback) {
let promise;
if (!callback) {
promise = new Promise((resolve, reject)=>{
callback = shared.callbackPromise(resolve, reject);
});
}
const cb = (err)=>{
if (err && ![
'InvalidParameterValue',
'MessageRejected'
].includes(err.code || err.Code || err.name)) {
return callback(err);
}
return callback(null, true);
};
const sesMessage = {
Content: {
Raw: {
Data: Buffer.from('From: \r\nTo: \r\n Subject: Invalid\r\n\r\nInvalid')
}
},
FromEmailAddress: 'invalid@invalid',
Destination: {
ToAddresses: [
'invalid@invalid'
]
}
};
this.getRegion((err, region)=>{
if (err || !region) {
region = 'us-east-1';
}
const command = new this.ses.SendEmailCommand(sesMessage);
const sendPromise = this.ses.sesClient.send(command);
sendPromise.then((data)=>cb(null, data)).catch((err)=>cb(err));
});
return promise;
}
}
module.exports = SESTransport;
}),
"[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/nodemailer.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
"use strict";
const Mailer = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/mailer/index.js [app-route] (ecmascript)");
const shared = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/shared/index.js [app-route] (ecmascript)");
const SMTPPool = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-pool/index.js [app-route] (ecmascript)");
const SMTPTransport = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/smtp-transport/index.js [app-route] (ecmascript)");
const SendmailTransport = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/sendmail-transport/index.js [app-route] (ecmascript)");
const StreamTransport = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/stream-transport/index.js [app-route] (ecmascript)");
const JSONTransport = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/json-transport/index.js [app-route] (ecmascript)");
const SESTransport = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/ses-transport/index.js [app-route] (ecmascript)");
const nmfetch = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/lib/fetch/index.js [app-route] (ecmascript)");
const packageData = __turbopack_context__.r("[project]/Documents/go-new/chinese-family-tree/node_modules/.pnpm/nodemailer@7.0.10/node_modules/nodemailer/package.json (json)");
const ETHEREAL_API = (process.env.ETHEREAL_API || 'https://api.nodemailer.com').replace(/\/+$/, '');
const ETHEREAL_WEB = (process.env.ETHEREAL_WEB || 'https://ethereal.email').replace(/\/+$/, '');
const ETHEREAL_API_KEY = (process.env.ETHEREAL_API_KEY || '').replace(/\s*/g, '') || null;
const ETHEREAL_CACHE = [
'true',
'yes',
'y',
'1'
].includes((process.env.ETHEREAL_CACHE || 'yes').toString().trim().toLowerCase());
let testAccount = false;
module.exports.createTransport = function(transporter, defaults) {
let urlConfig;
let options;
let mailer;
if (// provided transporter is a configuration object, not transporter plugin
typeof transporter === 'object' && typeof transporter.send !== 'function' || typeof transporter === 'string' && /^(smtps?|direct):/i.test(transporter)) {
if (urlConfig = typeof transporter === 'string' ? transporter : transporter.url) {
// parse a configuration URL into configuration options
options = shared.parseConnectionUrl(urlConfig);
} else {
options = transporter;
}
if (options.pool) {
transporter = new SMTPPool(options);
} else if (options.sendmail) {
transporter = new SendmailTransport(options);
} else if (options.streamTransport) {
transporter = new StreamTransport(options);
} else if (options.jsonTransport) {
transporter = new JSONTransport(options);
} else if (options.SES) {
if (options.SES.ses && options.SES.aws) {
let error = new Error('Using legacy SES configuration, expecting @aws-sdk/client-sesv2, see https://nodemailer.com/transports/ses/');
error.code = 'LegacyConfig';
throw error;
}
transporter = new SESTransport(options);
} else {
transporter = new SMTPTransport(options);
}
}
mailer = new Mailer(transporter, options, defaults);
return mailer;
};
module.exports.createTestAccount = function(apiUrl, callback) {
let promise;
if (!callback && typeof apiUrl === 'function') {
callback = apiUrl;
apiUrl = false;
}
if (!callback) {
promise = new Promise((resolve, reject)=>{
callback = shared.callbackPromise(resolve, reject);
});
}
if (ETHEREAL_CACHE && testAccount) {
setImmediate(()=>callback(null, testAccount));
return promise;
}
apiUrl = apiUrl || ETHEREAL_API;
let chunks = [];
let chunklen = 0;
let requestHeaders = {};
let requestBody = {
requestor: packageData.name,
version: packageData.version
};
if (ETHEREAL_API_KEY) {
requestHeaders.Authorization = 'Bearer ' + ETHEREAL_API_KEY;
}
let req = nmfetch(apiUrl + '/user', {
contentType: 'application/json',
method: 'POST',
headers: requestHeaders,
body: Buffer.from(JSON.stringify(requestBody))
});
req.on('readable', ()=>{
let chunk;
while((chunk = req.read()) !== null){
chunks.push(chunk);
chunklen += chunk.length;
}
});
req.once('error', (err)=>callback(err));
req.once('end', ()=>{
let res = Buffer.concat(chunks, chunklen);
let data;
let err;
try {
data = JSON.parse(res.toString());
} catch (E) {
err = E;
}
if (err) {
return callback(err);
}
if (data.status !== 'success' || data.error) {
return callback(new Error(data.error || 'Request failed'));
}
delete data.status;
testAccount = data;
callback(null, testAccount);
});
return promise;
};
module.exports.getTestMessageUrl = function(info) {
if (!info || !info.response) {
return false;
}
let infoProps = new Map();
info.response.replace(/\[([^\]]+)\]$/, (m, props)=>{
props.replace(/\b([A-Z0-9]+)=([^\s]+)/g, (m, key, value)=>{
infoProps.set(key, value);
});
});
if (infoProps.has('STATUS') && infoProps.has('MSGID')) {
return (testAccount.web || ETHEREAL_WEB) + '/message/' + infoProps.get('MSGID');
}
return false;
};
}),
];
//# sourceMappingURL=cfda4_nodemailer_b9a47597._.js.map