From c50db5c7d999caf54d524d0a640352dcdb281155 Mon Sep 17 00:00:00 2001 From: Tejas Mehta Date: Mon, 7 Oct 2024 21:20:50 -0400 Subject: [PATCH] fixes for sendgrid registeration methods (#123) --- packages/api-gateway/src/models/email.dto.ts | 50 +++++++++++++- .../src/modules/email/email.controller.ts | 22 ++++-- packages/api-gateway/test/email.e2e-spec.ts | 20 ++++++ packages/auth-service/test/app.e2e-spec.ts | 1 - .../src/modules/email/email.controller.ts | 1 + .../src/modules/email/email.service.ts | 67 +++++++++++++------ packages/email-service/test/app.e2e-spec.ts | 10 +++ packages/proto/definitions/email.proto | 6 ++ packages/proto/src/gen/email.ts | 6 ++ 9 files changed, 152 insertions(+), 31 deletions(-) diff --git a/packages/api-gateway/src/models/email.dto.ts b/packages/api-gateway/src/models/email.dto.ts index ca1bd04..c841c01 100644 --- a/packages/api-gateway/src/models/email.dto.ts +++ b/packages/api-gateway/src/models/email.dto.ts @@ -35,6 +35,54 @@ export class RegisterEmailModel { @IsOptional() @IsEmail() replyTo?: string; + + @ApiProperty({ + type: 'string', + description: + 'The nickname to assosicate with the sender (only visible in sendgrid)', + }) + @IsOptional() + nickname: string; + + @ApiProperty({ + type: 'string', + example: '123 Main St.', + description: 'The address to assosicate with the sender', + }) + @IsNotEmpty() + address: string; + + @ApiProperty({ + type: 'string', + example: 'Atlanta', + description: 'The city to assosicate with the sender', + }) + @IsNotEmpty() + city: string; + + @ApiProperty({ + type: 'string', + example: 'GA', + description: 'The state to assosicate with the sender', + }) + @IsNotEmpty() + state: string; + + @ApiProperty({ + type: 'string', + example: '30332', + description: 'The zip code to assosicate with the sender', + }) + @IsNotEmpty() + zip: string; + + @ApiProperty({ + type: 'string', + example: 'USA', + description: 'The country to assosicate with the sender', + }) + @IsNotEmpty() + country: string; } export class RegisterEmailResponse { @@ -249,7 +297,7 @@ export class RegisterDomainResponse { | EmailProto.AuthenticateDomainResponse | EmailProto.VerifyDomainResponse, ) { - this.id = res.id; + this.id = Number(res.id); this.valid = `${res.valid}`; this.records = new SendGridDNSResponse(res.records); this.statusCode = res.statusCode; diff --git a/packages/api-gateway/src/modules/email/email.controller.ts b/packages/api-gateway/src/modules/email/email.controller.ts index c7e2c6a..95c122c 100644 --- a/packages/api-gateway/src/modules/email/email.controller.ts +++ b/packages/api-gateway/src/modules/email/email.controller.ts @@ -94,6 +94,12 @@ export class EmailController implements OnModuleInit { replyTo: params.replyTo ?? params.email, configId: apiKey.project.id, configEnvironment: apiKey.environment, + nickname: params.nickname ?? params.name, + address: params.address, + city: params.city, + state: params.state, + zip: params.zip, + country: params.country, }), ); @@ -121,14 +127,16 @@ export class EmailController implements OnModuleInit { ); } - const res = this.emailService.authenticateDomain({ - domain: req.domain, - subdomain: req.subdomain, - configId: apiKey.project.id, - configEnvironment: apiKey.environment, - }); + const res = await lastValueFrom( + this.emailService.authenticateDomain({ + domain: req.domain, + subdomain: req.subdomain, + configId: apiKey.project.id, + configEnvironment: apiKey.environment, + }), + ); - return new RegisterDomainResponse(await lastValueFrom(res)); + return new RegisterDomainResponse(res); } @ApiOperation({ diff --git a/packages/api-gateway/test/email.e2e-spec.ts b/packages/api-gateway/test/email.e2e-spec.ts index fd72373..479b4f9 100644 --- a/packages/api-gateway/test/email.e2e-spec.ts +++ b/packages/api-gateway/test/email.e2e-spec.ts @@ -139,6 +139,11 @@ describe('Email Registration Routes', () => { .send({ email: 'invalidemail', // Malformed email name: 'name', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }) .expect(400); }); @@ -148,6 +153,11 @@ describe('Email Registration Routes', () => { .send({ email: 'validemail@example.com', name: 'name', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }) .expect(401); }); @@ -158,6 +168,11 @@ describe('Email Registration Routes', () => { .send({ email: 'validemail@example.com', name: 'name', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }) .expect(401); }); @@ -169,6 +184,11 @@ describe('Email Registration Routes', () => { .send({ email: 'validemail@example.com', name: 'name', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }) .expect(201); // Assuming the server responds with 201 Created on successful registration }); diff --git a/packages/auth-service/test/app.e2e-spec.ts b/packages/auth-service/test/app.e2e-spec.ts index 6f17cff..31887ee 100644 --- a/packages/auth-service/test/app.e2e-spec.ts +++ b/packages/auth-service/test/app.e2e-spec.ts @@ -496,7 +496,6 @@ describe('User authentication tests', () => { const res = await promise; res['id'] = Number(res['id']); - console.log(`res: ${JSON.stringify(res)}`); expect(res).toStrictEqual(correctUserResponse); }); }); diff --git a/packages/db-service/src/modules/email/email.controller.ts b/packages/db-service/src/modules/email/email.controller.ts index 7762c46..6e8ff91 100644 --- a/packages/db-service/src/modules/email/email.controller.ts +++ b/packages/db-service/src/modules/email/email.controller.ts @@ -240,6 +240,7 @@ export class EmailController implements EmailDbServiceController { }, }, }); + return { domain: emailDomain.domain, subdomain: emailDomain.subdomain, diff --git a/packages/email-service/src/modules/email/email.service.ts b/packages/email-service/src/modules/email/email.service.ts index 1cb26dc..f637947 100644 --- a/packages/email-service/src/modules/email/email.service.ts +++ b/packages/email-service/src/modules/email/email.service.ts @@ -5,16 +5,14 @@ import axios from 'axios'; import { ClientGrpc, RpcException } from '@nestjs/microservices'; import { lastValueFrom } from 'rxjs'; import { MailDataRequired } from '@sendgrid/mail'; +import { status } from '@grpc/grpc-js'; const { EMAIL_DB_SERVICE_NAME } = EmailProto; @Injectable() export class EmailService implements OnModuleInit { private emailService: EmailProto.EmailDbServiceClient; - constructor( - private sendgrid: SendGridService, - @Inject(EMAIL_DB_SERVICE_NAME) private emailClient: ClientGrpc, - ) {} + constructor(@Inject(EMAIL_DB_SERVICE_NAME) private emailClient: ClientGrpc) {} onModuleInit() { this.emailService = @@ -30,7 +28,10 @@ export class EmailService implements OnModuleInit { this.emailService.createEmailServiceConfig(request), ); if (!config) { - throw new RpcException('Failed to create email service config'); + throw new RpcException({ + code: status.INVALID_ARGUMENT, + message: 'Failed to create email service config', + }); } return { success: true, @@ -93,15 +94,21 @@ export class EmailService implements OnModuleInit { }, ); - const records: EmailProto.SendGridDnsRecords = response.data.dns; + const records: EmailProto.SendGridDnsRecords = { + dkim1: response.data.dns.dkim1, + dkim2: response.data.dns.dkim2, + mailCname: response.data.dns.mail_cname, + }; - this.emailService.createEmailDomain({ - domain: req.domain, - subdomain: req.subdomain, - sendgridId: response.data.id, - configId: req.configId, - configEnvironment: req.configEnvironment, - }); + // await lastValueFrom( + // this.emailService.createEmailDomain({ + // domain: req.domain, + // subdomain: req.subdomain, + // sendgridId: response.data.id, + // configId: req.configId, + // configEnvironment: req.configEnvironment, + // }), + // ); return { statusCode: response.status, @@ -110,8 +117,13 @@ export class EmailService implements OnModuleInit { records, }; } catch (error) { - console.error('Error registering domain:', error); - throw new RpcException('Failed to register domain'); + if (error instanceof RpcException) { + throw error; + } + throw new RpcException({ + code: status.INVALID_ARGUMENT, + message: JSON.stringify(error), + }); } } @@ -143,7 +155,10 @@ export class EmailService implements OnModuleInit { }; await sendgrid.send(data); } catch (err) { - throw new RpcException(JSON.stringify(err)); + throw new RpcException({ + code: status.INVALID_ARGUMENT, + message: JSON.stringify(err), + }); } } } @@ -183,13 +198,20 @@ export class EmailService implements OnModuleInit { message: 'test register success', }; } + try { const res = await axios.post( sendgridUrl, { - fromEmail: req.fromEmail, - fromName: req.fromName, - replyTo: req.replyTo, + nickname: req.nickname ?? req.fromName, + from_email: req.fromEmail, + from_name: req.fromName, + reply_to: req.replyTo, + address: req.address, + city: req.city, + state: req.state, + zip: req.zip, + country: req.country, }, { headers: { @@ -204,8 +226,10 @@ export class EmailService implements OnModuleInit { message: 'Sender registered successfully', }; } catch (err) { - console.error('error registering sender:', err); - throw new RpcException('Unable to register sender'); + throw new RpcException({ + code: status.INVALID_ARGUMENT, + message: JSON.stringify(err), + }); } } @@ -263,7 +287,6 @@ export class EmailService implements OnModuleInit { records, }; } catch (error) { - console.error('Error registering domain:', error); throw new RpcException('Failed to register domain'); } } diff --git a/packages/email-service/test/app.e2e-spec.ts b/packages/email-service/test/app.e2e-spec.ts index 37966dd..44e0bce 100644 --- a/packages/email-service/test/app.e2e-spec.ts +++ b/packages/email-service/test/app.e2e-spec.ts @@ -77,6 +77,11 @@ describe('Email Service Sender Registration Tests', () => { replyTo: 'example@example.com', configId: 0, configEnvironment: 'prod', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }, (err: any, response: EmailProto.RegisterSenderResponse) => { if (err) { @@ -102,6 +107,11 @@ describe('Email Service Sender Registration Tests', () => { replyTo: '', configId: 0, configEnvironment: 'prod', + address: 'address', + city: 'city', + state: 'state', + country: 'country', + zip: 'zip', }, (err: any, response: EmailProto.RegisterSenderResponse) => { if (err) { diff --git a/packages/proto/definitions/email.proto b/packages/proto/definitions/email.proto index cea27f5..9b8ef42 100644 --- a/packages/proto/definitions/email.proto +++ b/packages/proto/definitions/email.proto @@ -90,6 +90,12 @@ message RegisterSenderRequest { string reply_to = 3; int64 configId = 4; string configEnvironment = 5; + string nickname = 6; + string address = 7; + string city = 8; + string state = 9; + string country = 10; + string zip = 11; } message RegisterSenderResponse { diff --git a/packages/proto/src/gen/email.ts b/packages/proto/src/gen/email.ts index e85e96c..42b0811 100644 --- a/packages/proto/src/gen/email.ts +++ b/packages/proto/src/gen/email.ts @@ -81,6 +81,12 @@ export interface RegisterSenderRequest { replyTo: string; configId: number; configEnvironment: string; + nickname: string; + address: string; + city: string; + state: string; + country: string; + zip: string; } export interface RegisterSenderResponse {