@simplysm/service-server 13.0.13 → 13.0.14

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/README.md CHANGED
@@ -47,7 +47,6 @@ pnpm add @simplysm/service-server
47
47
 
48
48
  - [`OrmService`](docs/built-in-services.md#ormservice) - DB connection/transaction/query execution (WebSocket only, auth required)
49
49
  - [`CryptoService`](docs/built-in-services.md#cryptoservice) - SHA256 hash and AES-256-CBC encryption/decryption
50
- - [`SmtpService`](docs/built-in-services.md#smtpservice) - nodemailer-based email sending
51
50
  - [`AutoUpdateService`](docs/built-in-services.md#autoupdateservice) - App auto-update (provides latest version query and download path)
52
51
 
53
52
  ### Utilities
@@ -240,19 +239,18 @@ The package provides several built-in services:
240
239
 
241
240
  - [`OrmService`](docs/built-in-services.md#ormservice) - Database operations (MySQL, MSSQL, PostgreSQL)
242
241
  - [`CryptoService`](docs/built-in-services.md#cryptoservice) - Hashing and encryption
243
- - [`SmtpService`](docs/built-in-services.md#smtpservice) - Email sending
244
242
  - [`AutoUpdateService`](docs/built-in-services.md#autoupdateservice) - Client app auto-updates
245
243
 
246
244
  Register them like any other service:
247
245
 
248
246
  ```typescript
249
- import { createServiceServer, OrmService, CryptoService, SmtpService } from "@simplysm/service-server";
247
+ import { createServiceServer, OrmService, CryptoService } from "@simplysm/service-server";
250
248
 
251
249
  const server = createServiceServer({
252
250
  port: 8080,
253
251
  rootPath: "/app/data",
254
252
  auth: { jwtSecret: "secret" },
255
- services: [OrmService, CryptoService, SmtpService],
253
+ services: [OrmService, CryptoService],
256
254
  });
257
255
  ```
258
256
 
package/dist/index.d.ts CHANGED
@@ -10,8 +10,6 @@ export * from "./transport/http/upload-handler";
10
10
  export * from "./transport/http/static-file-handler";
11
11
  export { createProtocolWrapper, type ProtocolWrapper } from "./protocol/protocol-wrapper";
12
12
  export * from "./services/orm-service";
13
- export * from "./services/crypto-service";
14
- export * from "./services/smtp-service";
15
13
  export * from "./services/auto-update-service";
16
14
  export * from "./utils/config-manager";
17
15
  export * from "./legacy/v1-auto-update-handler";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAG5F,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG1F,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAG/C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AAGvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AAGnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAG5F,cAAc,uCAAuC,CAAC;AACtD,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG1F,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAG/C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,iCAAiC,CAAC;AAGhD,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -10,8 +10,6 @@ export * from "./transport/http/upload-handler.js";
10
10
  export * from "./transport/http/static-file-handler.js";
11
11
  import { createProtocolWrapper } from "./protocol/protocol-wrapper.js";
12
12
  export * from "./services/orm-service.js";
13
- export * from "./services/crypto-service.js";
14
- export * from "./services/smtp-service.js";
15
13
  export * from "./services/auto-update-service.js";
16
14
  export * from "./utils/config-manager.js";
17
15
  export * from "./legacy/v1-auto-update-handler.js";
package/dist/index.js.map CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,8BAAqD;AAC9D,SAAS,2BAA+C;AAGxD,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,6BAAmD;AAG5D,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd,cAAc;",
4
+ "mappings": "AACA,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AAGd,SAAS,8BAAqD;AAC9D,SAAS,2BAA+C;AAGxD,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,6BAAmD;AAG5D,cAAc;AACd,cAAc;AAGd,cAAc;AAGd,cAAc;AAGd,cAAc;",
5
5
  "names": []
6
6
  }
@@ -78,62 +78,6 @@ const server = createServiceServer({
78
78
  | `encryptAes(data)` | `Promise<string>` | AES-256-CBC encryption. `data` is `Uint8Array`. Returns hex string in `iv:encrypted` format |
79
79
  | `decryptAes(encText)` | `Promise<Uint8Array>` | AES-256-CBC decryption. Returns original binary |
80
80
 
81
- ## SmtpService
82
-
83
- A nodemailer-based email sending service. Can pass SMTP config directly or reference server config file.
84
-
85
- ```typescript
86
- import { createServiceServer, SmtpService } from "@simplysm/service-server";
87
-
88
- const server = createServiceServer({
89
- port: 8080,
90
- rootPath: "/app/data",
91
- services: [SmtpService],
92
- });
93
- ```
94
-
95
- `.config.json` config (when using config reference method):
96
-
97
- ```json
98
- {
99
- "smtp": {
100
- "default": {
101
- "host": "smtp.example.com",
102
- "port": 587,
103
- "secure": false,
104
- "user": "user@example.com",
105
- "pass": "password",
106
- "senderName": "My App",
107
- "senderEmail": "noreply@example.com"
108
- }
109
- }
110
- }
111
- ```
112
-
113
- | Method | Returns | Description |
114
- |--------|---------|------|
115
- | `send(options)` | `Promise<string>` | Send email by directly passing SMTP config. Returns message ID |
116
- | `sendByConfig(configName, options)` | `Promise<string>` | Send email by referencing SMTP config in config file. Returns message ID |
117
-
118
- `send()` options:
119
-
120
- ```typescript
121
- interface SmtpSendOption {
122
- host: string;
123
- port?: number;
124
- secure?: boolean;
125
- user?: string;
126
- pass?: string;
127
- from: string;
128
- to: string;
129
- cc?: string;
130
- bcc?: string;
131
- subject: string;
132
- html: string;
133
- attachments?: SmtpSendAttachment[];
134
- }
135
- ```
136
-
137
81
  ## AutoUpdateService
138
82
 
139
83
  Supports auto-update for client apps. Searches for latest version files by platform in the client directory.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@simplysm/service-server",
3
3
  "sideEffects": false,
4
- "version": "13.0.13",
4
+ "version": "13.0.14",
5
5
  "description": "심플리즘 패키지 - 서비스 모듈 (server)",
6
6
  "author": "김석래",
7
7
  "repository": {
@@ -31,18 +31,16 @@
31
31
  "fastify": "^5.7.4",
32
32
  "jose": "^6.1.3",
33
33
  "mime": "^4.1.0",
34
- "nodemailer": "^8.0.1",
35
34
  "semver": "^7.7.4",
36
35
  "utf-8-validate": "^6.0.6",
37
36
  "ws": "^8.19.0",
38
- "@simplysm/core-common": "13.0.13",
39
- "@simplysm/core-node": "13.0.13",
40
- "@simplysm/orm-common": "13.0.13",
41
- "@simplysm/orm-node": "13.0.13",
42
- "@simplysm/service-common": "13.0.13"
37
+ "@simplysm/core-common": "13.0.14",
38
+ "@simplysm/core-node": "13.0.14",
39
+ "@simplysm/orm-common": "13.0.14",
40
+ "@simplysm/orm-node": "13.0.14",
41
+ "@simplysm/service-common": "13.0.14"
43
42
  },
44
43
  "devDependencies": {
45
- "@types/nodemailer": "^7.0.9",
46
44
  "@types/semver": "^7.7.1",
47
45
  "@types/ws": "^8.18.1"
48
46
  }
package/src/index.ts CHANGED
@@ -23,8 +23,6 @@ export { createProtocolWrapper, type ProtocolWrapper } from "./protocol/protocol
23
23
 
24
24
  // Services
25
25
  export * from "./services/orm-service";
26
- export * from "./services/crypto-service";
27
- export * from "./services/smtp-service";
28
26
  export * from "./services/auto-update-service";
29
27
 
30
28
  // Utils
@@ -1,9 +0,0 @@
1
- import type { Bytes } from "@simplysm/core-common";
2
- import { type ServiceMethods } from "../core/define-service";
3
- export declare const CryptoService: import("..").ServiceDefinition<{
4
- encrypt(data: string | Bytes): Promise<string>;
5
- encryptAes(data: Bytes): Promise<string>;
6
- decryptAes(encText: string): Promise<Bytes>;
7
- }>;
8
- export type CryptoServiceType = ServiceMethods<typeof CryptoService>;
9
- //# sourceMappingURL=crypto-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto-service.d.ts","sourceRoot":"","sources":["../../src/services/crypto-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAInD,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE5E,eAAO,MAAM,aAAa;kBACJ,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;qBAK7B,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;wBAUpB,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;EAWhD,CAAC;AAEJ,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC"}
@@ -1,29 +0,0 @@
1
- import { bytesConcat, bytesToHex, bytesFromHex } from "@simplysm/core-common";
2
- import crypto from "crypto";
3
- import { defineService } from "../core/define-service.js";
4
- const CryptoService = defineService("Crypto", (ctx) => ({
5
- async encrypt(data) {
6
- const config = await ctx.getConfig("crypto");
7
- return crypto.createHmac("sha256", config.key).update(data).digest("hex");
8
- },
9
- async encryptAes(data) {
10
- const config = await ctx.getConfig("crypto");
11
- const iv = crypto.randomBytes(16);
12
- const cipher = crypto.createCipheriv("aes-256-cbc", config.key, iv);
13
- const encrypted = cipher.update(data);
14
- return bytesToHex(iv) + ":" + bytesToHex(bytesConcat([encrypted, cipher.final()]));
15
- },
16
- async decryptAes(encText) {
17
- const config = await ctx.getConfig("crypto");
18
- const textParts = encText.split(":");
19
- const iv = bytesFromHex(textParts.shift());
20
- const encryptedText = bytesFromHex(textParts.join(":"));
21
- const decipher = crypto.createDecipheriv("aes-256-cbc", config.key, iv);
22
- const decrypted = decipher.update(encryptedText);
23
- return bytesConcat([decrypted, decipher.final()]);
24
- }
25
- }));
26
- export {
27
- CryptoService
28
- };
29
- //# sourceMappingURL=crypto-service.js.map
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/services/crypto-service.ts"],
4
- "mappings": "AACA,SAAS,aAAa,YAAY,oBAAoB;AAEtD,OAAO,YAAY;AACnB,SAAS,qBAA0C;AAE5C,MAAM,gBAAgB,cAAc,UAAU,CAAC,SAAS;AAAA,EAC7D,MAAM,QAAQ,MAAuC;AACnD,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AACzD,WAAO,OAAO,WAAW,UAAU,OAAO,GAAG,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EAC1E;AAAA,EAEA,MAAM,WAAW,MAA8B;AAC7C,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AAEzD,UAAM,KAAK,OAAO,YAAY,EAAE;AAChC,UAAM,SAAS,OAAO,eAAe,eAAe,OAAO,KAAK,EAAE;AAClE,UAAM,YAAY,OAAO,OAAO,IAAI;AAEpC,WAAO,WAAW,EAAE,IAAI,MAAM,WAAW,YAAY,CAAC,WAAW,OAAO,MAAM,CAAC,CAAC,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,WAAW,SAAiC;AAChD,UAAM,SAAS,MAAM,IAAI,UAAwB,QAAQ;AAEzD,UAAM,YAAY,QAAQ,MAAM,GAAG;AACnC,UAAM,KAAK,aAAa,UAAU,MAAM,CAAE;AAC1C,UAAM,gBAAgB,aAAa,UAAU,KAAK,GAAG,CAAC;AACtD,UAAM,WAAW,OAAO,iBAAiB,eAAe,OAAO,KAAK,EAAE;AACtE,UAAM,YAAY,SAAS,OAAO,aAAa;AAE/C,WAAO,YAAY,CAAC,WAAW,SAAS,MAAM,CAAC,CAAC;AAAA,EAClD;AACF,EAAE;",
5
- "names": []
6
- }
@@ -1,8 +0,0 @@
1
- import type { SmtpSendByConfigOption, SmtpSendOption } from "@simplysm/service-common";
2
- import { type ServiceMethods } from "../core/define-service";
3
- export declare const SmtpService: import("..").ServiceDefinition<{
4
- send: (options: SmtpSendOption) => Promise<string>;
5
- sendByConfig(configName: string, options: SmtpSendByConfigOption): Promise<string>;
6
- }>;
7
- export type SmtpServiceType = ServiceMethods<typeof SmtpService>;
8
- //# sourceMappingURL=smtp-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"smtp-service.d.ts","sourceRoot":"","sources":["../../src/services/smtp-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,sBAAsB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE5E,eAAO,MAAM,WAAW;oBACO,cAAc,KAAG,OAAO,CAAC,MAAM,CAAC;6BAkC5B,MAAM,WAAW,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;EAiB1F,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -1,50 +0,0 @@
1
- import nodemailer from "nodemailer";
2
- import { defineService } from "../core/define-service.js";
3
- const SmtpService = defineService("Smtp", (ctx) => {
4
- const send = async (options) => {
5
- const transport = nodemailer.createTransport({
6
- host: options.host,
7
- port: options.port,
8
- secure: options.secure,
9
- auth: options.user != null ? {
10
- user: options.user,
11
- pass: options.pass
12
- } : void 0,
13
- tls: {
14
- rejectUnauthorized: false
15
- }
16
- });
17
- const mailOptions = {
18
- ...options,
19
- attachments: options.attachments?.map((att) => ({
20
- ...att,
21
- // eslint-disable-next-line no-restricted-globals -- nodemailer 라이브러리 요구사항
22
- content: att.content != null ? Buffer.from(att.content) : void 0
23
- }))
24
- };
25
- const info = await transport.sendMail(mailOptions);
26
- return info.messageId;
27
- };
28
- return {
29
- send,
30
- async sendByConfig(configName, options) {
31
- const config = (await ctx.getConfig("smtp"))[configName];
32
- if (config == null) {
33
- throw new Error(`SMTP \uC124\uC815\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${configName}`);
34
- }
35
- return send({
36
- user: config.user,
37
- pass: config.pass,
38
- host: config.host,
39
- port: config.port,
40
- secure: config.secure,
41
- from: `"${config.senderName}" <${config.senderEmail ?? config.user}>`,
42
- ...options
43
- });
44
- }
45
- };
46
- });
47
- export {
48
- SmtpService
49
- };
50
- //# sourceMappingURL=smtp-service.js.map
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/services/smtp-service.ts"],
4
- "mappings": "AAAA,OAAO,gBAAgB;AAEvB,SAAS,qBAA0C;AAE5C,MAAM,cAAc,cAAc,QAAQ,CAAC,QAAQ;AACxD,QAAM,OAAO,OAAO,YAA6C;AAC/D,UAAM,YAAY,WAAW,gBAAgB;AAAA,MAC3C,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,MACE,QAAQ,QAAQ,OACZ;AAAA,QACE,MAAM,QAAQ;AAAA,QACd,MAAM,QAAQ;AAAA,MAChB,IACA;AAAA,MACN,KAAK;AAAA,QACH,oBAAoB;AAAA,MACtB;AAAA,IACF,CAAC;AAGD,UAAM,cAAc;AAAA,MAClB,GAAG;AAAA,MACH,aAAa,QAAQ,aAAa,IAAI,CAAC,SAAS;AAAA,QAC9C,GAAG;AAAA;AAAA,QAEH,SAAS,IAAI,WAAW,OAAO,OAAO,KAAK,IAAI,OAAO,IAAI;AAAA,MAC5D,EAAE;AAAA,IACJ;AAEA,UAAM,OAAO,MAAM,UAAU,SAAS,WAAW;AACjD,WAAO,KAAK;AAAA,EACd;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,MAAM,aAAa,YAAoB,SAAkD;AACvF,YAAM,UAAU,MAAM,IAAI,UAAkD,MAAM,GAAG,UAAU;AAC/F,UAAI,UAAU,MAAM;AAClB,cAAM,IAAI,MAAM,yEAAuB,UAAU,EAAE;AAAA,MACrD;AAEA,aAAO,KAAK;AAAA,QACV,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,QAAQ,OAAO;AAAA,QACf,MAAM,IAAI,OAAO,UAAU,MAAM,OAAO,eAAe,OAAO,IAAI;AAAA,QAClE,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;",
5
- "names": []
6
- }
@@ -1,36 +0,0 @@
1
- import type { Bytes } from "@simplysm/core-common";
2
- import { bytesConcat, bytesToHex, bytesFromHex } from "@simplysm/core-common";
3
- import type { CryptoConfig } from "@simplysm/service-common";
4
- import crypto from "crypto";
5
- import { defineService, type ServiceMethods } from "../core/define-service";
6
-
7
- export const CryptoService = defineService("Crypto", (ctx) => ({
8
- async encrypt(data: string | Bytes): Promise<string> {
9
- const config = await ctx.getConfig<CryptoConfig>("crypto");
10
- return crypto.createHmac("sha256", config.key).update(data).digest("hex");
11
- },
12
-
13
- async encryptAes(data: Bytes): Promise<string> {
14
- const config = await ctx.getConfig<CryptoConfig>("crypto");
15
-
16
- const iv = crypto.randomBytes(16);
17
- const cipher = crypto.createCipheriv("aes-256-cbc", config.key, iv);
18
- const encrypted = cipher.update(data);
19
-
20
- return bytesToHex(iv) + ":" + bytesToHex(bytesConcat([encrypted, cipher.final()]));
21
- },
22
-
23
- async decryptAes(encText: string): Promise<Bytes> {
24
- const config = await ctx.getConfig<CryptoConfig>("crypto");
25
-
26
- const textParts = encText.split(":");
27
- const iv = bytesFromHex(textParts.shift()!);
28
- const encryptedText = bytesFromHex(textParts.join(":"));
29
- const decipher = crypto.createDecipheriv("aes-256-cbc", config.key, iv);
30
- const decrypted = decipher.update(encryptedText);
31
-
32
- return bytesConcat([decrypted, decipher.final()]);
33
- },
34
- }));
35
-
36
- export type CryptoServiceType = ServiceMethods<typeof CryptoService>;
@@ -1,59 +0,0 @@
1
- import nodemailer from "nodemailer";
2
- import type { SmtpConfig, SmtpSendByConfigOption, SmtpSendOption } from "@simplysm/service-common";
3
- import { defineService, type ServiceMethods } from "../core/define-service";
4
-
5
- export const SmtpService = defineService("Smtp", (ctx) => {
6
- const send = async (options: SmtpSendOption): Promise<string> => {
7
- const transport = nodemailer.createTransport({
8
- host: options.host,
9
- port: options.port,
10
- secure: options.secure,
11
- auth:
12
- options.user != null
13
- ? {
14
- user: options.user,
15
- pass: options.pass,
16
- }
17
- : undefined,
18
- tls: {
19
- rejectUnauthorized: false,
20
- },
21
- });
22
-
23
- // nodemailer 타입 정의는 Buffer를 요구하지만, 실제로 Uint8Array도 작동함
24
- const mailOptions = {
25
- ...options,
26
- attachments: options.attachments?.map((att) => ({
27
- ...att,
28
- // eslint-disable-next-line no-restricted-globals -- nodemailer 라이브러리 요구사항
29
- content: att.content != null ? Buffer.from(att.content) : undefined,
30
- })),
31
- };
32
-
33
- const info = await transport.sendMail(mailOptions);
34
- return info.messageId;
35
- };
36
-
37
- return {
38
- send,
39
-
40
- async sendByConfig(configName: string, options: SmtpSendByConfigOption): Promise<string> {
41
- const config = (await ctx.getConfig<Record<string, SmtpConfig | undefined>>("smtp"))[configName];
42
- if (config == null) {
43
- throw new Error(`SMTP 설정을 찾을 수 없습니다: ${configName}`);
44
- }
45
-
46
- return send({
47
- user: config.user,
48
- pass: config.pass,
49
- host: config.host,
50
- port: config.port,
51
- secure: config.secure,
52
- from: `"${config.senderName}" <${config.senderEmail ?? config.user}>`,
53
- ...options,
54
- });
55
- },
56
- };
57
- });
58
-
59
- export type SmtpServiceType = ServiceMethods<typeof SmtpService>;