@upyo/smtp 0.6.0-dev.299 → 0.6.0-dev.303
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +48 -14
- package/dist/index.js +48 -14
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -563,6 +563,37 @@ var SmtpPipelineTerminatedError = class extends Error {
|
|
|
563
563
|
}
|
|
564
564
|
};
|
|
565
565
|
/**
|
|
566
|
+
* An authentication failure backed by an SMTP server reply.
|
|
567
|
+
*
|
|
568
|
+
* This keeps {@link SmtpAuthError} as the public authentication error while
|
|
569
|
+
* retaining the reply fields needed to build structured transport receipts.
|
|
570
|
+
*
|
|
571
|
+
* @since 0.6.0
|
|
572
|
+
*/
|
|
573
|
+
var SmtpAuthResponseError = class extends SmtpAuthError {
|
|
574
|
+
/** The numeric SMTP reply code returned by the server. */
|
|
575
|
+
code;
|
|
576
|
+
/** The authentication command that produced the reply. */
|
|
577
|
+
command;
|
|
578
|
+
/** The textual SMTP reply returned by the server. */
|
|
579
|
+
response;
|
|
580
|
+
/**
|
|
581
|
+
* Creates an authentication response error.
|
|
582
|
+
*
|
|
583
|
+
* @param message A human-readable description of the authentication failure.
|
|
584
|
+
* @param code The numeric SMTP reply code.
|
|
585
|
+
* @param command The authentication command that produced the reply.
|
|
586
|
+
* @param response The textual SMTP reply returned by the server.
|
|
587
|
+
*/
|
|
588
|
+
constructor(message, code, command, response) {
|
|
589
|
+
super(message);
|
|
590
|
+
this.name = "SmtpAuthResponseError";
|
|
591
|
+
this.code = code;
|
|
592
|
+
this.command = command;
|
|
593
|
+
this.response = response;
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
566
597
|
* The maximum length of an SMTP command line, including the terminating CRLF,
|
|
567
598
|
* as specified by RFC 5321 §4.5.3.1.4.
|
|
568
599
|
*/
|
|
@@ -866,11 +897,11 @@ var SmtpConnection = class {
|
|
|
866
897
|
const response = await this.sendCommand(`EHLO ${this.config.localName}`, signal);
|
|
867
898
|
if (response.code === 500 || response.code === 502) {
|
|
868
899
|
const heloResponse = await this.sendCommand(`HELO ${this.config.localName}`, signal);
|
|
869
|
-
if (heloResponse.code !== 250) throw new
|
|
900
|
+
if (heloResponse.code !== 250) throw new SmtpResponseError(`HELO failed: ${heloResponse.message}`, heloResponse.code, "HELO", heloResponse.message);
|
|
870
901
|
this.capabilities = [];
|
|
871
902
|
return;
|
|
872
903
|
}
|
|
873
|
-
if (response.code !== 250) throw new
|
|
904
|
+
if (response.code !== 250) throw new SmtpResponseError(`EHLO failed: ${response.message}`, response.code, "EHLO", response.message);
|
|
874
905
|
this.capabilities = response.raw.split("\r\n").filter((line) => line.startsWith("250-") || line.startsWith("250 ")).slice(1).map((line) => line.substring(4)).filter((line) => line.length > 0);
|
|
875
906
|
}
|
|
876
907
|
async starttls(signal) {
|
|
@@ -878,7 +909,7 @@ var SmtpConnection = class {
|
|
|
878
909
|
if (this.socket instanceof node_tls.TLSSocket) throw new Error("Connection is already using TLS");
|
|
879
910
|
signal?.throwIfAborted();
|
|
880
911
|
const response = await this.sendCommand("STARTTLS", signal);
|
|
881
|
-
if (response.code !== 220) throw new
|
|
912
|
+
if (response.code !== 220) throw new SmtpResponseError(`STARTTLS failed: ${response.message}`, response.code, "STARTTLS", response.message);
|
|
882
913
|
signal?.throwIfAborted();
|
|
883
914
|
return new Promise((resolve, reject) => {
|
|
884
915
|
const timeout = setTimeout(() => {
|
|
@@ -951,16 +982,16 @@ var SmtpConnection = class {
|
|
|
951
982
|
const { user, pass } = auth;
|
|
952
983
|
const credentials = btoa(`\0${user}\0${pass}`);
|
|
953
984
|
const response = await this.sendCommand(`AUTH PLAIN ${credentials}`, signal);
|
|
954
|
-
if (response.code !== 235) throw new
|
|
985
|
+
if (response.code !== 235) throw new SmtpAuthResponseError(`Authentication failed: ${response.message}`, response.code, "AUTH PLAIN", response.message);
|
|
955
986
|
}
|
|
956
987
|
async authLogin(auth, signal) {
|
|
957
988
|
const { user, pass } = auth;
|
|
958
989
|
let response = await this.sendCommand("AUTH LOGIN", signal);
|
|
959
|
-
if (response.code !== 334) throw new
|
|
990
|
+
if (response.code !== 334) throw new SmtpAuthResponseError(`AUTH LOGIN failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
960
991
|
response = await this.sendCommand(btoa(user), signal);
|
|
961
|
-
if (response.code !== 334) throw new
|
|
992
|
+
if (response.code !== 334) throw new SmtpAuthResponseError(`Username authentication failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
962
993
|
response = await this.sendCommand(btoa(pass), signal);
|
|
963
|
-
if (response.code !== 235) throw new
|
|
994
|
+
if (response.code !== 235) throw new SmtpAuthResponseError(`Password authentication failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
964
995
|
}
|
|
965
996
|
/**
|
|
966
997
|
* Resolves an OAuth 2.0 access token via the connection's token manager,
|
|
@@ -1012,16 +1043,19 @@ var SmtpConnection = class {
|
|
|
1012
1043
|
async finishOAuth2(response, mechanism, continuation, signal) {
|
|
1013
1044
|
if (response.code === 235) return;
|
|
1014
1045
|
if (response.code === 334) {
|
|
1046
|
+
let finalResponse;
|
|
1015
1047
|
let finalMessage = "";
|
|
1016
1048
|
try {
|
|
1017
|
-
|
|
1018
|
-
finalMessage = ` (${
|
|
1049
|
+
finalResponse = await this.sendCommand(continuation, signal);
|
|
1050
|
+
finalMessage = ` (${finalResponse.message})`;
|
|
1019
1051
|
} catch {
|
|
1020
1052
|
signal?.throwIfAborted();
|
|
1021
1053
|
}
|
|
1022
|
-
|
|
1054
|
+
const message = `${mechanism} authentication failed: ${decodeOAuth2Challenge(response.message)}${finalMessage}`;
|
|
1055
|
+
if (finalResponse != null) throw new SmtpAuthResponseError(message, finalResponse.code, `AUTH ${mechanism}`, finalResponse.message);
|
|
1056
|
+
throw new SmtpAuthError(message);
|
|
1023
1057
|
}
|
|
1024
|
-
throw new
|
|
1058
|
+
throw new SmtpAuthResponseError(`${mechanism} authentication failed: ${response.message}`, response.code, `AUTH ${mechanism}`, response.message);
|
|
1025
1059
|
}
|
|
1026
1060
|
async sendMessage(message, signal) {
|
|
1027
1061
|
signal?.throwIfAborted();
|
|
@@ -1949,7 +1983,7 @@ var SmtpTransport = class {
|
|
|
1949
1983
|
await connection.connect(signal);
|
|
1950
1984
|
signal?.throwIfAborted();
|
|
1951
1985
|
const greeting = await connection.greeting(signal);
|
|
1952
|
-
if (greeting.code !== 220) throw new
|
|
1986
|
+
if (greeting.code !== 220) throw new SmtpResponseError(`Server greeting failed: ${greeting.message}`, greeting.code, "GREETING", greeting.message);
|
|
1953
1987
|
signal?.throwIfAborted();
|
|
1954
1988
|
await connection.ehlo(signal);
|
|
1955
1989
|
signal?.throwIfAborted();
|
|
@@ -2049,7 +2083,7 @@ function createSmtpFailure(message, error) {
|
|
|
2049
2083
|
attempts: 1,
|
|
2050
2084
|
providerDetails: { missingCapability: error.missingCapability }
|
|
2051
2085
|
});
|
|
2052
|
-
if (error instanceof SmtpResponseError) {
|
|
2086
|
+
if (error instanceof SmtpResponseError || error instanceof SmtpAuthResponseError) {
|
|
2053
2087
|
const enhancedStatusCode = parseEnhancedSmtpStatusCode(error.code, error.response);
|
|
2054
2088
|
const classification = classifySmtpReply(error.code, enhancedStatusCode);
|
|
2055
2089
|
return (0, __upyo_core.createFailedReceipt)(message, {
|
|
@@ -2061,7 +2095,7 @@ function createSmtpFailure(message, error) {
|
|
|
2061
2095
|
providerDetails: {
|
|
2062
2096
|
command: error.command,
|
|
2063
2097
|
response: error.response,
|
|
2064
|
-
rejectedRecipients: error.rejectedRecipients,
|
|
2098
|
+
rejectedRecipients: error instanceof SmtpResponseError ? error.rejectedRecipients : void 0,
|
|
2065
2099
|
...enhancedStatusCode == null ? {} : { enhancedStatusCode }
|
|
2066
2100
|
}
|
|
2067
2101
|
});
|
package/dist/index.js
CHANGED
|
@@ -540,6 +540,37 @@ var SmtpPipelineTerminatedError = class extends Error {
|
|
|
540
540
|
}
|
|
541
541
|
};
|
|
542
542
|
/**
|
|
543
|
+
* An authentication failure backed by an SMTP server reply.
|
|
544
|
+
*
|
|
545
|
+
* This keeps {@link SmtpAuthError} as the public authentication error while
|
|
546
|
+
* retaining the reply fields needed to build structured transport receipts.
|
|
547
|
+
*
|
|
548
|
+
* @since 0.6.0
|
|
549
|
+
*/
|
|
550
|
+
var SmtpAuthResponseError = class extends SmtpAuthError {
|
|
551
|
+
/** The numeric SMTP reply code returned by the server. */
|
|
552
|
+
code;
|
|
553
|
+
/** The authentication command that produced the reply. */
|
|
554
|
+
command;
|
|
555
|
+
/** The textual SMTP reply returned by the server. */
|
|
556
|
+
response;
|
|
557
|
+
/**
|
|
558
|
+
* Creates an authentication response error.
|
|
559
|
+
*
|
|
560
|
+
* @param message A human-readable description of the authentication failure.
|
|
561
|
+
* @param code The numeric SMTP reply code.
|
|
562
|
+
* @param command The authentication command that produced the reply.
|
|
563
|
+
* @param response The textual SMTP reply returned by the server.
|
|
564
|
+
*/
|
|
565
|
+
constructor(message, code, command, response) {
|
|
566
|
+
super(message);
|
|
567
|
+
this.name = "SmtpAuthResponseError";
|
|
568
|
+
this.code = code;
|
|
569
|
+
this.command = command;
|
|
570
|
+
this.response = response;
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
/**
|
|
543
574
|
* The maximum length of an SMTP command line, including the terminating CRLF,
|
|
544
575
|
* as specified by RFC 5321 §4.5.3.1.4.
|
|
545
576
|
*/
|
|
@@ -843,11 +874,11 @@ var SmtpConnection = class {
|
|
|
843
874
|
const response = await this.sendCommand(`EHLO ${this.config.localName}`, signal);
|
|
844
875
|
if (response.code === 500 || response.code === 502) {
|
|
845
876
|
const heloResponse = await this.sendCommand(`HELO ${this.config.localName}`, signal);
|
|
846
|
-
if (heloResponse.code !== 250) throw new
|
|
877
|
+
if (heloResponse.code !== 250) throw new SmtpResponseError(`HELO failed: ${heloResponse.message}`, heloResponse.code, "HELO", heloResponse.message);
|
|
847
878
|
this.capabilities = [];
|
|
848
879
|
return;
|
|
849
880
|
}
|
|
850
|
-
if (response.code !== 250) throw new
|
|
881
|
+
if (response.code !== 250) throw new SmtpResponseError(`EHLO failed: ${response.message}`, response.code, "EHLO", response.message);
|
|
851
882
|
this.capabilities = response.raw.split("\r\n").filter((line) => line.startsWith("250-") || line.startsWith("250 ")).slice(1).map((line) => line.substring(4)).filter((line) => line.length > 0);
|
|
852
883
|
}
|
|
853
884
|
async starttls(signal) {
|
|
@@ -855,7 +886,7 @@ var SmtpConnection = class {
|
|
|
855
886
|
if (this.socket instanceof TLSSocket) throw new Error("Connection is already using TLS");
|
|
856
887
|
signal?.throwIfAborted();
|
|
857
888
|
const response = await this.sendCommand("STARTTLS", signal);
|
|
858
|
-
if (response.code !== 220) throw new
|
|
889
|
+
if (response.code !== 220) throw new SmtpResponseError(`STARTTLS failed: ${response.message}`, response.code, "STARTTLS", response.message);
|
|
859
890
|
signal?.throwIfAborted();
|
|
860
891
|
return new Promise((resolve, reject) => {
|
|
861
892
|
const timeout = setTimeout(() => {
|
|
@@ -928,16 +959,16 @@ var SmtpConnection = class {
|
|
|
928
959
|
const { user, pass } = auth;
|
|
929
960
|
const credentials = btoa(`\0${user}\0${pass}`);
|
|
930
961
|
const response = await this.sendCommand(`AUTH PLAIN ${credentials}`, signal);
|
|
931
|
-
if (response.code !== 235) throw new
|
|
962
|
+
if (response.code !== 235) throw new SmtpAuthResponseError(`Authentication failed: ${response.message}`, response.code, "AUTH PLAIN", response.message);
|
|
932
963
|
}
|
|
933
964
|
async authLogin(auth, signal) {
|
|
934
965
|
const { user, pass } = auth;
|
|
935
966
|
let response = await this.sendCommand("AUTH LOGIN", signal);
|
|
936
|
-
if (response.code !== 334) throw new
|
|
967
|
+
if (response.code !== 334) throw new SmtpAuthResponseError(`AUTH LOGIN failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
937
968
|
response = await this.sendCommand(btoa(user), signal);
|
|
938
|
-
if (response.code !== 334) throw new
|
|
969
|
+
if (response.code !== 334) throw new SmtpAuthResponseError(`Username authentication failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
939
970
|
response = await this.sendCommand(btoa(pass), signal);
|
|
940
|
-
if (response.code !== 235) throw new
|
|
971
|
+
if (response.code !== 235) throw new SmtpAuthResponseError(`Password authentication failed: ${response.message}`, response.code, "AUTH LOGIN", response.message);
|
|
941
972
|
}
|
|
942
973
|
/**
|
|
943
974
|
* Resolves an OAuth 2.0 access token via the connection's token manager,
|
|
@@ -989,16 +1020,19 @@ var SmtpConnection = class {
|
|
|
989
1020
|
async finishOAuth2(response, mechanism, continuation, signal) {
|
|
990
1021
|
if (response.code === 235) return;
|
|
991
1022
|
if (response.code === 334) {
|
|
1023
|
+
let finalResponse;
|
|
992
1024
|
let finalMessage = "";
|
|
993
1025
|
try {
|
|
994
|
-
|
|
995
|
-
finalMessage = ` (${
|
|
1026
|
+
finalResponse = await this.sendCommand(continuation, signal);
|
|
1027
|
+
finalMessage = ` (${finalResponse.message})`;
|
|
996
1028
|
} catch {
|
|
997
1029
|
signal?.throwIfAborted();
|
|
998
1030
|
}
|
|
999
|
-
|
|
1031
|
+
const message = `${mechanism} authentication failed: ${decodeOAuth2Challenge(response.message)}${finalMessage}`;
|
|
1032
|
+
if (finalResponse != null) throw new SmtpAuthResponseError(message, finalResponse.code, `AUTH ${mechanism}`, finalResponse.message);
|
|
1033
|
+
throw new SmtpAuthError(message);
|
|
1000
1034
|
}
|
|
1001
|
-
throw new
|
|
1035
|
+
throw new SmtpAuthResponseError(`${mechanism} authentication failed: ${response.message}`, response.code, `AUTH ${mechanism}`, response.message);
|
|
1002
1036
|
}
|
|
1003
1037
|
async sendMessage(message, signal) {
|
|
1004
1038
|
signal?.throwIfAborted();
|
|
@@ -1926,7 +1960,7 @@ var SmtpTransport = class {
|
|
|
1926
1960
|
await connection.connect(signal);
|
|
1927
1961
|
signal?.throwIfAborted();
|
|
1928
1962
|
const greeting = await connection.greeting(signal);
|
|
1929
|
-
if (greeting.code !== 220) throw new
|
|
1963
|
+
if (greeting.code !== 220) throw new SmtpResponseError(`Server greeting failed: ${greeting.message}`, greeting.code, "GREETING", greeting.message);
|
|
1930
1964
|
signal?.throwIfAborted();
|
|
1931
1965
|
await connection.ehlo(signal);
|
|
1932
1966
|
signal?.throwIfAborted();
|
|
@@ -2026,7 +2060,7 @@ function createSmtpFailure(message, error) {
|
|
|
2026
2060
|
attempts: 1,
|
|
2027
2061
|
providerDetails: { missingCapability: error.missingCapability }
|
|
2028
2062
|
});
|
|
2029
|
-
if (error instanceof SmtpResponseError) {
|
|
2063
|
+
if (error instanceof SmtpResponseError || error instanceof SmtpAuthResponseError) {
|
|
2030
2064
|
const enhancedStatusCode = parseEnhancedSmtpStatusCode(error.code, error.response);
|
|
2031
2065
|
const classification = classifySmtpReply(error.code, enhancedStatusCode);
|
|
2032
2066
|
return createFailedReceipt(message, {
|
|
@@ -2038,7 +2072,7 @@ function createSmtpFailure(message, error) {
|
|
|
2038
2072
|
providerDetails: {
|
|
2039
2073
|
command: error.command,
|
|
2040
2074
|
response: error.response,
|
|
2041
|
-
rejectedRecipients: error.rejectedRecipients,
|
|
2075
|
+
rejectedRecipients: error instanceof SmtpResponseError ? error.rejectedRecipients : void 0,
|
|
2042
2076
|
...enhancedStatusCode == null ? {} : { enhancedStatusCode }
|
|
2043
2077
|
}
|
|
2044
2078
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upyo/smtp",
|
|
3
|
-
"version": "0.6.0-dev.
|
|
3
|
+
"version": "0.6.0-dev.303",
|
|
4
4
|
"description": "SMTP transport for Upyo email library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"email",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"sideEffects": false,
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@upyo/core": "0.6.0-dev.
|
|
56
|
+
"@upyo/core": "0.6.0-dev.303+d776cb0f"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"tsdown": "^0.12.7",
|