mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 23:45:21 +02:00
noop if no provider or api key
This commit is contained in:
parent
118b2d037e
commit
f712d939a4
9 changed files with 41 additions and 27 deletions
10
.env.example
10
.env.example
|
@ -44,11 +44,13 @@ NX_TELLER_ENV=sandbox
|
||||||
# EMAIL
|
# EMAIL
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
# We use Postmark for transactional emails. You can sign up for a free account
|
# We currently support Postmark for transactional emails. You can sign up for a free account
|
||||||
# and get a free API key at https://postmarkapp.com
|
# and get a free API key at https://postmarkapp.com
|
||||||
NX_POSTMARK_FROM_ADDRESS=account@example.com
|
NX_EMAIL_FROM_ADDRESS=account@example.com
|
||||||
NX_POSTMARK_REPLY_TO_ADDRESS=support@example.com
|
NX_EMAIL_REPLY_TO_ADDRESS=support@example.com
|
||||||
NX_POSTMARK_API_TOKEN=
|
NX_EMAIL_PROVIDER=
|
||||||
|
NX_EMAIL_PROVIDER_API_TOKEN=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
|
@ -37,7 +37,7 @@ And dozens upon dozens of smaller features.
|
||||||
|
|
||||||
This is the current state of building the app. We're actively working to make this process much more streamlined!
|
This is the current state of building the app. We're actively working to make this process much more streamlined!
|
||||||
|
|
||||||
*You'll need Docker installed to run the app locally.*
|
_You'll need Docker installed to run the app locally._
|
||||||
[Docker Desktop](https://www.docker.com/products/docker-desktop/) is an easy way to get started.
|
[Docker Desktop](https://www.docker.com/products/docker-desktop/) is an easy way to get started.
|
||||||
|
|
||||||
First, copy the `.env.example` file to `.env`:
|
First, copy the `.env.example` file to `.env`:
|
||||||
|
@ -48,7 +48,7 @@ cp .env.example .env
|
||||||
|
|
||||||
Then, create a new secret using `openssl rand -base64 32` and populate `NEXTAUTH_SECRET` in your `.env` file with it.
|
Then, create a new secret using `openssl rand -base64 32` and populate `NEXTAUTH_SECRET` in your `.env` file with it.
|
||||||
|
|
||||||
To enable transactional emails, you'll need to create a [Postmark](https://postmarkapp.com/) account and add your API key to your `.env` file (`NX_POSTMARK_API_TOKEN`). You can also set the from and reply-to email addresses (`NX_POSTMARK_FROM_ADDRESS` and `NX_POSTMARK_REPLY_TO_ADDRESS`). If you want to run the app without email, you can set `NX_POSTMARK_API_TOKEN` to a dummy value.
|
To enable transactional emails, you'll need to create a [Postmark](https://postmarkapp.com/) account and add your API key to your `.env` file (`NX_EMAIL_PROVIDER_API_TOKEN`) and set `NX_EMAIL_PROVIDER` to `postmark`. You can also set the from and reply-to email addresses (`NX_EMAIL_FROM_ADDRESS` and `NX_EMAIL_REPLY_TO_ADDRESS`). If you want to run the app without email, you can set `NX_EMAIL_PROVIDER_API_TOKEN` to a dummy value.
|
||||||
|
|
||||||
Maybe uses [Teller](https://teller.io/) for connecting financial accounts. To get started with Teller, you'll need to create an account. Once you've created an account:
|
Maybe uses [Teller](https://teller.io/) for connecting financial accounts. To get started with Teller, you'll need to create an account. Once you've created an account:
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { ServerClient as PostmarkServerClient } from 'postmark'
|
||||||
import env from '../../env'
|
import env from '../../env'
|
||||||
|
|
||||||
export function initializeEmailClient() {
|
export function initializeEmailClient() {
|
||||||
switch (process.env.NX_EMAIL_PROVIDER) {
|
switch (env.NX_EMAIL_PROVIDER) {
|
||||||
case 'postmark':
|
case 'postmark':
|
||||||
if (env.NX_EMAIL_PROVIDER_API_TOKEN) {
|
if (env.NX_EMAIL_PROVIDER_API_TOKEN) {
|
||||||
return new PostmarkServerClient(env.NX_EMAIL_PROVIDER_API_TOKEN)
|
return new PostmarkServerClient(env.NX_EMAIL_PROVIDER_API_TOKEN)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Missing Postmark API token')
|
return undefined
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid email provider')
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ router.get(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Implement verification email using Postmark instead of Auth0
|
// TODO: Implement verification email using internal email service instead of Auth0
|
||||||
router.post(
|
router.post(
|
||||||
'/resend-verification-email',
|
'/resend-verification-email',
|
||||||
endpoint.create({
|
endpoint.create({
|
||||||
|
|
|
@ -68,6 +68,7 @@ const envSchema = z.object({
|
||||||
|
|
||||||
NX_EMAIL_FROM_ADDRESS: z.string().default('account@maybe.co'),
|
NX_EMAIL_FROM_ADDRESS: z.string().default('account@maybe.co'),
|
||||||
NX_EMAIL_REPLY_TO_ADDRESS: z.string().default('support@maybe.co'),
|
NX_EMAIL_REPLY_TO_ADDRESS: z.string().default('support@maybe.co'),
|
||||||
|
NX_EMAIL_PROVIDER: z.string().optional(),
|
||||||
NX_EMAIL_PROVIDER_API_TOKEN: z.string().optional(),
|
NX_EMAIL_PROVIDER_API_TOKEN: z.string().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { ServerClient as PostmarkServerClient } from 'postmark'
|
||||||
import env from '../../env'
|
import env from '../../env'
|
||||||
|
|
||||||
export function initializeEmailClient() {
|
export function initializeEmailClient() {
|
||||||
switch (process.env.NX_EMAIL_PROVIDER) {
|
switch (env.NX_EMAIL_PROVIDER) {
|
||||||
case 'postmark':
|
case 'postmark':
|
||||||
if (env.NX_EMAIL_PROVIDER_API_TOKEN) {
|
if (env.NX_EMAIL_PROVIDER_API_TOKEN) {
|
||||||
return new PostmarkServerClient(env.NX_EMAIL_PROVIDER_API_TOKEN)
|
return new PostmarkServerClient(env.NX_EMAIL_PROVIDER_API_TOKEN)
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Missing Postmark API token')
|
return undefined
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid email provider')
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,9 @@ const envSchema = z.object({
|
||||||
|
|
||||||
NX_EMAIL_FROM_ADDRESS: z.string().default('account@maybe.co'),
|
NX_EMAIL_FROM_ADDRESS: z.string().default('account@maybe.co'),
|
||||||
NX_EMAIL_REPLY_TO_ADDRESS: z.string().default('support@maybe.co'),
|
NX_EMAIL_REPLY_TO_ADDRESS: z.string().default('support@maybe.co'),
|
||||||
|
NX_EMAIL_PROVIDER: z.string().optional(),
|
||||||
NX_EMAIL_PROVIDER_API_TOKEN: z.string().optional(),
|
NX_EMAIL_PROVIDER_API_TOKEN: z.string().optional(),
|
||||||
|
|
||||||
NX_STRIPE_SECRET_KEY: z.string().default('sk_test_REPLACE_THIS'),
|
NX_STRIPE_SECRET_KEY: z.string().default('sk_test_REPLACE_THIS'),
|
||||||
|
|
||||||
NX_CDN_PRIVATE_BUCKET: z.string().default('REPLACE_THIS'),
|
NX_CDN_PRIVATE_BUCKET: z.string().default('REPLACE_THIS'),
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import type { Logger } from 'winston'
|
import type { Logger } from 'winston'
|
||||||
import type { ServerClient as PostmarkServerClient } from 'postmark'
|
import type { ServerClient as PostmarkServerClient } from 'postmark'
|
||||||
import type { MessageSendingResponse } from 'postmark/dist/client/models'
|
import { PostmarkEmailProvider } from './providers'
|
||||||
import type { SharedType } from '@maybe-finance/shared'
|
import type { SharedType } from '@maybe-finance/shared'
|
||||||
|
|
||||||
import { PostmarkEmailProvider } from './providers/postmark.provider'
|
|
||||||
|
|
||||||
export interface IEmailProvider {
|
export interface IEmailProvider {
|
||||||
send(messages: SharedType.PlainEmailMessage): Promise<SharedType.EmailSendingResponse>
|
send(messages: SharedType.PlainEmailMessage): Promise<SharedType.EmailSendingResponse>
|
||||||
send(messages: SharedType.PlainEmailMessage[]): Promise<SharedType.EmailSendingResponse[]>
|
send(messages: SharedType.PlainEmailMessage[]): Promise<SharedType.EmailSendingResponse[]>
|
||||||
|
@ -23,13 +21,13 @@ export interface IEmailProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EmailService implements IEmailProvider {
|
export class EmailService implements IEmailProvider {
|
||||||
private emailProvider: IEmailProvider
|
private emailProvider: IEmailProvider | undefined
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
private readonly client: PostmarkServerClient | undefined,
|
private readonly client: PostmarkServerClient | undefined,
|
||||||
private readonly defaultAddresses: { from: string; replyTo?: string }
|
private readonly defaultAddresses: { from: string; replyTo?: string }
|
||||||
) {
|
) {
|
||||||
const provider = process.env.EMAIL_PROVIDER
|
const provider = process.env.NX_EMAIL_PROVIDER
|
||||||
|
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case 'postmark':
|
case 'postmark':
|
||||||
|
@ -40,7 +38,7 @@ export class EmailService implements IEmailProvider {
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error('Unsupported email provider')
|
undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,24 +47,34 @@ export class EmailService implements IEmailProvider {
|
||||||
*
|
*
|
||||||
* @returns success boolean(s)
|
* @returns success boolean(s)
|
||||||
*/
|
*/
|
||||||
send(messages: SharedType.PlainEmailMessage): Promise<any>
|
async send(messages: SharedType.PlainEmailMessage): Promise<SharedType.EmailSendingResponse>
|
||||||
send(messages: SharedType.PlainEmailMessage[]): Promise<any[]>
|
async send(messages: SharedType.PlainEmailMessage[]): Promise<SharedType.EmailSendingResponse[]>
|
||||||
send(
|
async send(
|
||||||
messages: SharedType.PlainEmailMessage | SharedType.PlainEmailMessage[]
|
messages: SharedType.PlainEmailMessage | SharedType.PlainEmailMessage[]
|
||||||
): Promise<any | any[]> {
|
): Promise<SharedType.EmailSendingResponse | SharedType.EmailSendingResponse[]> {
|
||||||
return this.emailProvider.send(messages)
|
if (!this.emailProvider || !this.client) {
|
||||||
|
//no-op
|
||||||
|
return undefined as unknown as SharedType.EmailSendingResponse
|
||||||
|
}
|
||||||
|
return await this.emailProvider.send(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends template email(s)
|
* Sends template email(s)
|
||||||
*/
|
*/
|
||||||
async sendTemplate(messages: SharedType.TemplateEmailMessage): Promise<MessageSendingResponse>
|
async sendTemplate(
|
||||||
|
messages: SharedType.TemplateEmailMessage
|
||||||
|
): Promise<SharedType.EmailSendingResponse>
|
||||||
async sendTemplate(
|
async sendTemplate(
|
||||||
messages: SharedType.TemplateEmailMessage[]
|
messages: SharedType.TemplateEmailMessage[]
|
||||||
): Promise<MessageSendingResponse[]>
|
): Promise<SharedType.EmailSendingResponse[]>
|
||||||
async sendTemplate(
|
async sendTemplate(
|
||||||
messages: SharedType.TemplateEmailMessage | SharedType.TemplateEmailMessage[]
|
messages: SharedType.TemplateEmailMessage | SharedType.TemplateEmailMessage[]
|
||||||
): Promise<MessageSendingResponse | MessageSendingResponse[]> {
|
): Promise<SharedType.EmailSendingResponse | SharedType.EmailSendingResponse[]> {
|
||||||
|
if (!this.emailProvider || !this.client) {
|
||||||
|
//no-op
|
||||||
|
return undefined as unknown as SharedType.EmailSendingResponse
|
||||||
|
}
|
||||||
return this.emailProvider.sendTemplate(messages)
|
return this.emailProvider.sendTemplate(messages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
libs/server/features/src/email/providers/index.ts
Normal file
1
libs/server/features/src/email/providers/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './postmark.provider'
|
Loading…
Add table
Add a link
Reference in a new issue