mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-08 04:36:13 +08:00
feat(server): allow customize mailer server (#5835)
This commit is contained in:
@@ -15,9 +15,9 @@ const {
|
|||||||
R2_SECRET_ACCESS_KEY,
|
R2_SECRET_ACCESS_KEY,
|
||||||
ENABLE_CAPTCHA,
|
ENABLE_CAPTCHA,
|
||||||
CAPTCHA_TURNSTILE_SECRET,
|
CAPTCHA_TURNSTILE_SECRET,
|
||||||
OAUTH_EMAIL_SENDER,
|
MAILER_SENDER,
|
||||||
OAUTH_EMAIL_LOGIN,
|
MAILER_USER,
|
||||||
OAUTH_EMAIL_PASSWORD,
|
MAILER_PASSWORD,
|
||||||
AFFINE_GOOGLE_CLIENT_ID,
|
AFFINE_GOOGLE_CLIENT_ID,
|
||||||
AFFINE_GOOGLE_CLIENT_SECRET,
|
AFFINE_GOOGLE_CLIENT_SECRET,
|
||||||
CLOUD_SQL_IAM_ACCOUNT,
|
CLOUD_SQL_IAM_ACCOUNT,
|
||||||
@@ -103,9 +103,9 @@ const createHelmCommand = ({ isDryRun }) => {
|
|||||||
`--set-string graphql.app.objectStorage.r2.accountId="${R2_ACCOUNT_ID}"`,
|
`--set-string graphql.app.objectStorage.r2.accountId="${R2_ACCOUNT_ID}"`,
|
||||||
`--set-string graphql.app.objectStorage.r2.accessKeyId="${R2_ACCESS_KEY_ID}"`,
|
`--set-string graphql.app.objectStorage.r2.accessKeyId="${R2_ACCESS_KEY_ID}"`,
|
||||||
`--set-string graphql.app.objectStorage.r2.secretAccessKey="${R2_SECRET_ACCESS_KEY}"`,
|
`--set-string graphql.app.objectStorage.r2.secretAccessKey="${R2_SECRET_ACCESS_KEY}"`,
|
||||||
`--set-string graphql.app.oauth.email.sender="${OAUTH_EMAIL_SENDER}"`,
|
`--set-string graphql.app.mailer.sender="${MAILER_SENDER}"`,
|
||||||
`--set-string graphql.app.oauth.email.login="${OAUTH_EMAIL_LOGIN}"`,
|
`--set-string graphql.app.mailer.user="${MAILER_USER}"`,
|
||||||
`--set-string graphql.app.oauth.email.password="${OAUTH_EMAIL_PASSWORD}"`,
|
`--set-string graphql.app.mailer.password="${MAILER_PASSWORD}"`,
|
||||||
`--set-string graphql.app.oauth.google.enabled=true`,
|
`--set-string graphql.app.oauth.google.enabled=true`,
|
||||||
`--set-string graphql.app.oauth.google.clientId="${AFFINE_GOOGLE_CLIENT_ID}"`,
|
`--set-string graphql.app.oauth.google.clientId="${AFFINE_GOOGLE_CLIENT_ID}"`,
|
||||||
`--set-string graphql.app.oauth.google.clientSecret="${AFFINE_GOOGLE_CLIENT_SECRET}"`,
|
`--set-string graphql.app.oauth.google.clientSecret="${AFFINE_GOOGLE_CLIENT_SECRET}"`,
|
||||||
|
|||||||
@@ -83,31 +83,33 @@ spec:
|
|||||||
value: "{{ .Values.app.captcha.enabled }}"
|
value: "{{ .Values.app.captcha.enabled }}"
|
||||||
- name: FEATURES_EARLY_ACCESS_PREVIEW
|
- name: FEATURES_EARLY_ACCESS_PREVIEW
|
||||||
value: "{{ .Values.app.features.earlyAccessPreview }}"
|
value: "{{ .Values.app.features.earlyAccessPreview }}"
|
||||||
- name: OAUTH_EMAIL_SENDER
|
- name: FEATURES_SYNC_CLIENT_VERSION_CHECK
|
||||||
|
value: "{{ .Values.app.features.syncClientVersionCheck }}"
|
||||||
|
- name: MAILER_HOST
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Values.app.oauth.email.secretName }}"
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
key: sender
|
key: host
|
||||||
- name: OAUTH_EMAIL_LOGIN
|
- name: MAILER_PORT
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Values.app.oauth.email.secretName }}"
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
key: login
|
|
||||||
- name: OAUTH_EMAIL_SERVER
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.app.oauth.email.secretName }}"
|
|
||||||
key: server
|
|
||||||
- name: OAUTH_EMAIL_PORT
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.app.oauth.email.secretName }}"
|
|
||||||
key: port
|
key: port
|
||||||
- name: OAUTH_EMAIL_PASSWORD
|
- name: MAILER_USER
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: "{{ .Values.app.oauth.email.secretName }}"
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: user
|
||||||
|
- name: MAILER_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
key: password
|
key: password
|
||||||
|
- name: MAILER_SENDER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: sender
|
||||||
- name: STRIPE_API_KEY
|
- name: STRIPE_API_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
|||||||
@@ -35,14 +35,7 @@ app:
|
|||||||
accountId: ''
|
accountId: ''
|
||||||
accessKeyId: ''
|
accessKeyId: ''
|
||||||
secretAccessKey: ''
|
secretAccessKey: ''
|
||||||
oauth:
|
oauth:
|
||||||
email:
|
|
||||||
secretName: 'oauth-email'
|
|
||||||
sender: 'noreply@toeverything.info'
|
|
||||||
login: ''
|
|
||||||
password: ''
|
|
||||||
server: 'smtp.gmail.com'
|
|
||||||
port: '465'
|
|
||||||
google:
|
google:
|
||||||
enabled: false
|
enabled: false
|
||||||
secretName: oauth-google
|
secretName: oauth-google
|
||||||
@@ -53,6 +46,13 @@ app:
|
|||||||
secretName: oauth-github
|
secretName: oauth-github
|
||||||
clientId: ''
|
clientId: ''
|
||||||
clientSecret: ''
|
clientSecret: ''
|
||||||
|
mailer:
|
||||||
|
secretName: 'mailer'
|
||||||
|
host: 'smtp.gmail.com'
|
||||||
|
port: '465'
|
||||||
|
user: ''
|
||||||
|
password: ''
|
||||||
|
sender: 'noreply@toeverything.info'
|
||||||
payment:
|
payment:
|
||||||
stripe:
|
stripe:
|
||||||
secretName: 'stripe'
|
secretName: 'stripe'
|
||||||
|
|||||||
@@ -448,7 +448,6 @@ jobs:
|
|||||||
${{ matrix.tests.script }}
|
${{ matrix.tests.script }}
|
||||||
env:
|
env:
|
||||||
DEV_SERVER_URL: http://localhost:8080
|
DEV_SERVER_URL: http://localhost:8080
|
||||||
ENABLE_LOCAL_EMAIL: true
|
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|||||||
@@ -275,9 +275,9 @@ jobs:
|
|||||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
ENABLE_CAPTCHA: true
|
ENABLE_CAPTCHA: true
|
||||||
CAPTCHA_TURNSTILE_SECRET: ${{ secrets.CAPTCHA_TURNSTILE_SECRET }}
|
CAPTCHA_TURNSTILE_SECRET: ${{ secrets.CAPTCHA_TURNSTILE_SECRET }}
|
||||||
OAUTH_EMAIL_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }}
|
MAILER_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }}
|
||||||
OAUTH_EMAIL_LOGIN: ${{ secrets.OAUTH_EMAIL_LOGIN }}
|
MAILER_USER: ${{ secrets.OAUTH_EMAIL_LOGIN }}
|
||||||
OAUTH_EMAIL_PASSWORD: ${{ secrets.OAUTH_EMAIL_PASSWORD }}
|
MAILER_PASSWORD: ${{ secrets.OAUTH_EMAIL_PASSWORD }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
||||||
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ You may need additional env for auth login. You may want to put your own one if
|
|||||||
For email login & password, please refer to https://nodemailer.com/usage/using-gmail/
|
For email login & password, please refer to https://nodemailer.com/usage/using-gmail/
|
||||||
|
|
||||||
```
|
```
|
||||||
OAUTH_EMAIL_SENDER=
|
MAILER_SENDER=
|
||||||
OAUTH_EMAIL_LOGIN=
|
MAILER_USER=
|
||||||
OAUTH_EMAIL_PASSWORD=
|
MAILER_PASSWORD=
|
||||||
OAUTH_GOOGLE_ENABLED="true"
|
OAUTH_GOOGLE_ENABLED="true"
|
||||||
OAUTH_GOOGLE_CLIENT_ID=
|
OAUTH_GOOGLE_CLIENT_ID=
|
||||||
OAUTH_GOOGLE_CLIENT_SECRET=
|
OAUTH_GOOGLE_CLIENT_SECRET=
|
||||||
|
|||||||
@@ -139,10 +139,11 @@
|
|||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"TS_NODE_PROJECT": "./tests/tsconfig.json",
|
"TS_NODE_PROJECT": "./tests/tsconfig.json",
|
||||||
"NODE_ENV": "test",
|
"NODE_ENV": "test",
|
||||||
"ENABLE_LOCAL_EMAIL": "true",
|
"MAILER_HOST": "0.0.0.0",
|
||||||
"OAUTH_EMAIL_LOGIN": "noreply@toeverything.info",
|
"MAILER_PORT": "1025",
|
||||||
"OAUTH_EMAIL_PASSWORD": "affine",
|
"MAILER_USER": "noreply@toeverything.info",
|
||||||
"OAUTH_EMAIL_SENDER": "noreply@toeverything.info",
|
"MAILER_PASSWORD": "affine",
|
||||||
|
"MAILER_SENDER": "noreply@toeverything.info",
|
||||||
"FEATURES_EARLY_ACCESS_PREVIEW": "false"
|
"FEATURES_EARLY_ACCESS_PREVIEW": "false"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ AFFiNE.ENV_MAP = {
|
|||||||
OAUTH_GITHUB_ENABLED: ['auth.oauthProviders.github.enabled', 'boolean'],
|
OAUTH_GITHUB_ENABLED: ['auth.oauthProviders.github.enabled', 'boolean'],
|
||||||
OAUTH_GITHUB_CLIENT_ID: 'auth.oauthProviders.github.clientId',
|
OAUTH_GITHUB_CLIENT_ID: 'auth.oauthProviders.github.clientId',
|
||||||
OAUTH_GITHUB_CLIENT_SECRET: 'auth.oauthProviders.github.clientSecret',
|
OAUTH_GITHUB_CLIENT_SECRET: 'auth.oauthProviders.github.clientSecret',
|
||||||
OAUTH_EMAIL_LOGIN: 'auth.email.login',
|
MAILER_HOST: 'mailer.host',
|
||||||
OAUTH_EMAIL_SENDER: 'auth.email.sender',
|
MAILER_PORT: ['mailer.port', 'int'],
|
||||||
OAUTH_EMAIL_SERVER: 'auth.email.server',
|
MAILER_USER: 'mailer.auth.user',
|
||||||
OAUTH_EMAIL_PORT: ['auth.email.port', 'int'],
|
MAILER_PASSWORD: 'mailer.auth.pass',
|
||||||
OAUTH_EMAIL_PASSWORD: 'auth.email.password',
|
MAILER_SENDER: 'mailer.from.address',
|
||||||
|
MAILER_SECURE: ['mailer.secure', 'boolean'],
|
||||||
THROTTLE_TTL: ['rateLimiter.ttl', 'int'],
|
THROTTLE_TTL: ['rateLimiter.ttl', 'int'],
|
||||||
THROTTLE_LIMIT: ['rateLimiter.limit', 'int'],
|
THROTTLE_LIMIT: ['rateLimiter.limit', 'int'],
|
||||||
REDIS_SERVER_HOST: 'plugins.redis.host',
|
REDIS_SERVER_HOST: 'plugins.redis.host',
|
||||||
@@ -30,7 +31,6 @@ AFFiNE.ENV_MAP = {
|
|||||||
'doc.manager.experimentalMergeWithYOcto',
|
'doc.manager.experimentalMergeWithYOcto',
|
||||||
'boolean',
|
'boolean',
|
||||||
],
|
],
|
||||||
ENABLE_LOCAL_EMAIL: ['auth.localEmail', 'boolean'],
|
|
||||||
STRIPE_API_KEY: 'plugins.payment.stripe.keys.APIKey',
|
STRIPE_API_KEY: 'plugins.payment.stripe.keys.APIKey',
|
||||||
STRIPE_WEBHOOK_KEY: 'plugins.payment.stripe.keys.webhookKey',
|
STRIPE_WEBHOOK_KEY: 'plugins.payment.stripe.keys.webhookKey',
|
||||||
FEATURES_EARLY_ACCESS_PREVIEW: ['featureFlags.earlyAccessPreview', 'boolean'],
|
FEATURES_EARLY_ACCESS_PREVIEW: ['featureFlags.earlyAccessPreview', 'boolean'],
|
||||||
|
|||||||
@@ -42,5 +42,13 @@ AFFiNE.plugins.use('redis');
|
|||||||
AFFiNE.plugins.use('payment');
|
AFFiNE.plugins.use('payment');
|
||||||
|
|
||||||
if (AFFiNE.deploy) {
|
if (AFFiNE.deploy) {
|
||||||
|
AFFiNE.mailer = {
|
||||||
|
service: 'gmail',
|
||||||
|
auth: {
|
||||||
|
user: env.MAILER_USER,
|
||||||
|
pass: env.MAILER_PASSWORD,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
AFFiNE.plugins.use('gcloud');
|
AFFiNE.plugins.use('gcloud');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,22 +115,7 @@ export const NextAuthOptionsProvider: FactoryProvider<NextAuthOptions> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const nextAuthOptions: NextAuthOptions = {
|
const nextAuthOptions: NextAuthOptions = {
|
||||||
providers: [
|
providers: [],
|
||||||
// @ts-expect-error esm interop issue
|
|
||||||
Email.default({
|
|
||||||
server: {
|
|
||||||
host: config.auth.email.server,
|
|
||||||
port: config.auth.email.port,
|
|
||||||
auth: {
|
|
||||||
user: config.auth.email.login,
|
|
||||||
pass: config.auth.email.password,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
from: config.auth.email.sender,
|
|
||||||
sendVerificationRequest: (params: SendVerificationRequestParams) =>
|
|
||||||
sendVerificationRequest(config, logger, mailer, session, params),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
adapter: prismaAdapter,
|
adapter: prismaAdapter,
|
||||||
debug: !config.node.prod,
|
debug: !config.node.prod,
|
||||||
session: {
|
session: {
|
||||||
@@ -156,6 +141,18 @@ export const NextAuthOptionsProvider: FactoryProvider<NextAuthOptions> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (config.mailer && mailer) {
|
||||||
|
nextAuthOptions.providers.push(
|
||||||
|
// @ts-expect-error esm interop issue
|
||||||
|
Email.default({
|
||||||
|
server: config.mailer,
|
||||||
|
from: config.mailer.from,
|
||||||
|
sendVerificationRequest: (params: SendVerificationRequestParams) =>
|
||||||
|
sendVerificationRequest(config, logger, mailer, session, params),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
nextAuthOptions.providers.push(
|
nextAuthOptions.providers.push(
|
||||||
// @ts-expect-error esm interop issue
|
// @ts-expect-error esm interop issue
|
||||||
Credentials.default({
|
Credentials.default({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { ApolloDriverConfig } from '@nestjs/apollo';
|
import type { ApolloDriverConfig } from '@nestjs/apollo';
|
||||||
|
import SMTPTransport from 'nodemailer/lib/smtp-transport';
|
||||||
|
|
||||||
import type { LeafPaths } from '../utils/types';
|
import type { LeafPaths } from '../utils/types';
|
||||||
import { EnvConfigType } from './env';
|
import { EnvConfigType } from './env';
|
||||||
@@ -263,18 +264,6 @@ export interface AFFiNEConfig {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
/**
|
|
||||||
* whether to use local email service to send email
|
|
||||||
* local debug only
|
|
||||||
*/
|
|
||||||
localEmail: boolean;
|
|
||||||
email: {
|
|
||||||
server: string;
|
|
||||||
port: number;
|
|
||||||
login: string;
|
|
||||||
sender: string;
|
|
||||||
password: string;
|
|
||||||
};
|
|
||||||
captcha: {
|
captcha: {
|
||||||
/**
|
/**
|
||||||
* whether to enable captcha
|
* whether to enable captcha
|
||||||
@@ -298,6 +287,13 @@ export interface AFFiNEConfig {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurations for mail service used to post auth or bussiness mails.
|
||||||
|
*
|
||||||
|
* @see https://nodemailer.com/smtp/
|
||||||
|
*/
|
||||||
|
mailer?: SMTPTransport.Options;
|
||||||
|
|
||||||
doc: {
|
doc: {
|
||||||
manager: {
|
manager: {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -166,14 +166,6 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
|||||||
return this.privateKey;
|
return this.privateKey;
|
||||||
},
|
},
|
||||||
oauthProviders: {},
|
oauthProviders: {},
|
||||||
localEmail: false,
|
|
||||||
email: {
|
|
||||||
server: 'smtp.gmail.com',
|
|
||||||
port: 465,
|
|
||||||
login: '',
|
|
||||||
sender: '',
|
|
||||||
password: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
storage: getDefaultAFFiNEStorageConfig(),
|
storage: getDefaultAFFiNEStorageConfig(),
|
||||||
rateLimiter: {
|
rateLimiter: {
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
import { Global, Module } from '@nestjs/common';
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { OptionalModule } from '../nestjs';
|
||||||
import { MailService } from './mail.service';
|
import { MailService } from './mail.service';
|
||||||
import { MAILER } from './mailer';
|
import { MAILER } from './mailer';
|
||||||
|
|
||||||
|
@Global()
|
||||||
|
@OptionalModule({
|
||||||
|
providers: [MAILER],
|
||||||
|
exports: [MAILER],
|
||||||
|
requires: ['mailer.auth.user', 'mailer.auth.pass'],
|
||||||
|
})
|
||||||
|
class MailerModule {}
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
providers: [MAILER, MailService],
|
imports: [MailerModule],
|
||||||
|
providers: [MailService],
|
||||||
exports: [MailService],
|
exports: [MailService],
|
||||||
})
|
})
|
||||||
export class MailModule {}
|
export class MailModule {}
|
||||||
|
|||||||
@@ -1,30 +1,28 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable, Optional } from '@nestjs/common';
|
||||||
|
|
||||||
import { Config } from '../config';
|
import { Config } from '../config';
|
||||||
import {
|
import { MAILER_SERVICE, type MailerService, type Options } from './mailer';
|
||||||
MAILER_SERVICE,
|
|
||||||
type MailerService,
|
|
||||||
type Options,
|
|
||||||
type Response,
|
|
||||||
} from './mailer';
|
|
||||||
import { emailTemplate } from './template';
|
import { emailTemplate } from './template';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MailService {
|
export class MailService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(MAILER_SERVICE) private readonly mailer: MailerService,
|
private readonly config: Config,
|
||||||
private readonly config: Config
|
@Optional() @Inject(MAILER_SERVICE) private readonly mailer?: MailerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async sendMail(options: Options): Promise<Response> {
|
async sendMail(options: Options) {
|
||||||
return this.mailer.sendMail(options);
|
if (!this.mailer) {
|
||||||
|
throw new Error('Mailer service is not configured.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.mailer.sendMail({
|
||||||
|
from: this.config.mailer?.from,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasConfigured() {
|
hasConfigured() {
|
||||||
return (
|
return !!this.mailer;
|
||||||
!!this.config.auth.email.login &&
|
|
||||||
!!this.config.auth.email.password &&
|
|
||||||
!!this.config.auth.email.sender
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendInviteEmail(
|
async sendInviteEmail(
|
||||||
@@ -80,7 +78,6 @@ export class MailService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `${invitationInfo.user.name} invited you to join ${invitationInfo.workspace.name}`,
|
subject: `${invitationInfo.user.name} invited you to join ${invitationInfo.workspace.name}`,
|
||||||
html,
|
html,
|
||||||
@@ -119,7 +116,6 @@ export class MailService {
|
|||||||
buttonUrl: url,
|
buttonUrl: url,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `Modify your AFFiNE password`,
|
subject: `Modify your AFFiNE password`,
|
||||||
html,
|
html,
|
||||||
@@ -135,7 +131,6 @@ export class MailService {
|
|||||||
buttonUrl: url,
|
buttonUrl: url,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `Set your AFFiNE password`,
|
subject: `Set your AFFiNE password`,
|
||||||
html,
|
html,
|
||||||
@@ -150,7 +145,6 @@ export class MailService {
|
|||||||
buttonUrl: url,
|
buttonUrl: url,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `Verify your current email for AFFiNE`,
|
subject: `Verify your current email for AFFiNE`,
|
||||||
html,
|
html,
|
||||||
@@ -165,7 +159,6 @@ export class MailService {
|
|||||||
buttonUrl: url,
|
buttonUrl: url,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `Verify your new email for AFFiNE`,
|
subject: `Verify your new email for AFFiNE`,
|
||||||
html,
|
html,
|
||||||
@@ -177,7 +170,6 @@ export class MailService {
|
|||||||
content: `As per your request, we have changed your email. Please make sure you're using ${to} when you log in the next time. `,
|
content: `As per your request, we have changed your email. Please make sure you're using ${to} when you log in the next time. `,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: `Your email has been changed`,
|
subject: `Your email has been changed`,
|
||||||
html,
|
html,
|
||||||
@@ -200,7 +192,6 @@ export class MailService {
|
|||||||
content: `${inviteeName} has joined ${workspaceName}`,
|
content: `${inviteeName} has joined ${workspaceName}`,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: title,
|
subject: title,
|
||||||
html,
|
html,
|
||||||
@@ -223,7 +214,6 @@ export class MailService {
|
|||||||
content: `${inviteeName} has left your workspace`,
|
content: `${inviteeName} has left your workspace`,
|
||||||
});
|
});
|
||||||
return this.sendMail({
|
return this.sendMail({
|
||||||
from: this.config.auth.email.sender,
|
|
||||||
to,
|
to,
|
||||||
subject: title,
|
subject: title,
|
||||||
html,
|
html,
|
||||||
|
|||||||
@@ -11,28 +11,11 @@ export type Response = SMTPTransport.SentMessageInfo;
|
|||||||
export type Options = SMTPTransport.Options;
|
export type Options = SMTPTransport.Options;
|
||||||
|
|
||||||
export const MAILER: FactoryProvider<
|
export const MAILER: FactoryProvider<
|
||||||
Transporter<SMTPTransport.SentMessageInfo>
|
Transporter<SMTPTransport.SentMessageInfo> | undefined
|
||||||
> = {
|
> = {
|
||||||
provide: MAILER_SERVICE,
|
provide: MAILER_SERVICE,
|
||||||
useFactory: (config: Config) => {
|
useFactory: (config: Config) => {
|
||||||
if (config.auth.localEmail) {
|
return config.mailer ? createTransport(config.mailer) : undefined;
|
||||||
return createTransport({
|
|
||||||
host: '0.0.0.0',
|
|
||||||
port: 1025,
|
|
||||||
secure: false,
|
|
||||||
auth: {
|
|
||||||
user: config.auth.email.login,
|
|
||||||
pass: config.auth.email.password,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return createTransport({
|
|
||||||
service: 'gmail',
|
|
||||||
auth: {
|
|
||||||
user: config.auth.email.login,
|
|
||||||
pass: config.auth.email.password,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
inject: [Config],
|
inject: [Config],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,11 +50,12 @@ const config: PlaywrightTestConfig = {
|
|||||||
DEBUG: 'affine:*',
|
DEBUG: 'affine:*',
|
||||||
FORCE_COLOR: 'true',
|
FORCE_COLOR: 'true',
|
||||||
DEBUG_COLORS: 'true',
|
DEBUG_COLORS: 'true',
|
||||||
ENABLE_LOCAL_EMAIL: process.env.ENABLE_LOCAL_EMAIL ?? 'true',
|
|
||||||
NEXTAUTH_URL: 'http://localhost:8080',
|
NEXTAUTH_URL: 'http://localhost:8080',
|
||||||
OAUTH_EMAIL_SENDER: 'noreply@toeverything.info',
|
MAILER_HOST: '0.0.0.0',
|
||||||
OAUTH_EMAIL_LOGIN: 'noreply@toeverything.info',
|
MAILER_PORT: '1025',
|
||||||
OAUTH_EMAIL_PASSWORD: 'affine',
|
MAILER_SENDER: 'noreply@toeverything.info',
|
||||||
|
MAILER_USER: 'noreply@toeverything.info',
|
||||||
|
MAILER_PASSWORD: 'affine',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ const config: PlaywrightTestConfig = {
|
|||||||
DEBUG: 'affine:*',
|
DEBUG: 'affine:*',
|
||||||
FORCE_COLOR: 'true',
|
FORCE_COLOR: 'true',
|
||||||
DEBUG_COLORS: 'true',
|
DEBUG_COLORS: 'true',
|
||||||
ENABLE_LOCAL_EMAIL: process.env.ENABLE_LOCAL_EMAIL ?? 'true',
|
|
||||||
NEXTAUTH_URL: 'http://localhost:8080',
|
NEXTAUTH_URL: 'http://localhost:8080',
|
||||||
OAUTH_EMAIL_SENDER: 'noreply@toeverything.info',
|
MAILER_SENDER: 'noreply@toeverything.info',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user